KoD 0.8
- tanti miglioramenti sotto il cofano, supporto iniziale al futuro kodi 19 - Nuova modalità di visualizzazione per episodio successivo - fixato wstream tramite l'aggiunta della finestra per risolvere il reCaptcha - aggiunta sezione segnala un problema in Aiuto - altri fix e migliorie varie a canali e server
This commit is contained in:
+68
-97
@@ -3,10 +3,9 @@
|
||||
# channeltools - Herramientas para trabajar con canales
|
||||
# ------------------------------------------------------------
|
||||
|
||||
import os
|
||||
|
||||
import jsontools
|
||||
from __future__ import absolute_import
|
||||
|
||||
from core import jsontools
|
||||
from platformcode import config, logger
|
||||
|
||||
DEFAULT_UPDATE_URL = "/channels/"
|
||||
@@ -14,6 +13,7 @@ dict_channels_parameters = dict()
|
||||
|
||||
remote_path = 'https://raw.githubusercontent.com/kodiondemand/media/master/'
|
||||
|
||||
|
||||
def is_adult(channel_name):
|
||||
logger.info("channel_name=" + channel_name)
|
||||
channel_parameters = get_channel_parameters(channel_name)
|
||||
@@ -27,6 +27,7 @@ def is_enabled(channel_name):
|
||||
|
||||
|
||||
def get_channel_parameters(channel_name):
|
||||
from core import filetools
|
||||
global dict_channels_parameters
|
||||
|
||||
if channel_name not in dict_channels_parameters:
|
||||
@@ -35,20 +36,22 @@ def get_channel_parameters(channel_name):
|
||||
# logger.debug(channel_parameters)
|
||||
if channel_parameters:
|
||||
# cambios de nombres y valores por defecto
|
||||
channel_parameters["title"] = channel_parameters.pop("name") + (' [DEPRECATED]' if channel_parameters.has_key('deprecated') and channel_parameters['deprecated'] else '')
|
||||
channel_parameters["title"] = channel_parameters.pop("name") + (' [DEPRECATED]' if 'deprecated' in channel_parameters and channel_parameters['deprecated'] else '')
|
||||
channel_parameters["channel"] = channel_parameters.pop("id")
|
||||
|
||||
# si no existe el key se declaran valor por defecto para que no de fallos en las funciones que lo llaman
|
||||
channel_parameters["adult"] = channel_parameters.get("adult", False)
|
||||
logger.info(channel_parameters["adult"])
|
||||
if channel_parameters["adult"]:
|
||||
channel_parameters["update_url"] = channel_parameters.get("update_url", DEFAULT_UPDATE_URL+'porn/')
|
||||
channel_parameters["update_url"] = channel_parameters.get("update_url",
|
||||
DEFAULT_UPDATE_URL + 'porn/')
|
||||
else:
|
||||
channel_parameters["update_url"] = channel_parameters.get("update_url", DEFAULT_UPDATE_URL)
|
||||
channel_parameters["language"] = channel_parameters.get("language", ["all"])
|
||||
## channel_parameters["adult"] = channel_parameters.get("adult", False)
|
||||
## channel_parameters["adult"] = channel_parameters.get("adult", False)
|
||||
channel_parameters["active"] = channel_parameters.get("active", False)
|
||||
channel_parameters["include_in_global_search"] = channel_parameters.get("include_in_global_search", False)
|
||||
channel_parameters["include_in_global_search"] = channel_parameters.get("include_in_global_search",
|
||||
False)
|
||||
channel_parameters["categories"] = channel_parameters.get("categories", list())
|
||||
|
||||
channel_parameters["thumbnail"] = channel_parameters.get("thumbnail", "")
|
||||
@@ -57,57 +60,27 @@ def get_channel_parameters(channel_name):
|
||||
|
||||
# Imagenes: se admiten url y archivos locales dentro de "resources/images"
|
||||
if channel_parameters.get("thumbnail") and "://" not in channel_parameters["thumbnail"]:
|
||||
channel_parameters["thumbnail"] = os.path.join(remote_path, 'resources', "thumb", channel_parameters["thumbnail"])
|
||||
channel_parameters["thumbnail"] = filetools.join(remote_path, "resources", "thumb", channel_parameters["thumbnail"])
|
||||
if channel_parameters.get("banner") and "://" not in channel_parameters["banner"]:
|
||||
channel_parameters["banner"] = os.path.join(remote_path, 'resources', "banner", channel_parameters["banner"])
|
||||
channel_parameters["banner"] = filetools.join(remote_path, "resources", "banner", channel_parameters["banner"])
|
||||
if channel_parameters.get("fanart") and "://" not in channel_parameters["fanart"]:
|
||||
channel_parameters["fanart"] = os.path.join(remote_path, 'resources', "fanart", channel_parameters["fanart"])
|
||||
channel_parameters["fanart"] = filetools.join(remote_path, "resources", channel_parameters["fanart"])
|
||||
|
||||
# Obtenemos si el canal tiene opciones de configuración
|
||||
channel_parameters["has_settings"] = False
|
||||
if 'settings' in channel_parameters:
|
||||
# if not isinstance(channel_parameters['settings'], list):
|
||||
# channel_parameters['settings'] = [channel_parameters['settings']]
|
||||
|
||||
# if "include_in_global_search" in channel_parameters['settings']:
|
||||
# channel_parameters["include_in_global_search"] = channel_parameters['settings']
|
||||
# ["include_in_global_search"].get('default', False)
|
||||
#
|
||||
# found = False
|
||||
# for el in channel_parameters['settings']:
|
||||
# for key in el.items():
|
||||
# if 'include_in' not in key:
|
||||
# channel_parameters["has_settings"] = True
|
||||
# found = True
|
||||
# break
|
||||
# if found:
|
||||
# break
|
||||
channel_parameters['settings'] = get_default_settings(channel_name)
|
||||
for s in channel_parameters['settings']:
|
||||
if 'id' in s:
|
||||
if s['id'] == "include_in_global_search":
|
||||
channel_parameters["include_in_global_search"] = True
|
||||
elif s['id'] == "filter_languages":
|
||||
channel_parameters["filter_languages"] = s.get('lvalues',[])
|
||||
channel_parameters["filter_languages"] = s.get('lvalues', [])
|
||||
elif s['id'].startswith("include_in_"):
|
||||
channel_parameters["has_settings"] = True
|
||||
|
||||
del channel_parameters['settings']
|
||||
|
||||
# Compatibilidad
|
||||
if 'compatible' in channel_parameters:
|
||||
# compatible python
|
||||
python_compatible = True
|
||||
if 'python' in channel_parameters["compatible"]:
|
||||
import sys
|
||||
python_condition = channel_parameters["compatible"]['python']
|
||||
if sys.version_info < tuple(map(int, (python_condition.split(".")))):
|
||||
python_compatible = False
|
||||
|
||||
channel_parameters["compatible"] = python_compatible
|
||||
else:
|
||||
channel_parameters["compatible"] = True
|
||||
|
||||
dict_channels_parameters[channel_name] = channel_parameters
|
||||
|
||||
else:
|
||||
@@ -115,13 +88,12 @@ def get_channel_parameters(channel_name):
|
||||
# lanzamos la excepcion y asi tenemos los valores básicos
|
||||
raise Exception
|
||||
|
||||
except Exception, ex:
|
||||
except Exception as ex:
|
||||
logger.error(channel_name + ".json error \n%s" % ex)
|
||||
channel_parameters = dict()
|
||||
channel_parameters["channel"] = ""
|
||||
channel_parameters["adult"] = False
|
||||
channel_parameters['active'] = False
|
||||
channel_parameters["compatible"] = True
|
||||
channel_parameters["language"] = ""
|
||||
channel_parameters["update_url"] = DEFAULT_UPDATE_URL
|
||||
return channel_parameters
|
||||
@@ -131,25 +103,26 @@ def get_channel_parameters(channel_name):
|
||||
|
||||
def get_channel_json(channel_name):
|
||||
# logger.info("channel_name=" + channel_name)
|
||||
import filetools
|
||||
from core import filetools
|
||||
channel_json = None
|
||||
try:
|
||||
channel_path = filetools.join(config.get_runtime_path(), "channels", channel_name + ".json")
|
||||
if not os.path.isfile(channel_path):
|
||||
if not filetools.isfile(channel_path):
|
||||
channel_path = filetools.join(config.get_runtime_path(), 'channels', "porn", channel_name + ".json")
|
||||
if not os.path.isfile(channel_path):
|
||||
if not filetools.isfile(channel_path):
|
||||
channel_path = filetools.join(config.get_runtime_path(), "specials", channel_name + ".json")
|
||||
if not os.path.isfile(channel_path):
|
||||
if not filetools.isfile(channel_path):
|
||||
channel_path = filetools.join(config.get_runtime_path(), "servers", channel_name + ".json")
|
||||
if not os.path.isfile(channel_path):
|
||||
channel_path = filetools.join(config.get_runtime_path(), "servers", "debriders", channel_name + ".json")
|
||||
if not filetools.isfile(channel_path):
|
||||
channel_path = filetools.join(config.get_runtime_path(), "servers", "debriders",
|
||||
channel_name + ".json")
|
||||
|
||||
if filetools.isfile(channel_path):
|
||||
# logger.info("channel_data=" + channel_path)
|
||||
channel_json = jsontools.load(filetools.read(channel_path))
|
||||
# logger.info("channel_json= %s" % channel_json)
|
||||
|
||||
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(" %s" % message)
|
||||
@@ -174,6 +147,7 @@ def get_channel_controls_settings(channel_name):
|
||||
|
||||
return list_controls, dict_settings
|
||||
|
||||
|
||||
def get_lang(channel_name):
|
||||
channel = __import__('channels.%s' % channel_name, fromlist=["channels.%s" % channel_name])
|
||||
list_language = [config.get_localized_string(70522)]
|
||||
@@ -199,16 +173,17 @@ def get_lang(channel_name):
|
||||
list_language.append(lang)
|
||||
return list_language
|
||||
|
||||
|
||||
def get_default_settings(channel_name):
|
||||
import filetools
|
||||
from core import filetools
|
||||
default_path = filetools.join(config.get_runtime_path(), 'default_channel_settings' + '.json')
|
||||
default_file = jsontools.load(filetools.read(default_path))
|
||||
|
||||
channel_path = filetools.join(config.get_runtime_path(),'channels',channel_name + '.json')
|
||||
adult_path = filetools.join(config.get_runtime_path(),'channels', 'porn', channel_name + '.json')
|
||||
channel_path = filetools.join(config.get_runtime_path(), 'channels', channel_name + '.json')
|
||||
adult_path = filetools.join(config.get_runtime_path(), 'channels', 'porn', channel_name + '.json')
|
||||
|
||||
# from core.support import dbg; dbg()
|
||||
if os.path.exists(channel_path) or os.path.exists(adult_path):
|
||||
if filetools.exists(channel_path) or filetools.exists(adult_path):
|
||||
default_controls = default_file['settings']
|
||||
default_controls_renumber = default_file['renumber']
|
||||
channel_json = get_channel_json(channel_name)
|
||||
@@ -217,33 +192,43 @@ def get_default_settings(channel_name):
|
||||
channel_language = channel_json['language']
|
||||
channel_controls = channel_json['settings']
|
||||
categories = channel_json['categories']
|
||||
not_active = channel_json['not_active'] if channel_json.has_key('not_active') else []
|
||||
default_off = channel_json['default_off'] if channel_json.has_key('default_off') else []
|
||||
not_active = channel_json['not_active'] if 'not_active' in channel_json else []
|
||||
default_off = channel_json['default_off'] if 'default_off' in channel_json else []
|
||||
|
||||
# Apply default configurations if they do not exist
|
||||
for control in default_controls:
|
||||
if control['id'] not in str(channel_controls):
|
||||
if 'include_in_newest' in control['id'] and 'include_in_newest' not in not_active and control['id'] not in not_active:
|
||||
if 'include_in_newest' in control['id'] and 'include_in_newest' not in not_active and control[
|
||||
'id'] not in not_active:
|
||||
label = control['id'].split('_')
|
||||
label = label[-1]
|
||||
if label == 'peliculas':
|
||||
if 'movie' in categories:
|
||||
control['label'] = config.get_localized_string(70727) + ' - ' + config.get_localized_string(30122)
|
||||
control['default'] = False if ('include_in_newest' in default_off) or ('include_in_newest_peliculas' in default_off) else True
|
||||
control['label'] = config.get_localized_string(70727) + ' - ' + config.get_localized_string(
|
||||
30122)
|
||||
control['default'] = False if ('include_in_newest' in default_off) or (
|
||||
'include_in_newest_peliculas' in default_off) else True
|
||||
channel_controls.append(control)
|
||||
else: pass
|
||||
else:
|
||||
pass
|
||||
elif label == 'series':
|
||||
if 'tvshow' in categories:
|
||||
control['label'] = config.get_localized_string(70727) + ' - ' + config.get_localized_string(30123)
|
||||
control['default'] = False if ('include_in_newest' in default_off) or ('include_in_newest_series' in default_off) else True
|
||||
control['label'] = config.get_localized_string(70727) + ' - ' + config.get_localized_string(
|
||||
30123)
|
||||
control['default'] = False if ('include_in_newest' in default_off) or (
|
||||
'include_in_newest_series' in default_off) else True
|
||||
channel_controls.append(control)
|
||||
else: pass
|
||||
else:
|
||||
pass
|
||||
elif label == 'anime':
|
||||
if 'anime' in categories:
|
||||
control['label'] = config.get_localized_string(70727) + ' - ' + config.get_localized_string(30124)
|
||||
control['default'] = False if ('include_in_newest' in default_off) or ('include_in_newest_anime' in default_off) else True
|
||||
control['label'] = config.get_localized_string(70727) + ' - ' + config.get_localized_string(
|
||||
30124)
|
||||
control['default'] = False if ('include_in_newest' in default_off) or (
|
||||
'include_in_newest_anime' in default_off) else True
|
||||
channel_controls.append(control)
|
||||
else: pass
|
||||
else:
|
||||
pass
|
||||
|
||||
else:
|
||||
control['label'] = config.get_localized_string(70727) + ' - ' + label.capitalize()
|
||||
@@ -259,13 +244,15 @@ def get_default_settings(channel_name):
|
||||
for control in default_controls_renumber:
|
||||
if control['id'] not in str(channel_controls):
|
||||
channel_controls.append(control)
|
||||
else: pass
|
||||
else:
|
||||
pass
|
||||
else:
|
||||
return get_channel_json(channel_name).get('settings', list())
|
||||
return channel_controls
|
||||
|
||||
|
||||
def get_channel_setting(name, channel, default=None):
|
||||
from core import filetools
|
||||
"""
|
||||
Retorna el valor de configuracion del parametro solicitado.
|
||||
|
||||
@@ -288,13 +275,15 @@ def get_channel_setting(name, channel, default=None):
|
||||
@rtype: any
|
||||
|
||||
"""
|
||||
file_settings = os.path.join(config.get_data_path(), "settings_channels", channel + "_data.json")
|
||||
file_settings = filetools.join(config.get_data_path(), "settings_channels", channel + "_data.json")
|
||||
dict_settings = {}
|
||||
dict_file = {}
|
||||
if os.path.exists(file_settings):
|
||||
if channel not in ['trakt']: def_settings = get_default_settings(channel)
|
||||
|
||||
if filetools.exists(file_settings):
|
||||
# Obtenemos configuracion guardada de ../settings/channel_data.json
|
||||
try:
|
||||
dict_file = jsontools.load(open(file_settings, "rb").read())
|
||||
dict_file = jsontools.load(filetools.read(file_settings))
|
||||
if isinstance(dict_file, dict) and 'settings' in dict_file:
|
||||
dict_settings = dict_file['settings']
|
||||
except EnvironmentError:
|
||||
@@ -313,9 +302,7 @@ def get_channel_setting(name, channel, default=None):
|
||||
dict_file['settings'] = dict_settings
|
||||
# Creamos el archivo ../settings/channel_data.json
|
||||
json_data = jsontools.dump(dict_file)
|
||||
try:
|
||||
open(file_settings, "wb").write(json_data)
|
||||
except EnvironmentError:
|
||||
if not filetools.write(file_settings, json_data, silent=True):
|
||||
logger.error("ERROR al salvar el archivo: %s" % file_settings)
|
||||
|
||||
# Devolvemos el valor del parametro local 'name' si existe, si no se devuelve default
|
||||
@@ -323,7 +310,7 @@ def get_channel_setting(name, channel, default=None):
|
||||
|
||||
|
||||
def set_channel_setting(name, value, channel):
|
||||
import filetools
|
||||
from core import filetools
|
||||
"""
|
||||
Fija el valor de configuracion del parametro indicado.
|
||||
|
||||
@@ -346,36 +333,22 @@ def set_channel_setting(name, value, channel):
|
||||
|
||||
"""
|
||||
# Creamos la carpeta si no existe
|
||||
if not os.path.exists(os.path.join(config.get_data_path(), "settings_channels")):
|
||||
os.mkdir(os.path.join(config.get_data_path(), "settings_channels"))
|
||||
if not filetools.exists(filetools.join(config.get_data_path(), "settings_channels")):
|
||||
filetools.mkdir(filetools.join(config.get_data_path(), "settings_channels"))
|
||||
|
||||
file_settings = os.path.join(config.get_data_path(), "settings_channels", channel + "_data.json")
|
||||
file_settings = filetools.join(config.get_data_path(), "settings_channels", channel + "_data.json")
|
||||
dict_settings = {}
|
||||
if channel not in ['trakt']: def_settings = get_default_settings(channel)
|
||||
|
||||
dict_file = None
|
||||
|
||||
if os.path.exists(file_settings):
|
||||
if filetools.exists(file_settings):
|
||||
# Obtenemos configuracion guardada de ../settings/channel_data.json
|
||||
try:
|
||||
dict_file = jsontools.load(open(file_settings, "r").read())
|
||||
dict_file = jsontools.load(filetools.read(file_settings))
|
||||
dict_settings = dict_file.get('settings', {})
|
||||
except EnvironmentError:
|
||||
logger.error("ERROR al leer el archivo: %s" % file_settings)
|
||||
|
||||
if os.path.isfile(filetools.join(config.get_runtime_path(), "channels", channel + ".json")):
|
||||
|
||||
# delete unused Settings
|
||||
def_keys = []
|
||||
del_keys = []
|
||||
for key in def_settings:
|
||||
def_keys.append(key['id'])
|
||||
for key in dict_settings:
|
||||
if key not in def_keys:
|
||||
del_keys.append(key)
|
||||
for key in del_keys:
|
||||
del dict_settings[key]
|
||||
|
||||
dict_settings[name] = value
|
||||
|
||||
# comprobamos si existe dict_file y es un diccionario, sino lo creamos
|
||||
@@ -385,10 +358,8 @@ def set_channel_setting(name, value, channel):
|
||||
dict_file['settings'] = dict_settings
|
||||
|
||||
# Creamos el archivo ../settings/channel_data.json
|
||||
try:
|
||||
json_data = jsontools.dump(dict_file)
|
||||
open(file_settings, "w").write(json_data)
|
||||
except EnvironmentError:
|
||||
json_data = jsontools.dump(dict_file)
|
||||
if not filetools.write(file_settings, json_data, silent=True):
|
||||
logger.error("ERROR al salvar el archivo: %s" % file_settings)
|
||||
return None
|
||||
|
||||
|
||||
+4
-4
@@ -20,8 +20,8 @@ metodos:
|
||||
from __future__ import division
|
||||
from future import standard_library
|
||||
standard_library.install_aliases()
|
||||
from future.builtins import range
|
||||
from future.builtins import object
|
||||
from builtins import range
|
||||
from builtins import object
|
||||
from past.utils import old_div
|
||||
#from builtins import str
|
||||
import sys
|
||||
@@ -243,7 +243,7 @@ class Downloader(object):
|
||||
|
||||
# Abrimos en modo "a+" para que cree el archivo si no existe, luego en modo "r+b" para poder hacer seek()
|
||||
self.file = filetools.file_open(filetools.join(self._path, self._filename), "a+", vfs=VFS)
|
||||
if self.file: self.file.close()
|
||||
if self.file: self.file.close()
|
||||
self.file = filetools.file_open(filetools.join(self._path, self._filename), "r+b", vfs=VFS)
|
||||
if not self.file:
|
||||
return
|
||||
@@ -258,7 +258,7 @@ class Downloader(object):
|
||||
self.__get_download_info__()
|
||||
|
||||
try:
|
||||
logger.info("Initialized Download: Parts: %s | Path: %s | Archive: %s | Size: %s" % \
|
||||
logger.info("Descarga inicializada: Partes: %s | Ruta: %s | Archivo: %s | Tamaño: %s" % \
|
||||
(str(len(self._download_info["parts"])), self._pathencode('utf-8'), \
|
||||
self._filenameencode('utf-8'), str(self._download_info["size"])))
|
||||
except:
|
||||
|
||||
+15
-9
@@ -110,6 +110,8 @@ def limpia_nombre_excepto_1(s):
|
||||
stripped = ''.join(c for c in s if c in validchars)
|
||||
# Convierte a iso
|
||||
s = stripped.encode("iso-8859-1")
|
||||
if PY3:
|
||||
s = s.decode('utf-8')
|
||||
return s
|
||||
|
||||
|
||||
@@ -129,7 +131,7 @@ def getfilefromtitle(url, title):
|
||||
logger.info("platform=" + plataforma)
|
||||
|
||||
# nombrefichero = xbmc.makeLegalFilename(title + url[-4:])
|
||||
from . import scrapertools
|
||||
from core import scrapertools
|
||||
|
||||
nombrefichero = title + scrapertools.get_filename_from_url(url)[-4:]
|
||||
logger.info("filename=%s" % nombrefichero)
|
||||
@@ -169,7 +171,10 @@ def downloadbest(video_urls, title, continuar=False):
|
||||
for elemento in invertida:
|
||||
# videotitle = elemento[0]
|
||||
url = elemento[1]
|
||||
logger.info("Downloading option " + title + " " + url.encode('ascii', 'ignore'))
|
||||
if not PY3:
|
||||
logger.info("Downloading option " + title + " " + url.encode('ascii', 'ignore'))
|
||||
else:
|
||||
logger.info("Downloading option " + title + " " + url.encode('ascii', 'ignore').decode('utf-8'))
|
||||
|
||||
# Calcula el fichero donde debe grabar
|
||||
try:
|
||||
@@ -621,7 +626,7 @@ def downloadfileGzipped(url, pathfichero):
|
||||
break
|
||||
except:
|
||||
reintentos += 1
|
||||
logger.info("ERROR in block download, retry %dd" % reintentos)
|
||||
logger.info("ERROR in block download, retry %d" % reintentos)
|
||||
for line in sys.exc_info():
|
||||
logger.error("%s" % line)
|
||||
|
||||
@@ -660,7 +665,7 @@ def GetTitleFromFile(title):
|
||||
# Imprime en el log lo que va a descartar
|
||||
logger.info("title=" + title)
|
||||
plataforma = config.get_system_platform()
|
||||
logger.info("platform=" + plataforma)
|
||||
logger.info("plataform=" + plataforma)
|
||||
|
||||
# nombrefichero = xbmc.makeLegalFilename(title + url[-4:])
|
||||
nombrefichero = title
|
||||
@@ -678,7 +683,7 @@ def downloadIfNotModifiedSince(url, timestamp):
|
||||
|
||||
# Convierte la fecha a GMT
|
||||
fecha_formateada = time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime(timestamp))
|
||||
logger.info("DateFormat=%s" % fecha_formateada)
|
||||
logger.info("fechaFormateada=%s" % fecha_formateada)
|
||||
|
||||
# Comprueba si ha cambiado
|
||||
inicio = time.clock()
|
||||
@@ -700,11 +705,11 @@ def downloadIfNotModifiedSince(url, timestamp):
|
||||
except urllib.error.URLError as e:
|
||||
# Si devuelve 304 es que no ha cambiado
|
||||
if hasattr(e, 'code'):
|
||||
logger.info("HTTP response code: %d" % e.code)
|
||||
logger.info("HTTP response code : %d" % e.code)
|
||||
if e.code == 304:
|
||||
logger.info("It has not changed")
|
||||
updated = False
|
||||
# Agarra los errores con codigo de respuesta del servidor externo solicitado
|
||||
# Agarra los errores con codigo de respuesta del servidor externo solicitado
|
||||
else:
|
||||
for line in sys.exc_info():
|
||||
logger.error("%s" % line)
|
||||
@@ -814,6 +819,7 @@ def download_all_episodes(item, channel, first_episode="", preferred_server="vid
|
||||
|
||||
for mirror_item in mirrors_itemlist:
|
||||
logger.info("mirror=" + mirror_item.title)
|
||||
|
||||
if "(Italiano)" in mirror_item.title:
|
||||
idioma = "(Italiano)"
|
||||
codigo_idioma = "it"
|
||||
@@ -885,8 +891,8 @@ def download_all_episodes(item, channel, first_episode="", preferred_server="vid
|
||||
|
||||
|
||||
def episodio_ya_descargado(show_title, episode_title):
|
||||
from . import scrapertools
|
||||
ficheros = os.listdir(".")
|
||||
from core import scrapertools
|
||||
ficheros = filetools.listdir(".")
|
||||
|
||||
for fichero in ficheros:
|
||||
# logger.info("fichero="+fichero)
|
||||
|
||||
+41
-42
@@ -87,7 +87,7 @@ def encode(path, _samba=False):
|
||||
if scrapertools.find_single_match(path, '(^\w+:\/\/)') or _samba:
|
||||
path = path.encode("utf-8", "ignore")
|
||||
else:
|
||||
if fs_encoding:
|
||||
if fs_encoding and not PY3:
|
||||
path = path.encode(fs_encoding, "ignore")
|
||||
|
||||
return path
|
||||
@@ -133,13 +133,13 @@ def read(path, linea_inicio=0, total_lineas=None, whence=0, silent=False, vfs=Tr
|
||||
try:
|
||||
linea_inicio = int(linea_inicio)
|
||||
except:
|
||||
logger.error('Read: ERROR de linea_inicio: %s' % str(linea_inicio))
|
||||
logger.error('Read: Start_line ERROR: %s' % str(linea_inicio))
|
||||
linea_inicio = 0
|
||||
if total_lineas != None and not isinstance(total_lineas, int):
|
||||
try:
|
||||
total_lineas = int(total_lineas)
|
||||
except:
|
||||
logger.error('Read: ERROR de total_lineas: %s' % str(total_lineas))
|
||||
logger.error('Read: ERROR of total_lineas: %s' % str(total_lineas))
|
||||
total_lineas = None
|
||||
if xbmc_vfs and vfs:
|
||||
if not exists(path): return False
|
||||
@@ -151,7 +151,7 @@ def read(path, linea_inicio=0, total_lineas=None, whence=0, silent=False, vfs=Tr
|
||||
except:
|
||||
return False
|
||||
f.seek(linea_inicio, whence)
|
||||
logger.debug('POSICIÓN de comienzo de lectura, tell(): %s' % f.seek(0, 1))
|
||||
logger.debug('POSITION of beginning of reading,, tell(): %s' % f.seek(0, 1))
|
||||
if total_lineas == None:
|
||||
total_lineas = 0
|
||||
data = f.read(total_lineas)
|
||||
@@ -169,15 +169,15 @@ def read(path, linea_inicio=0, total_lineas=None, whence=0, silent=False, vfs=Tr
|
||||
f.close()
|
||||
except:
|
||||
if not silent:
|
||||
logger.error("ERROR al leer el archivo: %s" % path)
|
||||
logger.error("ERROR reading file: %s" % path)
|
||||
logger.error(traceback.format_exc())
|
||||
return False
|
||||
|
||||
else:
|
||||
if not PY3:
|
||||
return "".join(data)
|
||||
return unicode("".join(data))
|
||||
else:
|
||||
return b"".join(data)
|
||||
return unicode(b"".join(data))
|
||||
|
||||
|
||||
def write(path, data, mode="wb", silent=False, vfs=True):
|
||||
@@ -226,20 +226,20 @@ def file_open(path, mode="r", silent=False, vfs=True):
|
||||
if xbmc_vfs and vfs:
|
||||
if 'r' in mode and '+' in mode:
|
||||
mode = mode.replace('r', 'w').replace('+', '')
|
||||
logger.debug('Open MODE cambiado a: %s' % mode)
|
||||
logger.debug('Open MODE changed to: %s' % mode)
|
||||
if 'a' in mode:
|
||||
mode = mode.replace('a', 'w').replace('+', '')
|
||||
logger.debug('Open MODE cambiado a: %s' % mode)
|
||||
logger.debug('Open MODE changed to: %s' % mode)
|
||||
return xbmcvfs.File(path, mode)
|
||||
elif path.lower().startswith("smb://"):
|
||||
return samba.smb_open(path, mode)
|
||||
else:
|
||||
return open(path, mode)
|
||||
except:
|
||||
logger.error("ERROR al abrir el archivo: %s, %s" % (path, mode))
|
||||
logger.error("ERROR when opening file: %s, %s" % (path, mode))
|
||||
if not silent:
|
||||
logger.error(traceback.format_exc())
|
||||
platformtools.dialog_notification("Error al abrir", path)
|
||||
platformtools.dialog_notification("Error Opening", path)
|
||||
return False
|
||||
|
||||
|
||||
@@ -258,7 +258,7 @@ def file_stat(path, silent=False, vfs=True):
|
||||
return xbmcvfs.Stat(path)
|
||||
raise
|
||||
except:
|
||||
logger.error("File_Stat no soportado: %s" % path)
|
||||
logger.error("File_Stat not supported: %s" % path)
|
||||
if not silent:
|
||||
logger.error(traceback.format_exc())
|
||||
return False
|
||||
@@ -283,9 +283,9 @@ def rename(path, new_name, silent=False, strict=False, vfs=True):
|
||||
dest = encode(join(dirname(path_end), new_name))
|
||||
result = xbmcvfs.rename(path, dest)
|
||||
if not result and not strict:
|
||||
logger.error("ERROR al RENOMBRAR el archivo: %s. Copiando y borrando" % path)
|
||||
logger.error("ERROR RENAME file: %s. Copying and deleting" % path)
|
||||
if not silent:
|
||||
dialogo = platformtools.dialog_progress("Copiando archivo", "")
|
||||
dialogo = platformtools.dialog_progress("Copying file", "")
|
||||
result = xbmcvfs.copy(path, dest)
|
||||
if not result:
|
||||
return False
|
||||
@@ -298,10 +298,10 @@ def rename(path, new_name, silent=False, strict=False, vfs=True):
|
||||
new_name = encode(new_name, False)
|
||||
os.rename(path, os.path.join(os.path.dirname(path), new_name))
|
||||
except:
|
||||
logger.error("ERROR al renombrar el archivo: %s" % path)
|
||||
logger.error("ERROR when renaming the file: %s" % path)
|
||||
if not silent:
|
||||
logger.error(traceback.format_exc())
|
||||
platformtools.dialog_notification("Error al renombrar", path)
|
||||
platformtools.dialog_notification("Error renaming", path)
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
@@ -324,9 +324,9 @@ def move(path, dest, silent=False, strict=False, vfs=True):
|
||||
dest = encode(dest)
|
||||
result = xbmcvfs.rename(path, dest)
|
||||
if not result and not strict:
|
||||
logger.error("ERROR al MOVER el archivo: %s. Copiando y borrando" % path)
|
||||
logger.error("ERROR when MOVING the file: %s. Copying and deleting" % path)
|
||||
if not silent:
|
||||
dialogo = platformtools.dialog_progress("Copiando archivo", "")
|
||||
dialogo = platformtools.dialog_progress("Copying file", "")
|
||||
result = xbmcvfs.copy(path, dest)
|
||||
if not result:
|
||||
return False
|
||||
@@ -349,7 +349,7 @@ def move(path, dest, silent=False, strict=False, vfs=True):
|
||||
dialogo = platformtools.dialog_progress("Copiando archivo", "")
|
||||
return copy(path, dest) == True and remove(path) == True
|
||||
except:
|
||||
logger.error("ERROR al mover el archivo: %s a %s" % (path, dest))
|
||||
logger.error("ERROR when moving file: %s to %s" % (path, dest))
|
||||
if not silent:
|
||||
logger.error(traceback.format_exc())
|
||||
return False
|
||||
@@ -376,7 +376,7 @@ def copy(path, dest, silent=False, vfs=True):
|
||||
if not silent:
|
||||
dialogo = platformtools.dialog_progress("Copiando archivo", "")
|
||||
return bool(xbmcvfs.copy(path, dest))
|
||||
|
||||
|
||||
fo = file_open(path, "rb")
|
||||
fd = file_open(dest, "wb")
|
||||
if fo and fd:
|
||||
@@ -398,7 +398,7 @@ def copy(path, dest, silent=False, vfs=True):
|
||||
if not silent:
|
||||
dialogo.close()
|
||||
except:
|
||||
logger.error("ERROR al copiar el archivo: %s" % path)
|
||||
logger.error("ERROR when copying the file: %s" % path)
|
||||
if not silent:
|
||||
logger.error(traceback.format_exc())
|
||||
return False
|
||||
@@ -420,13 +420,13 @@ def exists(path, silent=False, vfs=True):
|
||||
result = bool(xbmcvfs.exists(path))
|
||||
if not result and not path.endswith('/') and not path.endswith('\\'):
|
||||
result = bool(xbmcvfs.exists(join(path, ' ').rstrip()))
|
||||
return result
|
||||
return result
|
||||
elif path.lower().startswith("smb://"):
|
||||
return samba.exists(path)
|
||||
else:
|
||||
return os.path.exists(path)
|
||||
except:
|
||||
logger.error("ERROR al comprobar la ruta: %s" % path)
|
||||
logger.error("ERROR when checking the path: %s" % path)
|
||||
if not silent:
|
||||
logger.error(traceback.format_exc())
|
||||
return False
|
||||
@@ -458,7 +458,7 @@ def isfile(path, silent=False, vfs=True):
|
||||
else:
|
||||
return os.path.isfile(path)
|
||||
except:
|
||||
logger.error("ERROR al comprobar el archivo: %s" % path)
|
||||
logger.error("ERROR when checking file: %s" % path)
|
||||
if not silent:
|
||||
logger.error(traceback.format_exc())
|
||||
return False
|
||||
@@ -490,7 +490,7 @@ def isdir(path, silent=False, vfs=True):
|
||||
else:
|
||||
return os.path.isdir(path)
|
||||
except:
|
||||
logger.error("ERROR al comprobar el directorio: %s" % path)
|
||||
logger.error("ERROR when checking the directory: %s" % path)
|
||||
if not silent:
|
||||
logger.error(traceback.format_exc())
|
||||
return False
|
||||
@@ -517,7 +517,7 @@ def getsize(path, silent=False, vfs=True):
|
||||
else:
|
||||
return os.path.getsize(path)
|
||||
except:
|
||||
logger.error("ERROR al obtener el tamaño: %s" % path)
|
||||
logger.error("ERROR when getting the size: %s" % path)
|
||||
if not silent:
|
||||
logger.error(traceback.format_exc())
|
||||
return long(0)
|
||||
@@ -540,10 +540,10 @@ def remove(path, silent=False, vfs=True):
|
||||
else:
|
||||
os.remove(path)
|
||||
except:
|
||||
logger.error("ERROR al eliminar el archivo: %s" % path)
|
||||
logger.error("ERROR deleting file: %s" % path)
|
||||
if not silent:
|
||||
logger.error(traceback.format_exc())
|
||||
platformtools.dialog_notification("Error al eliminar el archivo", path)
|
||||
platformtools.dialog_notification("ERROR deleting file", path)
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
@@ -580,10 +580,10 @@ def rmdirtree(path, silent=False, vfs=True):
|
||||
import shutil
|
||||
shutil.rmtree(path, ignore_errors=True)
|
||||
except:
|
||||
logger.error("ERROR al eliminar el directorio: %s" % path)
|
||||
logger.error("ERROR deleting directory: %s" % path)
|
||||
if not silent:
|
||||
logger.error(traceback.format_exc())
|
||||
platformtools.dialog_notification("Error al eliminar el directorio", path)
|
||||
platformtools.dialog_notification("ERROR deleting directory", path)
|
||||
return False
|
||||
else:
|
||||
return not exists(path)
|
||||
@@ -608,10 +608,10 @@ def rmdir(path, silent=False, vfs=True):
|
||||
else:
|
||||
os.rmdir(path)
|
||||
except:
|
||||
logger.error("ERROR al eliminar el directorio: %s" % path)
|
||||
logger.error("ERROR deleting directory: %s" % path)
|
||||
if not silent:
|
||||
logger.error(traceback.format_exc())
|
||||
platformtools.dialog_notification("Error al eliminar el directorio", path)
|
||||
platformtools.dialog_notification("ERROR deleting directory", path)
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
@@ -641,10 +641,10 @@ def mkdir(path, silent=False, vfs=True):
|
||||
else:
|
||||
os.mkdir(path)
|
||||
except:
|
||||
logger.error("ERROR al crear el directorio: %s" % path)
|
||||
logger.error("ERROR when creating directory: %s" % path)
|
||||
if not silent:
|
||||
logger.error(traceback.format_exc())
|
||||
platformtools.dialog_notification("Error al crear el directorio", path)
|
||||
platformtools.dialog_notification("ERROR when creating directory", path)
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
@@ -724,7 +724,7 @@ def listdir(path, silent=False, vfs=True):
|
||||
else:
|
||||
return decode(os.listdir(path))
|
||||
except:
|
||||
logger.error("ERROR al leer el directorio: %s" % path)
|
||||
logger.error("ERROR when reading the directory: %s" % path)
|
||||
if not silent:
|
||||
logger.error(traceback.format_exc())
|
||||
return False
|
||||
@@ -740,14 +740,13 @@ def join(*paths):
|
||||
list_path = []
|
||||
if paths[0].startswith("/"):
|
||||
list_path.append("")
|
||||
|
||||
for path in paths:
|
||||
if path:
|
||||
if xbmc_vfs:
|
||||
if xbmc_vfs and type(path) != str:
|
||||
path = encode(path)
|
||||
list_path += path.replace("\\", "/").strip("/").split("/")
|
||||
|
||||
if scrapertools.find_single_match(paths[0], '(^\w+:\/\/)'):
|
||||
if scrapertools.find_single_match(paths[0], r'(^\w+:\/\/)'):
|
||||
return str("/".join(list_path))
|
||||
else:
|
||||
return str(os.sep.join(list_path))
|
||||
@@ -812,8 +811,8 @@ def remove_tags(title):
|
||||
return title_without_tags
|
||||
else:
|
||||
return title
|
||||
|
||||
|
||||
|
||||
|
||||
def remove_smb_credential(path):
|
||||
"""
|
||||
devuelve el path sin contraseña/usuario para paths de SMB
|
||||
@@ -823,10 +822,10 @@ def remove_smb_credential(path):
|
||||
@rtype: str
|
||||
"""
|
||||
logger.info()
|
||||
|
||||
|
||||
if not scrapertools.find_single_match(path, '(^\w+:\/\/)'):
|
||||
return path
|
||||
|
||||
|
||||
protocol = scrapertools.find_single_match(path, '(^\w+:\/\/)')
|
||||
path_without_credentials = scrapertools.find_single_match(path, '^\w+:\/\/(?:[^;\n]+;)?(?:[^:@\n]+[:|@])?(?:[^@\n]+@)?(.*?$)')
|
||||
|
||||
|
||||
+8
-6
@@ -31,7 +31,7 @@ cookies_file = os.path.join(config.get_data_path(), "cookies.dat")
|
||||
default_headers = dict()
|
||||
default_headers["User-Agent"] = "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36"
|
||||
default_headers["Accept"] = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"
|
||||
default_headers["Accept-Language"] = "es-ES,es;q=0.8,en-US;q=0.5,en;q=0.3"
|
||||
default_headers["Accept-Language"] = "it-IT,it;q=0.8,en-US;q=0.5,en;q=0.3"
|
||||
default_headers["Accept-Charset"] = "UTF-8"
|
||||
default_headers["Accept-Encoding"] = "gzip"
|
||||
|
||||
@@ -255,13 +255,11 @@ def downloadpage(url, **opt):
|
||||
domain = urlparse.urlparse(url).netloc
|
||||
CF = False
|
||||
if domain in ['www.guardaserie.media', 'casacinema.space', 'wstream.video', 'akvideo.stream', 'backin.net',
|
||||
'dreamsub.stream', 'altadefinizione-nuovo.link', 'ilgeniodellostreaming.si', 'www.piratestreaming.gratis']:
|
||||
'dreamsub.stream', 'altadefinizione-nuovo.link', 'ilgeniodellostreaming.si', 'www.piratestreaming.gratis',
|
||||
'altadefinizione.style']:
|
||||
from lib import cloudscraper
|
||||
session = cloudscraper.create_scraper()
|
||||
CF = True
|
||||
elif opt.get('session', False):
|
||||
session = opt['session'] # same session to speed up search
|
||||
logger.info('same session')
|
||||
else:
|
||||
from lib import requests
|
||||
session = requests.session()
|
||||
@@ -360,6 +358,7 @@ def downloadpage(url, **opt):
|
||||
timeout=opt['timeout'])
|
||||
except Exception as e:
|
||||
from lib import requests
|
||||
req = requests.Response()
|
||||
if not opt.get('ignore_response_code', False) and not proxy_data.get('stat', ''):
|
||||
response['data'] = ''
|
||||
response['sucess'] = False
|
||||
@@ -371,7 +370,6 @@ def downloadpage(url, **opt):
|
||||
show_infobox(info_dict)
|
||||
return type('HTTPResponse', (), response)
|
||||
else:
|
||||
req = requests.Response()
|
||||
req.status_code = str(e)
|
||||
|
||||
else:
|
||||
@@ -384,6 +382,10 @@ def downloadpage(url, **opt):
|
||||
|
||||
response['data'] = req.content
|
||||
response['url'] = req.url
|
||||
|
||||
if type(response['data']) != str:
|
||||
response['data'] = response['data'].decode('UTF-8')
|
||||
|
||||
if not response['data']:
|
||||
response['data'] = ''
|
||||
try:
|
||||
|
||||
+54
-26
@@ -3,12 +3,23 @@
|
||||
# Item is the object we use for representing data
|
||||
# --------------------------------------------------------------------------------
|
||||
|
||||
#from builtins import str
|
||||
from future.builtins import object
|
||||
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
|
||||
from html.parser import HTMLParser
|
||||
else:
|
||||
import urllib # Usamos el nativo de PY2 que es más rápido
|
||||
from HTMLParser import HTMLParser
|
||||
|
||||
import base64
|
||||
import copy
|
||||
import os
|
||||
import urllib
|
||||
|
||||
from HTMLParser import HTMLParser
|
||||
|
||||
from core import jsontools as json
|
||||
|
||||
@@ -58,12 +69,12 @@ class InfoLabels(dict):
|
||||
elif key == 'code':
|
||||
code = []
|
||||
# Añadir imdb_id al listado de codigos
|
||||
if 'imdb_id' in super(InfoLabels, self).keys() and super(InfoLabels, self).__getitem__('imdb_id'):
|
||||
if 'imdb_id' in list(super(InfoLabels, self).keys()) and super(InfoLabels, self).__getitem__('imdb_id'):
|
||||
code.append(super(InfoLabels, self).__getitem__('imdb_id'))
|
||||
|
||||
# Completar con el resto de codigos
|
||||
for scr in ['tmdb_id', 'tvdb_id', 'noscrap_id']:
|
||||
if scr in super(InfoLabels, self).keys() and super(InfoLabels, self).__getitem__(scr):
|
||||
if scr in list(super(InfoLabels, self).keys()) and super(InfoLabels, self).__getitem__(scr):
|
||||
value = "%s%s" % (scr[:-2], super(InfoLabels, self).__getitem__(scr))
|
||||
code.append(value)
|
||||
|
||||
@@ -78,21 +89,21 @@ class InfoLabels(dict):
|
||||
|
||||
elif key == 'mediatype':
|
||||
# "list", "movie", "tvshow", "season", "episode"
|
||||
if 'tvshowtitle' in super(InfoLabels, self).keys() \
|
||||
if 'tvshowtitle' in list(super(InfoLabels, self).keys()) \
|
||||
and super(InfoLabels, self).__getitem__('tvshowtitle') != "":
|
||||
if 'episode' in super(InfoLabels, self).keys() and super(InfoLabels, self).__getitem__('episode') != "":
|
||||
if 'episode' in list(super(InfoLabels, self).keys()) and super(InfoLabels, self).__getitem__('episode') != "":
|
||||
return 'episode'
|
||||
|
||||
if 'episodeName' in super(InfoLabels, self).keys() \
|
||||
if 'episodeName' in list(super(InfoLabels, self).keys()) \
|
||||
and super(InfoLabels, self).__getitem__('episodeName') != "":
|
||||
return 'episode'
|
||||
|
||||
if 'season' in super(InfoLabels, self).keys() and super(InfoLabels, self).__getitem__('season') != "":
|
||||
if 'season' in list(super(InfoLabels, self).keys()) and super(InfoLabels, self).__getitem__('season') != "":
|
||||
return 'season'
|
||||
else:
|
||||
return 'tvshow'
|
||||
|
||||
elif 'title' in super(InfoLabels, self).keys() and super(InfoLabels, self).__getitem__('title') != "":
|
||||
elif 'title' in list(super(InfoLabels, self).keys()) and super(InfoLabels, self).__getitem__('title') != "":
|
||||
return 'movie'
|
||||
|
||||
else:
|
||||
@@ -104,7 +115,7 @@ class InfoLabels(dict):
|
||||
|
||||
def tostring(self, separador=', '):
|
||||
ls = []
|
||||
dic = dict(super(InfoLabels, self).items())
|
||||
dic = dict(list(super(InfoLabels, self).items()))
|
||||
|
||||
for i in sorted(dic.items()):
|
||||
i_str = str(i)[1:-1]
|
||||
@@ -158,6 +169,7 @@ class Item(object):
|
||||
Función llamada al modificar cualquier atributo del item, modifica algunos atributos en función de los datos
|
||||
modificados.
|
||||
"""
|
||||
if PY3: name = self.toutf8(name)
|
||||
value = self.toutf8(value)
|
||||
if name == "__dict__":
|
||||
for key in value:
|
||||
@@ -313,9 +325,13 @@ class Item(object):
|
||||
valor = dic[var].tostring(',\r\t\t')
|
||||
else:
|
||||
valor = dic[var].tostring()
|
||||
elif PY3 and isinstance(dic[var], bytes):
|
||||
valor = "'%s'" % dic[var].decode('utf-8')
|
||||
else:
|
||||
valor = str(dic[var])
|
||||
|
||||
if PY3 and isinstance(var, bytes):
|
||||
var = var.decode('utf-8')
|
||||
ls.append(var + "= " + valor)
|
||||
|
||||
return separator.join(ls)
|
||||
@@ -327,12 +343,12 @@ class Item(object):
|
||||
|
||||
Uso: url = item.tourl()
|
||||
"""
|
||||
dump = json.dump(self.__dict__)
|
||||
dump = json.dump(self.__dict__).encode("utf8")
|
||||
# if empty dict
|
||||
if not dump:
|
||||
# set a str to avoid b64encode fails
|
||||
dump = ""
|
||||
return urllib.quote(base64.b64encode(dump))
|
||||
dump = "".encode("utf8")
|
||||
return str(urllib.quote(base64.b64encode(dump)))
|
||||
|
||||
def fromurl(self, url):
|
||||
"""
|
||||
@@ -367,6 +383,7 @@ class Item(object):
|
||||
return self
|
||||
|
||||
def tojson(self, path=""):
|
||||
from core import filetools
|
||||
"""
|
||||
Crea un JSON a partir del item, para guardar archivos de favoritos, lista de descargas, etc...
|
||||
Si se especifica un path, te lo guarda en la ruta especificada, si no, devuelve la cadena json
|
||||
@@ -377,11 +394,13 @@ class Item(object):
|
||||
@type path: str
|
||||
"""
|
||||
if path:
|
||||
open(path, "wb").write(json.dump(self.__dict__))
|
||||
#open(path, "wb").write(json.dump(self.__dict__))
|
||||
res = filetools.write(path, json.dump(self.__dict__))
|
||||
else:
|
||||
return json.dump(self.__dict__)
|
||||
|
||||
def fromjson(self, json_item=None, path=""):
|
||||
from core import filetools
|
||||
"""
|
||||
Genera un item a partir de un archivo JSON
|
||||
Si se especifica un path, lee directamente el archivo, si no, lee la cadena de texto pasada.
|
||||
@@ -394,8 +413,9 @@ class Item(object):
|
||||
@type path: str
|
||||
"""
|
||||
if path:
|
||||
if os.path.exists(path):
|
||||
json_item = open(path, "rb").read()
|
||||
if filetools.exists(path):
|
||||
#json_item = open(path, "rb").read()
|
||||
json_item = filetools.read(path)
|
||||
else:
|
||||
json_item = {}
|
||||
|
||||
@@ -436,6 +456,8 @@ class Item(object):
|
||||
unicode_title = unicode(value, "utf8", "ignore")
|
||||
return HTMLParser().unescape(unicode_title).encode("utf8")
|
||||
except:
|
||||
if PY3 and isinstance(value, bytes):
|
||||
value = value.decode("utf8")
|
||||
return value
|
||||
|
||||
def toutf8(self, *args):
|
||||
@@ -447,13 +469,18 @@ class Item(object):
|
||||
else:
|
||||
value = self.__dict__
|
||||
|
||||
if type(value) == unicode:
|
||||
return value.encode("utf8")
|
||||
if isinstance(value, unicode):
|
||||
value = value.encode("utf8")
|
||||
if PY3: value = value.decode("utf8")
|
||||
return value
|
||||
|
||||
elif type(value) == str:
|
||||
elif not PY3 and isinstance(value, str):
|
||||
return unicode(value, "utf8", "ignore").encode("utf8")
|
||||
|
||||
elif type(value) == list:
|
||||
elif PY3 and isinstance(value, bytes):
|
||||
return value.decode("utf8")
|
||||
|
||||
elif isinstance(value, list):
|
||||
for x, key in enumerate(value):
|
||||
value[x] = self.toutf8(value[x])
|
||||
return value
|
||||
@@ -461,11 +488,12 @@ class Item(object):
|
||||
elif isinstance(value, dict):
|
||||
newdct = {}
|
||||
for key in value:
|
||||
v = self.toutf8(value[key])
|
||||
if type(key) == unicode:
|
||||
key = key.encode("utf8")
|
||||
value_unc = self.toutf8(value[key])
|
||||
key_unc = self.toutf8(key)
|
||||
#if isinstance(key, unicode):
|
||||
# key = key.encode("utf8")
|
||||
|
||||
newdct[key] = v
|
||||
newdct[key_unc] = value_unc
|
||||
|
||||
if len(args) > 0:
|
||||
if isinstance(value, InfoLabels):
|
||||
|
||||
+29
-21
@@ -10,24 +10,28 @@ from platformcode import logger
|
||||
try:
|
||||
import json
|
||||
except:
|
||||
logger.info("json incluido en el interprete **NO** disponible")
|
||||
logger.info("json included in the interpreter **NOT** available")
|
||||
|
||||
try:
|
||||
import simplejson as json
|
||||
except:
|
||||
logger.info("simplejson incluido en el interprete **NO** disponible")
|
||||
logger.info("simplejson included in the interpreter **NOT** available")
|
||||
try:
|
||||
from lib import simplejson as json
|
||||
except:
|
||||
logger.info("simplejson en el directorio lib **NO** disponible")
|
||||
logger.error("No se ha encontrado un parser de JSON valido")
|
||||
logger.info("simplejson in lib directory **NOT** available")
|
||||
logger.error("A valid JSON parser was not found")
|
||||
json = None
|
||||
else:
|
||||
logger.info("Usando simplejson en el directorio lib")
|
||||
logger.info("Using simplejson in the lib directory")
|
||||
else:
|
||||
logger.info("Usando simplejson incluido en el interprete")
|
||||
else:
|
||||
logger.info("Usando json incluido en el interprete")
|
||||
logger.info("Using simplejson included in the interpreter")
|
||||
# ~ else:
|
||||
# ~ logger.info("Usando json incluido en el interprete")
|
||||
|
||||
import sys
|
||||
PY3 = False
|
||||
if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int
|
||||
|
||||
|
||||
def load(*args, **kwargs):
|
||||
@@ -37,7 +41,7 @@ def load(*args, **kwargs):
|
||||
try:
|
||||
value = json.loads(*args, **kwargs)
|
||||
except:
|
||||
logger.error("**NO** se ha podido cargar el JSON")
|
||||
logger.error("**NOT** able to load the JSON")
|
||||
logger.error(traceback.format_exc())
|
||||
value = {}
|
||||
|
||||
@@ -46,12 +50,12 @@ def load(*args, **kwargs):
|
||||
|
||||
def dump(*args, **kwargs):
|
||||
if not kwargs:
|
||||
kwargs = {"indent": 4, "skipkeys": True, "sort_keys": True, "ensure_ascii": False}
|
||||
kwargs = {"indent": 4, "skipkeys": True, "sort_keys": True, "ensure_ascii": True}
|
||||
|
||||
try:
|
||||
value = json.dumps(*args, **kwargs)
|
||||
except:
|
||||
logger.error("**NO** se ha podido cargar el JSON")
|
||||
logger.error("JSON could **NOT** be saved")
|
||||
logger.error(traceback.format_exc())
|
||||
value = ""
|
||||
return value
|
||||
@@ -59,11 +63,15 @@ def dump(*args, **kwargs):
|
||||
|
||||
def to_utf8(dct):
|
||||
if isinstance(dct, dict):
|
||||
return dict((to_utf8(key), to_utf8(value)) for key, value in dct.iteritems())
|
||||
return dict((to_utf8(key), to_utf8(value)) for key, value in dct.items())
|
||||
elif isinstance(dct, list):
|
||||
return [to_utf8(element) for element in dct]
|
||||
elif isinstance(dct, unicode):
|
||||
return dct.encode('utf-8')
|
||||
dct = dct.encode("utf8")
|
||||
if PY3: dct = dct.decode("utf8")
|
||||
return dct
|
||||
elif PY3 and isinstance(dct, bytes):
|
||||
return dct.decode('utf-8')
|
||||
else:
|
||||
return dct
|
||||
|
||||
@@ -124,18 +132,18 @@ def check_to_backup(data, fname, dict_data):
|
||||
logger.info()
|
||||
|
||||
if not dict_data:
|
||||
logger.error("Error al cargar el json del fichero %s" % fname)
|
||||
logger.error("Error loading json from file %s" % fname)
|
||||
|
||||
if data != "":
|
||||
# se crea un nuevo fichero
|
||||
from core import filetools
|
||||
title = filetools.write("%s.bk" % fname, data)
|
||||
if title != "":
|
||||
logger.error("Ha habido un error al guardar el fichero: %s.bk" % fname)
|
||||
logger.error("There was an error saving the file: %s.bk" % fname)
|
||||
else:
|
||||
logger.debug("Se ha guardado una copia con el nombre: %s.bk" % fname)
|
||||
logger.debug("A copy with the name has been saved: %s.bk" % fname)
|
||||
else:
|
||||
logger.debug("Está vacío el fichero: %s" % fname)
|
||||
logger.debug("The file is empty: %s" % fname)
|
||||
|
||||
|
||||
def update_node(dict_node, name_file, node, path=None):
|
||||
@@ -175,18 +183,18 @@ def update_node(dict_node, name_file, node, path=None):
|
||||
# es un dict
|
||||
if dict_data:
|
||||
if node in dict_data:
|
||||
logger.debug(" existe el key %s" % node)
|
||||
logger.debug(" the key exists %s" % node)
|
||||
dict_data[node] = dict_node
|
||||
else:
|
||||
logger.debug(" NO existe el key %s" % node)
|
||||
logger.debug(" The key does NOT exist %s" % node)
|
||||
new_dict = {node: dict_node}
|
||||
dict_data.update(new_dict)
|
||||
else:
|
||||
logger.debug(" NO es un dict")
|
||||
logger.debug(" It is NOT a dict")
|
||||
dict_data = {node: dict_node}
|
||||
json_data = dump(dict_data)
|
||||
result = filetools.write(fname, json_data)
|
||||
except:
|
||||
logger.error("No se ha podido actualizar %s" % fname)
|
||||
logger.error("Could not update %s" % fname)
|
||||
|
||||
return result, json_data
|
||||
|
||||
+11
-6
@@ -1,5 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import sys
|
||||
PY3 = False
|
||||
if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int
|
||||
|
||||
#from builtins import str
|
||||
from core.item import InfoLabels
|
||||
from platformcode import config, logger
|
||||
from platformcode import platformtools
|
||||
@@ -46,7 +51,7 @@ def find_and_set_infoLabels(item):
|
||||
try:
|
||||
scraper = __import__('core.%s' % scraper_actual, fromlist=["core.%s" % scraper_actual])
|
||||
except ImportError:
|
||||
exec "import core." + scraper_actual + " as scraper"
|
||||
exec("import core." + scraper_actual + " as scraper")
|
||||
except:
|
||||
import traceback
|
||||
logger.error(traceback.format_exc())
|
||||
@@ -99,9 +104,9 @@ def find_and_set_infoLabels(item):
|
||||
return True
|
||||
# raise
|
||||
|
||||
elif list_opciones_cuadro[index] in scrapers_disponibles.values():
|
||||
elif list_opciones_cuadro[index] in list(scrapers_disponibles.values()):
|
||||
# Obtener el nombre del modulo del scraper
|
||||
for k, v in scrapers_disponibles.items():
|
||||
for k, v in list(scrapers_disponibles.items()):
|
||||
if list_opciones_cuadro[index] == v:
|
||||
if scrapers_disponibles[scraper_actual] not in list_opciones_cuadro:
|
||||
list_opciones_cuadro.append(scrapers_disponibles[scraper_actual])
|
||||
@@ -111,7 +116,7 @@ def find_and_set_infoLabels(item):
|
||||
scraper = None
|
||||
scraper = __import__('core.%s' % scraper_actual, fromlist=["core.%s" % scraper_actual])
|
||||
except ImportError:
|
||||
exec "import core." + scraper_actual + " as scraper_module"
|
||||
exec("import core." + scraper_actual + " as scraper_module")
|
||||
break
|
||||
|
||||
logger.error("Error al importar el modulo scraper %s" % scraper_actual)
|
||||
@@ -175,7 +180,7 @@ def cuadro_completar(item):
|
||||
|
||||
if not dict_default[c[0]] or dict_default[c[0]] == 'None' or dict_default[c[0]] == 0:
|
||||
dict_default[c[0]] = ''
|
||||
elif isinstance(dict_default[c[0]], (int, float, long)):
|
||||
elif isinstance(dict_default[c[0]], (int, float)) or (not PY3 and isinstance(dict_default[c[0]], (int, float, long))):
|
||||
# Si es numerico lo convertimos en str
|
||||
dict_default[c[0]] = str(dict_default[c[0]])
|
||||
|
||||
@@ -204,7 +209,7 @@ def callback_cuadro_completar(item, dict_values):
|
||||
if dict_values.get("title", None):
|
||||
# Adaptar dict_values a infoLabels validos
|
||||
dict_values['mediatype'] = ['movie', 'tvshow'][dict_values['mediatype']]
|
||||
for k, v in dict_values.items():
|
||||
for k, v in list(dict_values.items()):
|
||||
if k in dict_default and dict_default[k] == dict_values[k]:
|
||||
del dict_values[k]
|
||||
|
||||
|
||||
+80
-5
@@ -1,17 +1,36 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# --------------------------------------------------------------------------------
|
||||
# Scraper tools v2 for reading and processing web elements
|
||||
# Scraper tools for reading and processing web elements
|
||||
# --------------------------------------------------------------------------------
|
||||
|
||||
#from future import standard_library
|
||||
#standard_library.install_aliases()
|
||||
#from builtins import str
|
||||
#from builtins import chr
|
||||
import sys
|
||||
PY3 = False
|
||||
if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int
|
||||
|
||||
import re
|
||||
import time
|
||||
|
||||
import urlparse
|
||||
|
||||
# from core import httptools
|
||||
from core.entities import html5
|
||||
from platformcode import logger
|
||||
|
||||
|
||||
# def get_header_from_response(url, header_to_get="", post=None, headers=None):
|
||||
# header_to_get = header_to_get.lower()
|
||||
# response = httptools.downloadpage(url, post=post, headers=headers, only_headers=True)
|
||||
# return response.headers.get(header_to_get)
|
||||
|
||||
|
||||
# def read_body_and_headers(url, post=None, headers=None, follow_redirects=False, timeout=None):
|
||||
# response = httptools.downloadpage(url, post=post, headers=headers, follow_redirects=follow_redirects,
|
||||
# timeout=timeout)
|
||||
# return response.data, response.headers
|
||||
|
||||
|
||||
def printMatches(matches):
|
||||
i = 0
|
||||
for match in matches:
|
||||
@@ -89,7 +108,10 @@ def unescape(text):
|
||||
else:
|
||||
# named entity
|
||||
try:
|
||||
import htmlentitydefs
|
||||
if PY3:
|
||||
import html.entities as htmlentitydefs
|
||||
else:
|
||||
import htmlentitydefs
|
||||
text = unichr(htmlentitydefs.name2codepoint[text[1:-1]]).encode("utf-8")
|
||||
except KeyError:
|
||||
logger.error("keyerror")
|
||||
@@ -103,6 +125,50 @@ def unescape(text):
|
||||
# Convierte los codigos html "ñ" y lo reemplaza por "ñ" caracter unicode utf-8
|
||||
|
||||
|
||||
# def decodeHtmlentities(string):
|
||||
# string = entitiesfix(string)
|
||||
# entity_re = re.compile("&(#?)(\d{1,5}|\w{1,8});")
|
||||
|
||||
# def substitute_entity(match):
|
||||
# if PY3:
|
||||
# from html.entities import name2codepoint as n2cp
|
||||
# else:
|
||||
# from htmlentitydefs import name2codepoint as n2cp
|
||||
# ent = match.group(2)
|
||||
# if match.group(1) == "#":
|
||||
# return unichr(int(ent)).encode('utf-8')
|
||||
# else:
|
||||
# cp = n2cp.get(ent)
|
||||
|
||||
# if cp:
|
||||
# return unichr(cp).encode('utf-8')
|
||||
# else:
|
||||
# return match.group()
|
||||
|
||||
# return entity_re.subn(substitute_entity, string)[0]
|
||||
|
||||
|
||||
# def entitiesfix(string):
|
||||
# # Las entidades comienzan siempre con el símbolo & , y terminan con un punto y coma ( ; ).
|
||||
# string = string.replace("á", "á")
|
||||
# string = string.replace("é", "é")
|
||||
# string = string.replace("í", "í")
|
||||
# string = string.replace("ó", "ó")
|
||||
# string = string.replace("ú", "ú")
|
||||
# string = string.replace("Á", "Á")
|
||||
# string = string.replace("É", "É")
|
||||
# string = string.replace("Í", "Í")
|
||||
# string = string.replace("Ó", "Ó")
|
||||
# string = string.replace("Ú", "Ú")
|
||||
# string = string.replace("ü", "ü")
|
||||
# string = string.replace("Ü", "Ü")
|
||||
# string = string.replace("ñ", "ñ")
|
||||
# string = string.replace("¿", "¿")
|
||||
# string = string.replace("¡", "¡")
|
||||
# string = string.replace(";;", ";")
|
||||
# return string
|
||||
|
||||
|
||||
def htmlclean(cadena):
|
||||
cadena = re.compile("<!--.*?-->", re.DOTALL).sub("", cadena)
|
||||
|
||||
@@ -292,8 +358,12 @@ def remove_show_from_title(title, show):
|
||||
return title
|
||||
|
||||
|
||||
# scrapertools.get_filename_from_url(media_url)[-4:]
|
||||
def get_filename_from_url(url):
|
||||
if PY3:
|
||||
import urllib.parse as urlparse # Es muy lento en PY2. En PY3 es nativo
|
||||
else:
|
||||
import urlparse # Usamos el nativo de PY2 que es más rápido
|
||||
|
||||
parsed_url = urlparse.urlparse(url)
|
||||
try:
|
||||
filename = parsed_url.path
|
||||
@@ -311,6 +381,11 @@ def get_filename_from_url(url):
|
||||
|
||||
|
||||
def get_domain_from_url(url):
|
||||
if PY3:
|
||||
import urllib.parse as urlparse # Es muy lento en PY2. En PY3 es nativo
|
||||
else:
|
||||
import urlparse # Usamos el nativo de PY2 que es más rápido
|
||||
|
||||
parsed_url = urlparse.urlparse(url)
|
||||
try:
|
||||
filename = parsed_url.netloc
|
||||
|
||||
+96
-65
@@ -3,18 +3,32 @@
|
||||
# Server management
|
||||
# --------------------------------------------------------------------------------
|
||||
|
||||
import os
|
||||
from __future__ import division
|
||||
from __future__ import absolute_import
|
||||
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 urlparse # Es muy lento en PY2. En PY3 es nativo
|
||||
else:
|
||||
import urlparse # Usamos el nativo de PY2 que es más rápido
|
||||
|
||||
from future.builtins import range
|
||||
from past.utils import old_div
|
||||
|
||||
import datetime
|
||||
import re
|
||||
import time
|
||||
|
||||
import filetools
|
||||
import urlparse
|
||||
|
||||
from core import filetools
|
||||
from core import httptools
|
||||
from core import jsontools
|
||||
from core.item import Item
|
||||
from platformcode import config, logger
|
||||
from platformcode import platformtools
|
||||
# from servers.decrypters import zcrypt
|
||||
from lib import unshortenit
|
||||
|
||||
dict_servers_parameters = {}
|
||||
@@ -80,7 +94,7 @@ def get_servers_itemlist(itemlist, fnc=None, sort=False):
|
||||
@type sort: bool
|
||||
"""
|
||||
# Recorre los servidores
|
||||
for serverid in get_servers_list().keys():
|
||||
for serverid in list(get_servers_list().keys()):
|
||||
server_parameters = get_server_parameters(serverid)
|
||||
|
||||
# Recorre los patrones
|
||||
@@ -105,18 +119,18 @@ def get_servers_itemlist(itemlist, fnc=None, sort=False):
|
||||
item.url = url
|
||||
|
||||
# Eliminamos los servidores desactivados
|
||||
itemlist = filter(lambda i: not i.server or is_server_enabled(i.server), itemlist)
|
||||
#itemlist = filter(lambda i: not i.server or is_server_enabled(i.server), itemlist)
|
||||
# Filtrar si es necesario
|
||||
itemlist = filter_servers(itemlist)
|
||||
|
||||
for item in itemlist:
|
||||
# Asignamos "directo" en caso de que el server no se encuentre en pelisalcarta
|
||||
# Asignamos "directo" en caso de que el server no se encuentre en Alfa
|
||||
if not item.server and item.url:
|
||||
item.server = 'directo'
|
||||
item.server = "directo"
|
||||
|
||||
if fnc:
|
||||
item.title = fnc(item)
|
||||
|
||||
# Filtrar si es necesario
|
||||
itemlist = filter_servers(itemlist)
|
||||
|
||||
# Ordenar segun favoriteslist si es necesario
|
||||
if sort:
|
||||
@@ -137,7 +151,8 @@ def findvideos(data, skip=False):
|
||||
logger.info()
|
||||
devuelve = []
|
||||
skip = int(skip)
|
||||
servers_list = get_servers_list().keys()
|
||||
servers_list = list(get_servers_list().keys())
|
||||
|
||||
|
||||
# Ordenar segun favoriteslist si es necesario
|
||||
servers_list = sort_servers(servers_list)
|
||||
@@ -145,8 +160,8 @@ def findvideos(data, skip=False):
|
||||
|
||||
# Ejecuta el findvideos en cada servidor activo
|
||||
for serverid in servers_list:
|
||||
if not is_server_enabled(serverid):
|
||||
continue
|
||||
'''if not is_server_enabled(serverid):
|
||||
continue'''
|
||||
if config.get_setting("filter_servers") == True and config.get_setting("black_list", server=serverid):
|
||||
is_filter_servers = True
|
||||
continue
|
||||
@@ -167,6 +182,8 @@ def findvideosbyserver(data, serverid):
|
||||
return []
|
||||
|
||||
server_parameters = get_server_parameters(serverid)
|
||||
if not server_parameters["active"]:
|
||||
return []
|
||||
devuelve = []
|
||||
if "find_videos" in server_parameters:
|
||||
# Recorre los patrones
|
||||
@@ -229,6 +246,8 @@ def resolve_video_urls_for_playing(server, url, video_password="", muestra_dialo
|
||||
|
||||
# Si el vídeo es "directo" o "local", no hay que buscar más
|
||||
if server == "directo" or server == "local":
|
||||
if isinstance(video_password, list):
|
||||
return video_password, len(video_password) > 0, "<br/>".join(error_messages)
|
||||
logger.info("Server: %s, la url es la buena" % server)
|
||||
video_urls.append(["%s [%s]" % (urlparse.urlparse(url)[2][-4:], server), url])
|
||||
|
||||
@@ -309,7 +328,7 @@ def resolve_video_urls_for_playing(server, url, video_password="", muestra_dialo
|
||||
|
||||
# Muestra el progreso
|
||||
if muestra_dialogo:
|
||||
progreso.update((100 / len(opciones)) * opciones.index(opcion), config.get_localized_string(70180) % server_name)
|
||||
progreso.update((old_div(100, len(opciones))) * opciones.index(opcion), config.get_localized_string(70180) % server_name)
|
||||
|
||||
# Modo free
|
||||
if opcion == "free":
|
||||
@@ -377,7 +396,7 @@ def get_server_name(serverid):
|
||||
serverid = serverid.lower().split(".")[0]
|
||||
|
||||
# Obtenemos el listado de servers
|
||||
server_list = get_servers_list().keys()
|
||||
server_list = list(get_servers_list().keys())
|
||||
|
||||
# Si el nombre está en la lista
|
||||
if serverid in server_list:
|
||||
@@ -445,25 +464,25 @@ def get_server_parameters(server):
|
||||
if server not in dict_servers_parameters:
|
||||
try:
|
||||
# Servers
|
||||
if os.path.isfile(os.path.join(config.get_runtime_path(), "servers", server + ".json")):
|
||||
path = os.path.join(config.get_runtime_path(), "servers", server + ".json")
|
||||
if filetools.isfile(filetools.join(config.get_runtime_path(), "servers", server + ".json")):
|
||||
path = filetools.join(config.get_runtime_path(), "servers", server + ".json")
|
||||
|
||||
# Debriders
|
||||
elif os.path.isfile(os.path.join(config.get_runtime_path(), "servers", "debriders", server + ".json")):
|
||||
path = os.path.join(config.get_runtime_path(), "servers", "debriders", server + ".json")
|
||||
elif filetools.isfile(filetools.join(config.get_runtime_path(), "servers", "debriders", server + ".json")):
|
||||
path = filetools.join(config.get_runtime_path(), "servers", "debriders", server + ".json")
|
||||
#
|
||||
#Cuando no está bien definido el server en el canal (no existe conector), muestra error por no haber "path" y se tiene que revisar el canal
|
||||
#
|
||||
data = filetools.read(path)
|
||||
dict_server = jsontools.load(data)
|
||||
dict_server = jsontools.load(filetools.read(path))
|
||||
|
||||
# Imagenes: se admiten url y archivos locales dentro de "resources/images"
|
||||
if dict_server.get("thumbnail") and "://" not in dict_server["thumbnail"]:
|
||||
dict_server["thumbnail"] = os.path.join("https://raw.githubusercontent.com/kodiondemand/media/master/resources/servers", dict_server["thumbnail"])
|
||||
dict_server["thumbnail"] = filetools.join(config.get_runtime_path(), "resources", "media",
|
||||
"servers", dict_server["thumbnail"])
|
||||
for k in ['premium', 'id']:
|
||||
dict_server[k] = dict_server.get(k, list())
|
||||
|
||||
if type(dict_server[k]) == str:
|
||||
if isinstance(dict_server[k], str):
|
||||
dict_server[k] = [dict_server[k]]
|
||||
|
||||
if "find_videos" in dict_server:
|
||||
@@ -497,7 +516,7 @@ def get_server_json(server_name):
|
||||
server_json = jsontools.load(filetools.read(server_path))
|
||||
# logger.info("server_json= %s" % server_json)
|
||||
|
||||
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(" %s" % message)
|
||||
@@ -554,16 +573,16 @@ def get_server_setting(name, server, default=None):
|
||||
|
||||
"""
|
||||
# Creamos la carpeta si no existe
|
||||
if not os.path.exists(os.path.join(config.get_data_path(), "settings_servers")):
|
||||
os.mkdir(os.path.join(config.get_data_path(), "settings_servers"))
|
||||
if not filetools.exists(filetools.join(config.get_data_path(), "settings_servers")):
|
||||
filetools.mkdir(filetools.join(config.get_data_path(), "settings_servers"))
|
||||
|
||||
file_settings = os.path.join(config.get_data_path(), "settings_servers", server + "_data.json")
|
||||
file_settings = filetools.join(config.get_data_path(), "settings_servers", server + "_data.json")
|
||||
dict_settings = {}
|
||||
dict_file = {}
|
||||
if os.path.exists(file_settings):
|
||||
if filetools.exists(file_settings):
|
||||
# Obtenemos configuracion guardada de ../settings/channel_data.json
|
||||
try:
|
||||
dict_file = jsontools.load(open(file_settings, "rb").read())
|
||||
dict_file = jsontools.load(filetools.read(file_settings))
|
||||
if isinstance(dict_file, dict) and 'settings' in dict_file:
|
||||
dict_settings = dict_file['settings']
|
||||
except EnvironmentError:
|
||||
@@ -580,10 +599,7 @@ def get_server_setting(name, server, default=None):
|
||||
dict_settings = default_settings
|
||||
dict_file['settings'] = dict_settings
|
||||
# Creamos el archivo ../settings/channel_data.json
|
||||
json_data = jsontools.dump(dict_file)
|
||||
try:
|
||||
open(file_settings, "wb").write(json_data)
|
||||
except EnvironmentError:
|
||||
if not filetools.write(file_settings, jsontools.dump(dict_file)):
|
||||
logger.info("ERROR al salvar el archivo: %s" % file_settings)
|
||||
|
||||
# Devolvemos el valor del parametro local 'name' si existe, si no se devuelve default
|
||||
@@ -592,18 +608,18 @@ def get_server_setting(name, server, default=None):
|
||||
|
||||
def set_server_setting(name, value, server):
|
||||
# Creamos la carpeta si no existe
|
||||
if not os.path.exists(os.path.join(config.get_data_path(), "settings_servers")):
|
||||
os.mkdir(os.path.join(config.get_data_path(), "settings_servers"))
|
||||
if not filetools.exists(filetools.join(config.get_data_path(), "settings_servers")):
|
||||
filetools.mkdir(filetools.join(config.get_data_path(), "settings_servers"))
|
||||
|
||||
file_settings = os.path.join(config.get_data_path(), "settings_servers", server + "_data.json")
|
||||
file_settings = filetools.join(config.get_data_path(), "settings_servers", server + "_data.json")
|
||||
dict_settings = {}
|
||||
|
||||
dict_file = None
|
||||
|
||||
if os.path.exists(file_settings):
|
||||
if filetools.exists(file_settings):
|
||||
# Obtenemos configuracion guardada de ../settings/channel_data.json
|
||||
try:
|
||||
dict_file = jsontools.load(open(file_settings, "r").read())
|
||||
dict_file = jsontools.load(filetools.read(file_settings))
|
||||
dict_settings = dict_file.get('settings', {})
|
||||
except EnvironmentError:
|
||||
logger.info("ERROR al leer el archivo: %s" % file_settings)
|
||||
@@ -617,10 +633,7 @@ def set_server_setting(name, value, server):
|
||||
dict_file['settings'] = dict_settings
|
||||
|
||||
# Creamos el archivo ../settings/channel_data.json
|
||||
try:
|
||||
json_data = jsontools.dump(dict_file)
|
||||
open(file_settings, "w").write(json_data)
|
||||
except EnvironmentError:
|
||||
if not filetools.write(file_settings, jsontools.dump(dict_file)):
|
||||
logger.info("ERROR al salvar el archivo: %s" % file_settings)
|
||||
return None
|
||||
|
||||
@@ -636,11 +649,10 @@ def get_servers_list():
|
||||
@rtype: dict
|
||||
"""
|
||||
server_list = {}
|
||||
for server in os.listdir(os.path.join(config.get_runtime_path(), "servers")):
|
||||
for server in filetools.listdir(filetools.join(config.get_runtime_path(), "servers")):
|
||||
if server.endswith(".json") and not server == "version.json":
|
||||
server_parameters = get_server_parameters(server)
|
||||
if server_parameters["active"] == True:
|
||||
server_list[server.split(".")[0]] = server_parameters
|
||||
server_list[server.split(".")[0]] = server_parameters
|
||||
|
||||
return server_list
|
||||
|
||||
@@ -654,7 +666,7 @@ def get_debriders_list():
|
||||
@rtype: dict
|
||||
"""
|
||||
server_list = {}
|
||||
for server in os.listdir(os.path.join(config.get_runtime_path(), "servers", "debriders")):
|
||||
for server in filetools.listdir(filetools.join(config.get_runtime_path(), "servers", "debriders")):
|
||||
if server.endswith(".json"):
|
||||
server_parameters = get_server_parameters(server)
|
||||
if server_parameters["active"] == True:
|
||||
@@ -678,6 +690,7 @@ def sort_servers(servers_list):
|
||||
else:
|
||||
servers_list = sorted(servers_list,
|
||||
key=lambda x: config.get_setting("favorites_servers_list", server=x) or 100)
|
||||
|
||||
return servers_list
|
||||
|
||||
|
||||
@@ -689,18 +702,26 @@ def filter_servers(servers_list):
|
||||
u objetos Item. En cuyo caso es necesario q tengan un atributo item.server del tipo str.
|
||||
:return: Lista del mismo tipo de objetos que servers_list filtrada en funcion de la Lista Negra.
|
||||
"""
|
||||
#Eliminamos los inactivos
|
||||
if servers_list:
|
||||
servers_list = [i for i in servers_list if not i.server or is_server_enabled(i.server)]
|
||||
|
||||
|
||||
if servers_list and config.get_setting('filter_servers'):
|
||||
if isinstance(servers_list[0], Item):
|
||||
servers_list_filter = filter(lambda x: not config.get_setting("black_list", server=x.server), servers_list)
|
||||
servers_list_filter = [x for x in servers_list if not config.get_setting("black_list", server=x.server)]
|
||||
else:
|
||||
servers_list_filter = filter(lambda x: not config.get_setting("black_list", server=x), servers_list)
|
||||
servers_list_filter = [x for x in servers_list if not config.get_setting("black_list", server=x)]
|
||||
|
||||
# Si no hay enlaces despues de filtrarlos
|
||||
if servers_list_filter or not platformtools.dialog_yesno(config.get_localized_string(60000),
|
||||
config.get_localized_string(60010),
|
||||
config.get_localized_string(70281)):
|
||||
servers_list = servers_list_filter
|
||||
|
||||
|
||||
if config.get_setting("favorites_servers") == True:
|
||||
servers_list = sort_servers(servers_list)
|
||||
|
||||
return servers_list
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -715,21 +736,31 @@ def check_list_links(itemlist, numero='', timeout=3):
|
||||
El parámetro timeout indica un tope de espera para descargar la página
|
||||
"""
|
||||
numero = ((int(numero) + 1) * 5) if numero != '' else 10
|
||||
for it in itemlist:
|
||||
if numero > 0 and it.server != '' and it.url != '':
|
||||
verificacion = check_video_link(it.url, it.server, timeout)
|
||||
it.title = verificacion + ' ' + it.title.strip()
|
||||
logger.info('VERIFICATION= '+ verificacion)
|
||||
it.alive = verificacion
|
||||
numero -= 1
|
||||
from lib.concurrent import futures
|
||||
with futures.ThreadPoolExecutor() as executor:
|
||||
checked = []
|
||||
for it in itemlist:
|
||||
if numero > 0 and it.server != '' and it.url != '':
|
||||
checked.append(executor.submit(check_video_link, it, timeout))
|
||||
numero -= 1
|
||||
for link in futures.as_completed(checked):
|
||||
res = link.result()
|
||||
if res:
|
||||
it = res[0]
|
||||
verificacion = res[1]
|
||||
it.title = verificacion + ' ' + it.title.strip()
|
||||
logger.info('VERIFICATION= ' + verificacion)
|
||||
it.alive = verificacion
|
||||
return itemlist
|
||||
|
||||
def check_video_link(url, server, timeout=3):
|
||||
"""
|
||||
Comprueba si el enlace a un video es valido y devuelve un string de 2 posiciones con la verificacion.
|
||||
:param url, server: Link y servidor
|
||||
:return: str(2) '??':No se ha podido comprobar. 'Ok':Parece que el link funciona. 'NO':Parece que no funciona.
|
||||
def check_video_link(item, timeout=3):
|
||||
"""
|
||||
Comprueba si el enlace a un video es valido y devuelve un string de 2 posiciones con la verificacion.
|
||||
:param url, server: Link y servidor
|
||||
:return: str(2) '??':No se ha podido comprobar. 'Ok':Parece que el link funciona. 'NO':Parece que no funciona.
|
||||
"""
|
||||
url = item.url
|
||||
server = item.server
|
||||
|
||||
NK = "[COLOR 0xFFF9B613][B]" + u"\u2022".encode('utf-8') + "[/B][/COLOR]"
|
||||
OK = "[COLOR 0xFF00C289][B]" + u"\u2022".encode('utf-8') + "[/B][/COLOR]"
|
||||
@@ -744,7 +775,7 @@ def check_video_link(url, server, timeout=3):
|
||||
except:
|
||||
server_module = None
|
||||
logger.info("[check_video_link] No se puede importar el servidor! %s" % server)
|
||||
return NK
|
||||
return item, NK
|
||||
|
||||
if hasattr(server_module, 'test_video_exists'):
|
||||
ant_timeout = httptools.HTTPTOOLS_DEFAULT_DOWNLOAD_TIMEOUT
|
||||
@@ -764,7 +795,7 @@ def check_video_link(url, server, timeout=3):
|
||||
|
||||
finally:
|
||||
httptools.HTTPTOOLS_DEFAULT_DOWNLOAD_TIMEOUT = ant_timeout # Restaurar tiempo de descarga
|
||||
return resultado
|
||||
return item, resultado
|
||||
|
||||
logger.info("[check_video_link] No hay test_video_exists para servidor: %s" % server)
|
||||
return NK
|
||||
return item, NK
|
||||
|
||||
+59
-26
@@ -10,8 +10,10 @@ from concurrent import futures
|
||||
try:
|
||||
import urllib.request as urllib
|
||||
import urllib.parse as urlparse
|
||||
from urllib.parse import urlencode
|
||||
except ImportError:
|
||||
import urllib, urlparse
|
||||
from urllib import urlencode
|
||||
|
||||
from channelselector import thumb
|
||||
from core import httptools, scrapertools, servertools, tmdb, channeltools
|
||||
@@ -157,7 +159,8 @@ def scrapeLang(scraped, lang, longtitle):
|
||||
return language, longtitle
|
||||
|
||||
def cleantitle(title):
|
||||
cleantitle = scrapertools.htmlclean(scrapertools.decodeHtmlentities(title).replace('"', "'").replace('×', 'x').replace('–', '-')).strip()
|
||||
if type(title) != str: title.decode('UTF-8')
|
||||
cleantitle = title.replace('"', "'").replace('×', 'x').replace('–', '-').strip()
|
||||
return cleantitle
|
||||
|
||||
def scrapeBlock(item, args, block, patron, headers, action, pagination, debug, typeContentDict, typeActionDict, blacklist, search, pag, function, lang):
|
||||
@@ -192,16 +195,17 @@ def scrapeBlock(item, args, block, patron, headers, action, pagination, debug, t
|
||||
for i, match in enumerate(matches):
|
||||
if pagination and (pag - 1) * pagination > i and not search: continue # pagination
|
||||
if pagination and i >= pag * pagination and not search: break # pagination
|
||||
listGroups = match.keys()
|
||||
match = match.values()
|
||||
# listGroups = match.keys()
|
||||
# match = match.values()
|
||||
|
||||
if len(listGroups) > len(match): # to fix a bug
|
||||
match = list(match)
|
||||
match.extend([''] * (len(listGroups) - len(match)))
|
||||
# if len(listGroups) > len(match): # to fix a bug
|
||||
# match = list(match)
|
||||
# match.extend([''] * (len(listGroups) - len(match)))
|
||||
|
||||
scraped = {}
|
||||
for kk in known_keys:
|
||||
val = match[listGroups.index(kk)] if kk in listGroups else ''
|
||||
val = match[kk] if kk in match else ''
|
||||
# val = match[listGroups.index(kk)] if kk in listGroups else ''
|
||||
if val and (kk == "url" or kk == 'thumb') and 'http' not in val:
|
||||
val = scrapertools.find_single_match(item.url, 'https?://[a-z0-9.-]+') + (val if val.startswith('/') else '/' + val)
|
||||
scraped[kk] = val
|
||||
@@ -294,8 +298,10 @@ def scrapeBlock(item, args, block, patron, headers, action, pagination, debug, t
|
||||
other = scraped['other'] if scraped['other'] else ''
|
||||
)
|
||||
|
||||
for lg in list(set(listGroups).difference(known_keys)):
|
||||
it.__setattr__(lg, match[listGroups.index(lg)])
|
||||
# for lg in list(set(listGroups).difference(known_keys)):
|
||||
# it.__setattr__(lg, match[listGroups.index(lg)])
|
||||
for lg in list(set(match.keys()).difference(known_keys)):
|
||||
it.__setattr__(lg, match[lg])
|
||||
|
||||
if 'itemHook' in args:
|
||||
it = args['itemHook'](it)
|
||||
@@ -367,7 +373,7 @@ def scrape(func):
|
||||
|
||||
log('PATRON= ', patron)
|
||||
if not data:
|
||||
page = httptools.downloadpage(item.url, headers=headers, ignore_response_code=True, session=item.session)
|
||||
page = httptools.downloadpage(item.url, headers=headers, ignore_response_code=True)
|
||||
# if url may be changed and channel has findhost to update
|
||||
if (not page.data or scrapertools.get_domain_from_url(page.url) != scrapertools.get_domain_from_url(item.url)) and 'findhost' in func.__globals__:
|
||||
host = func.__globals__['findhost']()
|
||||
@@ -376,8 +382,7 @@ def scrape(func):
|
||||
jsontools.update_node(host, func.__module__.split('.')[-1], 'url')
|
||||
parse[1] = scrapertools.get_domain_from_url(host)
|
||||
item.url = urlparse.urlunparse(parse)
|
||||
page = httptools.downloadpage(item.url, headers=headers, ignore_response_code=True,
|
||||
session=item.session)
|
||||
page = httptools.downloadpage(item.url, headers=headers, ignore_response_code=True)
|
||||
data = page.data.replace("'", '"')
|
||||
data = re.sub('\n|\t', ' ', data)
|
||||
data = re.sub(r'>\s+<', '> <', data)
|
||||
@@ -468,7 +473,7 @@ def dooplay_get_links(item, host):
|
||||
ret = []
|
||||
|
||||
for type, post, nume, title, server in matches:
|
||||
postData = urllib.urlencode({
|
||||
postData = urlencode({
|
||||
"action": "doo_player_ajax",
|
||||
"post": post,
|
||||
"nume": nume,
|
||||
@@ -582,7 +587,7 @@ def swzz_get_url(item):
|
||||
elif 'https://stayonline.pro' in item.url:
|
||||
id = item.url.split('/')[-2]
|
||||
reqUrl = 'https://stayonline.pro/ajax/linkView.php'
|
||||
p = urllib.urlencode({"id": id})
|
||||
p = urlencode({"id": id})
|
||||
data = httptools.downloadpage(reqUrl, post=p).data
|
||||
try:
|
||||
import json
|
||||
@@ -699,9 +704,9 @@ def menu(func):
|
||||
if global_search:
|
||||
menuItem(itemlist, filename, config.get_localized_string(70741) % '… bold', 'search', host + dictUrl['search'])
|
||||
|
||||
|
||||
autoplay.init(item.channel, list_servers, list_quality)
|
||||
autoplay.show_option(item.channel, itemlist)
|
||||
if 'get_channel_results' not in inspect.stack()[1][3]:
|
||||
autoplay.init(item.channel, list_servers, list_quality)
|
||||
autoplay.show_option(item.channel, itemlist)
|
||||
channel_config(item, itemlist)
|
||||
|
||||
return itemlist
|
||||
@@ -744,7 +749,7 @@ def typo(string, typography=''):
|
||||
if '{}' in string:
|
||||
string = '{' + re.sub(r'\s\{\}','',string) + '}'
|
||||
if 'submenu' in string:
|
||||
string = u"\u2022\u2022 ".encode('utf-8') + re.sub(r'\ssubmenu','',string)
|
||||
string = "•• " + re.sub(r'\ssubmenu','',string)
|
||||
if 'color' in string:
|
||||
color = scrapertools.find_single_match(string, 'color ([a-z]+)')
|
||||
if color == 'kod' or '': color = kod_color
|
||||
@@ -758,7 +763,7 @@ def typo(string, typography=''):
|
||||
if '--' in string:
|
||||
string = ' - ' + re.sub(r'\s--','',string)
|
||||
if 'bullet' in string:
|
||||
string = '[B]' + u"\u2022".encode('utf-8') + '[/B] ' + re.sub(r'\sbullet','',string)
|
||||
string = '[B]' + "•" + '[/B] ' + re.sub(r'\sbullet','',string)
|
||||
|
||||
return string
|
||||
|
||||
@@ -766,10 +771,33 @@ def typo(string, typography=''):
|
||||
def match(item_url_string, **args):
|
||||
'''
|
||||
match is a function that combines httptools and scraper tools:
|
||||
|
||||
supports all httptools and the following arggs:
|
||||
@param item_url_string: if it's a titem download the page item.url, if it's a URL download the page, if it's a string pass it to scrapertools
|
||||
@type item_url_string: item or str
|
||||
@param string: force item_url_string to be a string
|
||||
@type string: bool
|
||||
@param patronBlock: find first element in patron
|
||||
@type patronBlock: str
|
||||
@param patronBloks: find multiple matches
|
||||
@type patronBloks: str or list
|
||||
@param debugBlock: regex101.com for debug
|
||||
@type debugBlock: bool
|
||||
@param patron: find multiple matches on block, blocks or data
|
||||
@type patron: str or list
|
||||
@param debug: regex101.com for debug
|
||||
@type debug: bool
|
||||
|
||||
Return a item with the following key:
|
||||
data: data of the webpage
|
||||
block: first block
|
||||
blocks: all the blocks
|
||||
match: first match
|
||||
matches: all the matches
|
||||
'''
|
||||
log(item_url_string)
|
||||
|
||||
matches = []
|
||||
matches = blocks = []
|
||||
url = None
|
||||
# arguments allowed for scrape
|
||||
patron = args.get('patron', None)
|
||||
@@ -778,12 +806,15 @@ def match(item_url_string, **args):
|
||||
debug = args.get('debug', False)
|
||||
debugBlock = args.get('debugBlock', False)
|
||||
string = args.get('string', False)
|
||||
|
||||
# remove scrape arguments
|
||||
args = dict([(key, val) for key, val in args.items() if key not in ['patron', 'patronBlock', 'patronBlocks', 'debug', 'debugBlock', 'string']])
|
||||
# dbg()
|
||||
|
||||
# check type of item_url_string
|
||||
if type(item_url_string) == str:
|
||||
if item_url_string.startswith('http') and not string: url = item_url_string
|
||||
if string:
|
||||
data = item_url_string
|
||||
elif type(item_url_string) == str:
|
||||
if item_url_string.startswith('http'): url = item_url_string
|
||||
else : data = item_url_string
|
||||
else:
|
||||
# if item_url_string is an item use item.url as url
|
||||
@@ -803,7 +834,9 @@ def match(item_url_string, **args):
|
||||
if patronBlock:
|
||||
blocks = [scrapertools.find_single_match(data, patronBlock)]
|
||||
elif patronBlocks:
|
||||
blocks = scrapertools.find_multiple_matches(data, patronBlock)
|
||||
if type(patronBlock) == str: patron = [patronBlock]
|
||||
for p in patronBlock:
|
||||
blocks += scrapertools.find_multiple_matches(data, p)
|
||||
else:
|
||||
blocks = [data]
|
||||
|
||||
@@ -1010,7 +1043,7 @@ def server(item, data='', itemlist=[], headers='', AutoPlay=True, CheckLinks=Tru
|
||||
|
||||
item.title = typo(item.contentTitle.strip(),'bold') if item.contentType == 'movie' or (config.get_localized_string(30161) in item.title) else item.title
|
||||
|
||||
videoitem.plot= typo(videoitem.title, 'bold')
|
||||
videoitem.plot= typo(videoitem.title, 'bold') + typo(videoitem.quality, '_ [] bold')
|
||||
videoitem.title = item.title + (typo(videoitem.title, '_ color kod [] bold') if videoitem.title else "") + (typo(videoitem.quality, '_ color kod []') if videoitem.quality else "")
|
||||
videoitem.fulltitle = item.fulltitle
|
||||
videoitem.show = item.show
|
||||
@@ -1036,7 +1069,7 @@ def controls(itemlist, item, AutoPlay=True, CheckLinks=True, down_load=True):
|
||||
channel_node = autoplay_node.get(item.channel, {})
|
||||
settings_node = channel_node.get('settings', {})
|
||||
AP = get_setting('autoplay') or settings_node['active']
|
||||
HS = config.get_setting('hide_servers') or (settings_node['hide_servers'] if settings_node.has_key('hide_server') else False)
|
||||
HS = config.get_setting('hide_servers') or (settings_node['hide_servers'] if 'hide_server' in settings_node else False)
|
||||
|
||||
if CL and not AP:
|
||||
if get_setting('checklinks', item.channel):
|
||||
|
||||
+75
-39
@@ -1,10 +1,26 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#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.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
|
||||
|
||||
from future.builtins import range
|
||||
from future.builtins import object
|
||||
|
||||
import ast
|
||||
|
||||
import copy
|
||||
import re
|
||||
import sqlite3
|
||||
import time
|
||||
import urllib
|
||||
|
||||
import xbmcaddon
|
||||
|
||||
@@ -37,8 +53,8 @@ def_lang = addon.getSetting('language')
|
||||
# tmdb.set_infoLabels(item, seekTmdb = True)
|
||||
#
|
||||
# Obtener datos basicos de una pelicula:
|
||||
# Antes de llamar al metodo set_infoLabels el titulo a buscar debe estar en item.fulltitle
|
||||
# o en item.contentTitle y el año en item.infoLabels['year'].
|
||||
# Antes de llamar al metodo set_infoLabels el titulo a buscar debe estar en item.contentTitle
|
||||
# y el año en item.infoLabels['year'].
|
||||
#
|
||||
# Obtener datos basicos de una serie:
|
||||
# Antes de llamar al metodo set_infoLabels el titulo a buscar debe estar en item.show o en
|
||||
@@ -73,7 +89,6 @@ def_lang = addon.getSetting('language')
|
||||
otmdb_global = None
|
||||
fname = filetools.join(config.get_data_path(), "kod_db.sqlite")
|
||||
|
||||
|
||||
def create_bd():
|
||||
conn = sqlite3.connect(fname)
|
||||
c = conn.cursor()
|
||||
@@ -160,7 +175,7 @@ def cache_response(fn):
|
||||
conn = sqlite3.connect(fname, timeout=15)
|
||||
c = conn.cursor()
|
||||
url = re.sub('&year=-', '', args[0])
|
||||
# logger.error('la url %s' % url)
|
||||
if PY3: url = str.encode(url)
|
||||
url_base64 = base64.b64encode(url)
|
||||
c.execute("SELECT response, added FROM tmdb_cache WHERE url=?", (url_base64,))
|
||||
row = c.fetchone()
|
||||
@@ -171,7 +186,9 @@ def cache_response(fn):
|
||||
# si no se ha obtenido información, llamamos a la funcion
|
||||
if not result:
|
||||
result = fn(*args)
|
||||
result_base64 = base64.b64encode(str(result))
|
||||
result = str(result)
|
||||
if PY3: result = str.encode(result)
|
||||
result_base64 = base64.b64encode(result)
|
||||
c.execute("INSERT OR REPLACE INTO tmdb_cache (url, response, added) VALUES (?, ?, ?)",
|
||||
(url_base64, result_base64, time.time()))
|
||||
|
||||
@@ -375,17 +392,19 @@ def set_infoLabels_item(item, seekTmdb=True, idioma_busqueda=def_lang, lock=None
|
||||
# ... buscar datos temporada
|
||||
item.infoLabels['mediatype'] = 'season'
|
||||
temporada = otmdb_global.get_temporada(numtemporada)
|
||||
if not isinstance(temporada, dict):
|
||||
temporada = ast.literal_eval(temporada.decode('utf-8'))
|
||||
|
||||
if temporada:
|
||||
# Actualizar datos
|
||||
__leer_datos(otmdb_global)
|
||||
item.infoLabels['title'] = temporada['name'] if temporada.has_key('name') else ''
|
||||
if temporada.has_key('overview') and temporada['overview']:
|
||||
item.infoLabels['title'] = temporada['name'] if 'name' in temporada else ''
|
||||
if 'overview' in temporada and temporada['overview']:
|
||||
item.infoLabels['plot'] = temporada['overview']
|
||||
if temporada.has_key('air_date') and temporada['air_date']:
|
||||
if 'air_date' in temporada and temporada['air_date']:
|
||||
date = temporada['air_date'].split('-')
|
||||
item.infoLabels['aired'] = date[2] + "/" + date[1] + "/" + date[0]
|
||||
if temporada.has_key('poster_path') and temporada['poster_path']:
|
||||
if 'poster_path' in temporada and temporada['poster_path']:
|
||||
item.infoLabels['poster_path'] = 'http://image.tmdb.org/t/p/original' + temporada['poster_path']
|
||||
item.thumbnail = item.infoLabels['poster_path']
|
||||
|
||||
@@ -445,12 +464,8 @@ def set_infoLabels_item(item, seekTmdb=True, idioma_busqueda=def_lang, lock=None
|
||||
# Busqueda de pelicula por titulo...
|
||||
if item.infoLabels['year'] or item.infoLabels['filtro']:
|
||||
# ...y año o filtro
|
||||
if item.contentTitle:
|
||||
titulo_buscado = item.contentTitle
|
||||
else:
|
||||
titulo_buscado = item.fulltitle
|
||||
|
||||
otmdb = Tmdb(texto_buscado=titulo_buscado, tipo=tipo_busqueda, idioma_busqueda=idioma_busqueda,
|
||||
searched_title = item.contentTitle if item.contentTitle else item.fulltitle
|
||||
otmdb = Tmdb(texto_buscado=searched_title, tipo=tipo_busqueda, idioma_busqueda=idioma_busqueda,
|
||||
filtro=item.infoLabels.get('filtro', {}), year=item.infoLabels['year'])
|
||||
if otmdb is not None:
|
||||
if otmdb.get_id() and config.get_setting("tmdb_plus_info", default=False):
|
||||
@@ -492,7 +507,7 @@ def find_and_set_infoLabels(item):
|
||||
title = title.replace(year, "").strip()
|
||||
item.infoLabels['year'] = year[1:-1]
|
||||
|
||||
if not item.infoLabels.get("tmdb_id"):
|
||||
if not item.infoLabels.get("tmdb_id") or not item.infoLabels.get("tmdb_id")[0].isdigit():
|
||||
if not item.infoLabels.get("imdb_id"):
|
||||
otmdb_global = Tmdb(texto_buscado=title, tipo=tipo_busqueda, year=item.infoLabels['year'])
|
||||
else:
|
||||
@@ -588,7 +603,6 @@ def get_genres(type):
|
||||
return genres.dic_generos[lang]
|
||||
|
||||
|
||||
|
||||
# Clase auxiliar
|
||||
class ResultDictDefault(dict):
|
||||
# Python 2.4
|
||||
@@ -606,7 +620,7 @@ class ResultDictDefault(dict):
|
||||
return list()
|
||||
elif key == 'images_posters':
|
||||
posters = dict()
|
||||
if 'images' in super(ResultDictDefault, self).keys() and \
|
||||
if 'images' in list(super(ResultDictDefault, self).keys()) and \
|
||||
'posters' in super(ResultDictDefault, self).__getitem__('images'):
|
||||
posters = super(ResultDictDefault, self).__getitem__('images')['posters']
|
||||
super(ResultDictDefault, self).__setattr__("images_posters", posters)
|
||||
@@ -615,7 +629,7 @@ class ResultDictDefault(dict):
|
||||
|
||||
elif key == "images_backdrops":
|
||||
backdrops = dict()
|
||||
if 'images' in super(ResultDictDefault, self).keys() and \
|
||||
if 'images' in list(super(ResultDictDefault, self).keys()) and \
|
||||
'backdrops' in super(ResultDictDefault, self).__getitem__('images'):
|
||||
backdrops = super(ResultDictDefault, self).__getitem__('images')['backdrops']
|
||||
super(ResultDictDefault, self).__setattr__("images_backdrops", backdrops)
|
||||
@@ -624,7 +638,7 @@ class ResultDictDefault(dict):
|
||||
|
||||
elif key == "images_profiles":
|
||||
profiles = dict()
|
||||
if 'images' in super(ResultDictDefault, self).keys() and \
|
||||
if 'images' in list(super(ResultDictDefault, self).keys()) and \
|
||||
'profiles' in super(ResultDictDefault, self).__getitem__('images'):
|
||||
profiles = super(ResultDictDefault, self).__getitem__('images')['profiles']
|
||||
super(ResultDictDefault, self).__setattr__("images_profiles", profiles)
|
||||
@@ -640,7 +654,7 @@ class ResultDictDefault(dict):
|
||||
|
||||
def tostring(self, separador=',\n'):
|
||||
ls = []
|
||||
for i in super(ResultDictDefault, self).items():
|
||||
for i in list(super(ResultDictDefault, self).items()):
|
||||
i_str = str(i)[1:-1]
|
||||
if isinstance(i[0], str):
|
||||
old = i[0] + "',"
|
||||
@@ -899,12 +913,16 @@ class Tmdb(object):
|
||||
logger.info("[Tmdb.py] Filling in dictionary of genres")
|
||||
|
||||
resultado = cls.get_json(url)
|
||||
if not isinstance(resultado, dict):
|
||||
resultado = ast.literal_eval(resultado.decode('utf-8'))
|
||||
lista_generos = resultado["genres"]
|
||||
|
||||
for i in lista_generos:
|
||||
cls.dic_generos[idioma][tipo][str(i["id"])] = i["name"]
|
||||
except:
|
||||
logger.error("Error generating dictionaries")
|
||||
import traceback
|
||||
logger.error(traceback.format_exc())
|
||||
|
||||
def __by_id(self, source='tmdb'):
|
||||
|
||||
@@ -926,6 +944,8 @@ class Tmdb(object):
|
||||
|
||||
logger.info("[Tmdb.py] Searching %s:\n%s" % (buscando, url))
|
||||
resultado = self.get_json(url)
|
||||
if not isinstance(resultado, dict):
|
||||
resultado = ast.literal_eval(resultado.decode('utf-8'))
|
||||
|
||||
if resultado:
|
||||
if source != "tmdb":
|
||||
@@ -942,14 +962,14 @@ class Tmdb(object):
|
||||
else:
|
||||
# No hay resultados de la busqueda
|
||||
msg = "The search of %s gave no results" % buscando
|
||||
# logger.debug(msg)
|
||||
logger.debug(msg)
|
||||
|
||||
def __search(self, index_results=0, page=1):
|
||||
self.result = ResultDictDefault()
|
||||
results = []
|
||||
total_results = 0
|
||||
text_simple = self.busqueda_texto.lower()
|
||||
text_quote = urllib.quote(text_simple)
|
||||
total_results = 0
|
||||
total_pages = 0
|
||||
buscando = ""
|
||||
|
||||
@@ -957,15 +977,17 @@ class Tmdb(object):
|
||||
# http://api.themoviedb.org/3/search/movie?api_key=a1ab8b8669da03637a4b98fa39c39228&query=superman&language=es
|
||||
# &include_adult=false&page=1
|
||||
url = ('http://api.themoviedb.org/3/search/%s?api_key=a1ab8b8669da03637a4b98fa39c39228&query=%s&language=%s'
|
||||
'&include_adult=%s&page=%s' % (self.busqueda_tipo, text_quote.replace(' ', '%20'),
|
||||
'&include_adult=%s&page=%s' % (self.busqueda_tipo, text_quote,
|
||||
self.busqueda_idioma, self.busqueda_include_adult, page))
|
||||
|
||||
if self.busqueda_year:
|
||||
url += '&year=%s' % self.busqueda_year
|
||||
|
||||
buscando = self.busqueda_texto.capitalize()
|
||||
logger.info("[Tmdb.py] Searching %s on page %s:\n%s" % (buscando, page, url))
|
||||
logger.info("[Tmdb.py] Buscando %s en pagina %s:\n%s" % (buscando, page, url))
|
||||
resultado = self.get_json(url)
|
||||
if not isinstance(resultado, dict):
|
||||
resultado = ast.literal_eval(resultado.decode('utf-8'))
|
||||
|
||||
total_results = resultado.get("total_results", 0)
|
||||
total_pages = resultado.get("total_pages", 0)
|
||||
@@ -973,11 +995,13 @@ class Tmdb(object):
|
||||
if total_results > 0:
|
||||
results = resultado["results"]
|
||||
|
||||
if self.busqueda_filtro and results:
|
||||
if self.busqueda_filtro and total_results > 1:
|
||||
# TODO documentar esta parte
|
||||
for key, value in dict(self.busqueda_filtro).items():
|
||||
for key, value in list(dict(self.busqueda_filtro).items()):
|
||||
for r in results[:]:
|
||||
if key not in r or r[key] != value:
|
||||
if not r[key]:
|
||||
r[key] = str(r[key])
|
||||
if key not in r or value not in r[key]:
|
||||
results.remove(r)
|
||||
total_results -= 1
|
||||
|
||||
@@ -1015,7 +1039,7 @@ class Tmdb(object):
|
||||
type_search = self.discover.get('url', '')
|
||||
if type_search:
|
||||
params = []
|
||||
for key, value in self.discover.items():
|
||||
for key, value in list(self.discover.items()):
|
||||
if key != "url":
|
||||
params.append(key + "=" + str(value))
|
||||
# http://api.themoviedb.org/3/discover/movie?api_key=a1ab8b8669da03637a4b98fa39c39228&query=superman&language=es
|
||||
@@ -1024,6 +1048,8 @@ class Tmdb(object):
|
||||
|
||||
logger.info("[Tmdb.py] Searcing %s:\n%s" % (type_search, url))
|
||||
resultado = self.get_json(url)
|
||||
if not isinstance(resultado, dict):
|
||||
resultado = ast.literal_eval(resultado.decode('utf-8'))
|
||||
|
||||
total_results = resultado.get("total_results", -1)
|
||||
total_pages = resultado.get("total_pages", 1)
|
||||
@@ -1036,7 +1062,7 @@ class Tmdb(object):
|
||||
results = resultado["results"]
|
||||
if self.busqueda_filtro and results:
|
||||
# TODO documentar esta parte
|
||||
for key, value in dict(self.busqueda_filtro).items():
|
||||
for key, value in list(dict(self.busqueda_filtro).items()):
|
||||
for r in results[:]:
|
||||
if key not in r or r[key] != value:
|
||||
results.remove(r)
|
||||
@@ -1184,6 +1210,8 @@ class Tmdb(object):
|
||||
(self.busqueda_tipo, self.busqueda_id, self.busqueda_idioma))
|
||||
|
||||
resultado = self.get_json(url)
|
||||
if not isinstance(resultado, dict):
|
||||
resultado = ast.literal_eval(resultado.decode('utf-8'))
|
||||
|
||||
if 'overview' in resultado:
|
||||
self.result['overview'] = resultado['overview']
|
||||
@@ -1316,6 +1344,8 @@ class Tmdb(object):
|
||||
logger.info("[Tmdb.py] Searcing " + buscando)
|
||||
try:
|
||||
self.temporada[numtemporada] = self.get_json(url)
|
||||
if not isinstance(self.temporada[numtemporada], dict):
|
||||
self.temporada[numtemporada] = ast.literal_eval(self.temporada[numtemporada].decode('utf-8'))
|
||||
|
||||
except:
|
||||
logger.error("Unable to get the season")
|
||||
@@ -1356,6 +1386,8 @@ class Tmdb(object):
|
||||
return {}
|
||||
|
||||
temporada = self.get_temporada(numtemporada)
|
||||
if not isinstance(temporada, dict):
|
||||
temporada = ast.literal_eval(temporada.decode('utf-8'))
|
||||
if not temporada:
|
||||
# Se ha producido un error
|
||||
return {}
|
||||
@@ -1388,9 +1420,9 @@ class Tmdb(object):
|
||||
dic_aux = dict((i['id'], i) for i in ret_dic["temporada_crew"])
|
||||
for e in temporada["episodes"]:
|
||||
for crew in e['crew']:
|
||||
if crew['id'] not in dic_aux.keys():
|
||||
if crew['id'] not in list(dic_aux.keys()):
|
||||
dic_aux[crew['id']] = crew
|
||||
ret_dic["temporada_crew"] = dic_aux.values()
|
||||
ret_dic["temporada_crew"] = list(dic_aux.values())
|
||||
|
||||
# Obtener datos del capitulo si procede
|
||||
if capitulo != -1:
|
||||
@@ -1429,6 +1461,8 @@ class Tmdb(object):
|
||||
% (self.busqueda_tipo, self.result['id'], self.busqueda_idioma)
|
||||
|
||||
dict_videos = self.get_json(url)
|
||||
if not isinstance(dict_videos, dict):
|
||||
dict_videos = ast.literal_eval(dict_videos.decode('utf-8'))
|
||||
|
||||
if dict_videos['results']:
|
||||
dict_videos['results'] = sorted(dict_videos['results'], key=lambda x: (x['type'], x['size']))
|
||||
@@ -1440,6 +1474,8 @@ class Tmdb(object):
|
||||
% (self.busqueda_tipo, self.result['id'])
|
||||
|
||||
dict_videos = self.get_json(url)
|
||||
if not isinstance(dict_videos, dict):
|
||||
dict_videos = ast.literal_eval(dict_videos.decode('utf-8'))
|
||||
|
||||
if dict_videos['results']:
|
||||
dict_videos['results'] = sorted(dict_videos['results'], key=lambda x: (x['type'], x['size']))
|
||||
@@ -1481,13 +1517,13 @@ class Tmdb(object):
|
||||
if not origen:
|
||||
origen = self.result
|
||||
|
||||
if 'credits' in origen.keys():
|
||||
if 'credits' in list(origen.keys()):
|
||||
dic_origen_credits = origen['credits']
|
||||
origen['credits_cast'] = dic_origen_credits.get('cast', [])
|
||||
origen['credits_crew'] = dic_origen_credits.get('crew', [])
|
||||
del origen['credits']
|
||||
|
||||
items = origen.items()
|
||||
items = list(origen.items())
|
||||
|
||||
# Informacion Temporada/episodio
|
||||
if ret_infoLabels['season'] and self.temporada.get(ret_infoLabels['season']):
|
||||
@@ -1496,14 +1532,14 @@ class Tmdb(object):
|
||||
if ret_infoLabels['episode']:
|
||||
episodio = ret_infoLabels['episode']
|
||||
|
||||
items.extend(self.get_episodio(ret_infoLabels['season'], episodio).items())
|
||||
items.extend(list(self.get_episodio(ret_infoLabels['season'], episodio).items()))
|
||||
|
||||
# logger.info("ret_infoLabels" % ret_infoLabels)
|
||||
|
||||
for k, v in items:
|
||||
if not v:
|
||||
continue
|
||||
elif type(v) == str:
|
||||
elif isinstance(v, str):
|
||||
v = re.sub(r"\n|\r|\t", "", v)
|
||||
# fix
|
||||
if v == "None":
|
||||
@@ -1517,7 +1553,7 @@ class Tmdb(object):
|
||||
|
||||
elif k == 'runtime': #Duration for movies
|
||||
ret_infoLabels['duration'] = int(v) * 60
|
||||
|
||||
|
||||
elif k == 'episode_run_time': #Duration for episodes
|
||||
try:
|
||||
for v_alt in v: #It comes as a list (?!)
|
||||
@@ -1572,7 +1608,7 @@ class Tmdb(object):
|
||||
|
||||
elif k == 'credits_cast' or k == 'temporada_cast' or k == 'episodio_guest_stars':
|
||||
dic_aux = dict((name, character) for (name, character) in l_castandrole)
|
||||
l_castandrole.extend([(p['name'], p['character']) for p in v if p['name'] not in dic_aux.keys()])
|
||||
l_castandrole.extend([(p['name'], p['character']) for p in v if p['name'] not in list(dic_aux.keys())])
|
||||
|
||||
elif k == 'videos':
|
||||
if not isinstance(v, list):
|
||||
|
||||
+44
-42
@@ -7,9 +7,14 @@
|
||||
# del addon y también Kodi.
|
||||
# ------------------------------------------------------------
|
||||
|
||||
import re
|
||||
from future import standard_library
|
||||
standard_library.install_aliases()
|
||||
#from builtins import str
|
||||
from future.builtins import object
|
||||
|
||||
import urllib2
|
||||
import urllib.request, urllib.error, urllib.parse
|
||||
|
||||
import re
|
||||
|
||||
from core import jsontools
|
||||
from core import scrapertools
|
||||
@@ -218,7 +223,7 @@ def set_infoLabels_item(item):
|
||||
break
|
||||
|
||||
_next = list_episodes['links']['next']
|
||||
if type(_next) == int:
|
||||
if isinstance(_next, int):
|
||||
page = _next
|
||||
else:
|
||||
break
|
||||
@@ -330,7 +335,7 @@ def completar_codigos(item):
|
||||
break
|
||||
|
||||
|
||||
class Tvdb:
|
||||
class Tvdb(object):
|
||||
def __init__(self, **kwargs):
|
||||
|
||||
self.__check_token()
|
||||
@@ -398,12 +403,12 @@ class Tvdb:
|
||||
params = {"apikey": apikey}
|
||||
|
||||
try:
|
||||
req = urllib2.Request(url, data=jsontools.dump(params), headers=DEFAULT_HEADERS)
|
||||
response = urllib2.urlopen(req)
|
||||
req = urllib.request.Request(url, data=jsontools.dump(params), headers=DEFAULT_HEADERS)
|
||||
response = urllib.request.urlopen(req)
|
||||
html = response.read()
|
||||
response.close()
|
||||
|
||||
except Exception, ex:
|
||||
except Exception as ex:
|
||||
message = "An exception of type %s occured. Arguments:\n%s" % (type(ex).__name__, repr(ex.args))
|
||||
logger.error("error en: %s" % message)
|
||||
|
||||
@@ -426,12 +431,12 @@ class Tvdb:
|
||||
url = HOST + "/refresh_token"
|
||||
|
||||
try:
|
||||
req = urllib2.Request(url, headers=DEFAULT_HEADERS)
|
||||
response = urllib2.urlopen(req)
|
||||
req = urllib.request.Request(url, headers=DEFAULT_HEADERS)
|
||||
response = urllib.request.urlopen(req)
|
||||
html = response.read()
|
||||
response.close()
|
||||
|
||||
except urllib2.HTTPError, err:
|
||||
except urllib.error.HTTPError as err:
|
||||
logger.error("err.code es %s" % err.code)
|
||||
# si hay error 401 es que el token se ha pasado de tiempo y tenemos que volver a llamar a login
|
||||
if err.code == 401:
|
||||
@@ -439,7 +444,7 @@ class Tvdb:
|
||||
else:
|
||||
raise
|
||||
|
||||
except Exception, ex:
|
||||
except Exception as ex:
|
||||
message = "An exception of type %s occured. Arguments:\n%s" % (type(ex).__name__, repr(ex.args))
|
||||
logger.error("error en: %s" % message)
|
||||
|
||||
@@ -525,19 +530,18 @@ class Tvdb:
|
||||
params = {"airedSeason": "%s" % season, "airedEpisode": "%s" % episode}
|
||||
|
||||
try:
|
||||
import urllib
|
||||
params = urllib.urlencode(params)
|
||||
params = urllib.parse.urlencode(params)
|
||||
|
||||
url = HOST + "/series/%s/episodes/query?%s" % (_id, params)
|
||||
DEFAULT_HEADERS["Accept-Language"] = lang
|
||||
logger.debug("url: %s, \nheaders: %s" % (url, DEFAULT_HEADERS))
|
||||
|
||||
req = urllib2.Request(url, headers=DEFAULT_HEADERS)
|
||||
response = urllib2.urlopen(req)
|
||||
req = urllib.request.Request(url, headers=DEFAULT_HEADERS)
|
||||
response = urllib.request.urlopen(req)
|
||||
html = response.read()
|
||||
response.close()
|
||||
|
||||
except Exception, ex:
|
||||
except Exception as ex:
|
||||
message = "An exception of type %s occured. Arguments:\n%s" % (type(ex).__name__, repr(ex.args))
|
||||
logger.error("error en: %s" % message)
|
||||
|
||||
@@ -595,12 +599,12 @@ class Tvdb:
|
||||
url = HOST + "/series/%s/episodes?page=%s" % (_id, page)
|
||||
logger.debug("url: %s, \nheaders: %s" % (url, DEFAULT_HEADERS))
|
||||
|
||||
req = urllib2.Request(url, headers=DEFAULT_HEADERS)
|
||||
response = urllib2.urlopen(req)
|
||||
req = urllib.request.Request(url, headers=DEFAULT_HEADERS)
|
||||
response = urllib.request.urlopen(req)
|
||||
html = response.read()
|
||||
response.close()
|
||||
|
||||
except Exception, ex:
|
||||
except Exception as ex:
|
||||
message = "An exception of type %s occured. Arguments:\n%s" % (type(ex).__name__, repr(ex.args))
|
||||
logger.error("error en: %s" % message)
|
||||
|
||||
@@ -682,13 +686,13 @@ class Tvdb:
|
||||
try:
|
||||
DEFAULT_HEADERS["Accept-Language"] = lang
|
||||
logger.debug("url: %s, \nheaders: %s" % (url, DEFAULT_HEADERS))
|
||||
req = urllib2.Request(url, headers=DEFAULT_HEADERS)
|
||||
response = urllib2.urlopen(req)
|
||||
req = urllib.request.Request(url, headers=DEFAULT_HEADERS)
|
||||
response = urllib.request.urlopen(req)
|
||||
html = response.read()
|
||||
response.close()
|
||||
|
||||
except Exception, ex:
|
||||
if type(ex) == urllib2.HTTPError:
|
||||
except Exception as ex:
|
||||
if isinstance(ex, urllib).HTTPError:
|
||||
logger.debug("code es %s " % ex.code)
|
||||
|
||||
message = "An exception of type %s occured. Arguments:\n%s" % (type(ex).__name__, repr(ex.args))
|
||||
@@ -741,20 +745,19 @@ class Tvdb:
|
||||
elif zap2it_id:
|
||||
params["zap2itId"] = zap2it_id
|
||||
|
||||
import urllib
|
||||
params = urllib.urlencode(params)
|
||||
params = urllib.parse.urlencode(params)
|
||||
|
||||
DEFAULT_HEADERS["Accept-Language"] = lang
|
||||
url = HOST + "/search/series?%s" % params
|
||||
logger.debug("url: %s, \nheaders: %s" % (url, DEFAULT_HEADERS))
|
||||
|
||||
req = urllib2.Request(url, headers=DEFAULT_HEADERS)
|
||||
response = urllib2.urlopen(req)
|
||||
req = urllib.request.Request(url, headers=DEFAULT_HEADERS)
|
||||
response = urllib.request.urlopen(req)
|
||||
html = response.read()
|
||||
response.close()
|
||||
|
||||
except Exception, ex:
|
||||
if type(ex) == urllib2.HTTPError:
|
||||
except Exception as ex:
|
||||
if isinstance(ex, urllib).HTTPError:
|
||||
logger.debug("code es %s " % ex.code)
|
||||
|
||||
message = "An exception of type %s occured. Arguments:\n%s" % (type(ex).__name__, repr(ex.args))
|
||||
@@ -835,15 +838,15 @@ class Tvdb:
|
||||
|
||||
try:
|
||||
DEFAULT_HEADERS["Accept-Language"] = lang
|
||||
req = urllib2.Request(url, headers=DEFAULT_HEADERS)
|
||||
req = urllib.request.Request(url, headers=DEFAULT_HEADERS)
|
||||
logger.debug("url: %s, \nheaders: %s" % (url, DEFAULT_HEADERS))
|
||||
|
||||
response = urllib2.urlopen(req)
|
||||
response = urllib.request.urlopen(req)
|
||||
html = response.read()
|
||||
response.close()
|
||||
|
||||
except Exception, ex:
|
||||
if type(ex) == urllib2.HTTPError:
|
||||
except Exception as ex:
|
||||
if isinstance(ex, urllib).HTTPError:
|
||||
logger.debug("code es %s " % ex.code)
|
||||
|
||||
message = "An exception of type %s occured. Arguments:\n%s" % (type(ex).__name__, repr(ex.args))
|
||||
@@ -905,18 +908,17 @@ class Tvdb:
|
||||
|
||||
try:
|
||||
|
||||
import urllib
|
||||
params = urllib.urlencode(params)
|
||||
params = urllib.parse.urlencode(params)
|
||||
DEFAULT_HEADERS["Accept-Language"] = lang
|
||||
url = HOST + "/series/%s/images/query?%s" % (_id, params)
|
||||
logger.debug("url: %s, \nheaders: %s" % (url, DEFAULT_HEADERS))
|
||||
|
||||
req = urllib2.Request(url, headers=DEFAULT_HEADERS)
|
||||
response = urllib2.urlopen(req)
|
||||
req = urllib.request.Request(url, headers=DEFAULT_HEADERS)
|
||||
response = urllib.request.urlopen(req)
|
||||
html = response.read()
|
||||
response.close()
|
||||
|
||||
except Exception, ex:
|
||||
except Exception as ex:
|
||||
message = "An exception of type %s occured. Arguments:\n%s" % (type(ex).__name__, repr(ex.args))
|
||||
logger.error("error en: %s" % message)
|
||||
|
||||
@@ -946,8 +948,8 @@ class Tvdb:
|
||||
DEFAULT_HEADERS["Accept-Language"] = lang
|
||||
logger.debug("url: %s, \nheaders: %s" % (url, DEFAULT_HEADERS))
|
||||
|
||||
req = urllib2.Request(url, headers=DEFAULT_HEADERS)
|
||||
response = urllib2.urlopen(req)
|
||||
req = urllib.request.Request(url, headers=DEFAULT_HEADERS)
|
||||
response = urllib.request.urlopen(req)
|
||||
html = response.read()
|
||||
response.close()
|
||||
|
||||
@@ -1039,7 +1041,7 @@ class Tvdb:
|
||||
# origen['credits_crew'] = dic_origen_credits.get('crew', [])
|
||||
# del origen['credits']
|
||||
|
||||
items = origen.items()
|
||||
items = list(origen.items())
|
||||
|
||||
for k, v in items:
|
||||
if not v:
|
||||
@@ -1118,7 +1120,7 @@ class Tvdb:
|
||||
|
||||
elif k == 'cast':
|
||||
dic_aux = dict((name, character) for (name, character) in l_castandrole)
|
||||
l_castandrole.extend([(p['name'], p['role']) for p in v if p['name'] not in dic_aux.keys()])
|
||||
l_castandrole.extend([(p['name'], p['role']) for p in v if p['name'] not in list(dic_aux.keys())])
|
||||
|
||||
else:
|
||||
logger.debug("Atributos no añadidos: %s=%s" % (k, v))
|
||||
|
||||
+122
-179
@@ -3,6 +3,11 @@
|
||||
# Common Library Tools
|
||||
# ------------------------------------------------------------
|
||||
|
||||
#from builtins import str
|
||||
import sys
|
||||
PY3 = False
|
||||
if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int
|
||||
|
||||
import errno
|
||||
import math
|
||||
import traceback
|
||||
@@ -130,7 +135,10 @@ def save_movie(item):
|
||||
else:
|
||||
base_name = item.contentTitle
|
||||
|
||||
base_name = unicode(filetools.validate_path(base_name.replace('/', '-')), "utf8").encode("utf8")
|
||||
if not PY3:
|
||||
base_name = unicode(filetools.validate_path(base_name.replace('/', '-')), "utf8").encode("utf8")
|
||||
else:
|
||||
base_name = filetools.validate_path(base_name.replace('/', '-'))
|
||||
|
||||
if config.get_setting("lowerize_title", "videolibrary") == 0:
|
||||
base_name = base_name.lower()
|
||||
@@ -191,9 +199,12 @@ def save_movie(item):
|
||||
|
||||
# Si se ha marcado la opción de url de emergencia, se añade ésta a la película después de haber ejecutado Findvideos del canal
|
||||
try:
|
||||
headers = {}
|
||||
if item.headers:
|
||||
headers = item.headers
|
||||
channel = generictools.verify_channel(item.channel)
|
||||
if config.get_setting("emergency_urls", channel) in [1, 3]:
|
||||
item = emergency_urls(item, None, json_path)
|
||||
item = emergency_urls(item, None, json_path, headers=headers)
|
||||
if item_nfo.emergency_urls and not isinstance(item_nfo.emergency_urls, dict):
|
||||
del item_nfo.emergency_urls
|
||||
if not item_nfo.emergency_urls:
|
||||
@@ -224,7 +235,7 @@ def save_movie(item):
|
||||
return 0, 0, -1
|
||||
|
||||
def filter_list(episodelist, action=None, path=None):
|
||||
if path: path = path.decode('utf8')
|
||||
# if path: path = path.decode('utf8')
|
||||
# import xbmc
|
||||
# if xbmc.getCondVisibility('system.platform.windows') > 0: path = path.replace('smb:','').replace('/','\\')
|
||||
channel_prefs = {}
|
||||
@@ -397,17 +408,29 @@ def save_tvshow(item, episodelist):
|
||||
return 0, 0, -1, path
|
||||
|
||||
_id = item.infoLabels['code'][0]
|
||||
if not item.infoLabels['code'][0] or item.infoLabels['code'][0] == 'None':
|
||||
if item.infoLabels['code'][1] and item.infoLabels['code'][1] != 'None':
|
||||
_id = item.infoLabels['code'][1]
|
||||
elif item.infoLabels['code'][2] and item.infoLabels['code'][2] != 'None':
|
||||
_id = item.infoLabels['code'][2]
|
||||
else:
|
||||
logger.error("NO ENCONTRADO EN SCRAPER O NO TIENE code: " + item.url
|
||||
+ ' / ' + item.infoLabels['code'])
|
||||
return 0, 0, -1, path
|
||||
|
||||
if config.get_setting("original_title_folder", "videolibrary") == 1 and item.infoLabels['originaltitle']:
|
||||
base_name = item.infoLabels[u'originaltitle']
|
||||
base_name = item.infoLabels['originaltitle']
|
||||
elif item.infoLabels['tvshowtitle']:
|
||||
base_name = item.infoLabels[u'tvshowtitle']
|
||||
base_name = item.infoLabels['tvshowtitle']
|
||||
elif item.infoLabels['title']:
|
||||
base_name = item.infoLabels[u'title']
|
||||
base_name = item.infoLabels['title']
|
||||
else:
|
||||
base_name = u'%s' % item.contentSerieName
|
||||
base_name = item.contentSerieName
|
||||
|
||||
base_name = unicode(filetools.validate_path(base_name.replace('/', '-')), "utf8").encode("utf8")
|
||||
if not PY3:
|
||||
base_name = unicode(filetools.validate_path(base_name.replace('/', '-')), "utf8").encode("utf8")
|
||||
else:
|
||||
base_name = filetools.validate_path(base_name.replace('/', '-'))
|
||||
|
||||
if config.get_setting("lowerize_title", "videolibrary") == 0:
|
||||
base_name = base_name.lower()
|
||||
@@ -415,7 +438,7 @@ def save_tvshow(item, episodelist):
|
||||
for raiz, subcarpetas, ficheros in filetools.walk(TVSHOWS_PATH):
|
||||
for c in subcarpetas:
|
||||
code = scrapertools.find_single_match(c, '\[(.*?)\]')
|
||||
if code and code in item.infoLabels['code']:
|
||||
if code and code != 'None' and code in item.infoLabels['code']:
|
||||
path = filetools.join(raiz, c)
|
||||
_id = code
|
||||
break
|
||||
@@ -425,7 +448,7 @@ def save_tvshow(item, episodelist):
|
||||
logger.info("Creating series directory: " + path)
|
||||
try:
|
||||
filetools.mkdir(path)
|
||||
except OSError, exception:
|
||||
except OSError as exception:
|
||||
if exception.errno != errno.EEXIST:
|
||||
raise
|
||||
|
||||
@@ -518,7 +541,7 @@ def save_episodes(path, episodelist, serie, silent=False, overwrite=True):
|
||||
news_in_playcounts = {}
|
||||
|
||||
# Listamos todos los ficheros de la serie, asi evitamos tener que comprobar si existe uno por uno
|
||||
raiz, carpetas_series, ficheros = filetools.walk(path).next()
|
||||
raiz, carpetas_series, ficheros = next(filetools.walk(path))
|
||||
ficheros = [filetools.join(path, f) for f in ficheros]
|
||||
|
||||
nostrm_episodelist = []
|
||||
@@ -550,7 +573,11 @@ def save_episodes(path, episodelist, serie, silent=False, overwrite=True):
|
||||
tags = []
|
||||
if config.get_setting("enable_filter", "videolibrary"):
|
||||
tags = [x.strip() for x in config.get_setting("filters", "videolibrary").lower().split(",")]
|
||||
|
||||
for e in episodelist:
|
||||
headers = {}
|
||||
if e.headers:
|
||||
headers = e.headers
|
||||
if tags != [] and tags != None and any(tag in e.title.lower() for tag in tags):
|
||||
continue
|
||||
|
||||
@@ -567,31 +594,34 @@ def save_episodes(path, episodelist, serie, silent=False, overwrite=True):
|
||||
if overwrite: #pero solo si se se sobrescriben los .json
|
||||
json_epi = Item().fromjson(filetools.read(json_path)) #Leemos el .json
|
||||
if json_epi.emergency_urls: #si existen las urls de emergencia...
|
||||
e.emergency_urls = json_epi.emergency_urls #... las copiamos
|
||||
else: #y si no...
|
||||
e = emergency_urls(e, channel, json_path) #... las generamos
|
||||
e.emergency_urls = json_epi.emergency_urls #... las copiamos
|
||||
else: #y si no...
|
||||
e = emergency_urls(e, channel, json_path, headers=headers) #... las generamos
|
||||
else:
|
||||
e = emergency_urls(e, channel, json_path) #Si el episodio no existe, generamos las urls
|
||||
if e.emergency_urls: #Si ya tenemos urls...
|
||||
e = emergency_urls(e, channel, json_path, headers=headers) #Si el episodio no existe, generamos las urls
|
||||
if e.emergency_urls: #Si ya tenemos urls...
|
||||
emergency_urls_succ = True #... es un éxito y vamos a marcar el .nfo
|
||||
elif emergency_urls_stat == 2 and e.contentType == 'episode': #Borramos urls de emergencia?
|
||||
elif emergency_urls_stat == 2 and e.contentType == 'episode': #Borramos urls de emergencia?
|
||||
if e.emergency_urls: del e.emergency_urls
|
||||
emergency_urls_succ = True #... es un éxito y vamos a marcar el .nfo
|
||||
elif emergency_urls_stat == 3 and e.contentType == 'episode': #Actualizamos urls de emergencia?
|
||||
if not silent:
|
||||
p_dialog.update(0, 'Cacheando enlaces y archivos .torrent...', e.title) #progress dialog
|
||||
e = emergency_urls(e, channel, json_path) #generamos las urls
|
||||
if e.emergency_urls: #Si ya tenemos urls...
|
||||
e = emergency_urls(e, channel, json_path, headers=headers) #generamos las urls
|
||||
if e.emergency_urls: #Si ya tenemos urls...
|
||||
emergency_urls_succ = True #... es un éxito y vamos a marcar el .nfo
|
||||
|
||||
if not e.infoLabels["tmdb_id"] or (serie.infoLabels["tmdb_id"] and e.infoLabels["tmdb_id"] != serie.infoLabels["tmdb_id"]): #en series multicanal, prevalece el infolabels...
|
||||
|
||||
if not e.infoLabels["tmdb_id"] or (serie.infoLabels["tmdb_id"] and e.infoLabels["tmdb_id"] != serie.infoLabels["tmdb_id"]): #en series multicanal, prevalece el infolabels...
|
||||
e.infoLabels = serie.infoLabels #... del canal actual y no el del original
|
||||
e.contentSeason, e.contentEpisodeNumber = season_episode.split("x")
|
||||
if e.videolibray_emergency_urls:
|
||||
del e.videolibray_emergency_urls
|
||||
if e.channel_redir:
|
||||
del e.channel_redir #... y se borran las marcas de redirecciones
|
||||
new_episodelist.append(e)
|
||||
except:
|
||||
if e.contentType == 'episode':
|
||||
logger.error("Unable to save %s emergency urls in the video library" % e.contentTitle)
|
||||
logger.error(traceback.format_exc())
|
||||
continue
|
||||
|
||||
# No hay lista de episodios, no hay nada que guardar
|
||||
@@ -600,18 +630,35 @@ def save_episodes(path, episodelist, serie, silent=False, overwrite=True):
|
||||
return 0, 0, 0
|
||||
|
||||
# fix float porque la division se hace mal en python 2.x
|
||||
t = float(100) / len(new_episodelist)
|
||||
try:
|
||||
t = float(100) / len(new_episodelist)
|
||||
except:
|
||||
t = 0
|
||||
|
||||
last_season_episode = ''
|
||||
for i, e in enumerate(scraper.sort_episode_list(new_episodelist)):
|
||||
if not silent:
|
||||
p_dialog.update(int(math.ceil((i + 1) * t)), config.get_localized_string(60064), e.title)
|
||||
|
||||
high_sea = e.contentSeason
|
||||
high_epi = e.contentEpisodeNumber
|
||||
if scrapertools.find_single_match(e.title, '[a|A][l|L]\s*(\d+)'):
|
||||
high_epi = int(scrapertools.find_single_match(e.title, 'al\s*(\d+)'))
|
||||
max_sea = e.infoLabels["number_of_seasons"]
|
||||
max_epi = 0
|
||||
if e.infoLabels["number_of_seasons"] and (e.infoLabels["temporada_num_episodios"] or e.infoLabels["number_of_seasons"] == 1):
|
||||
if e.infoLabels["number_of_seasons"] == 1 and e.infoLabels["number_of_episodes"]:
|
||||
max_epi = e.infoLabels["number_of_episodes"]
|
||||
else:
|
||||
max_epi = e.infoLabels["temporada_num_episodios"]
|
||||
|
||||
season_episode = "%sx%s" % (e.contentSeason, str(e.contentEpisodeNumber).zfill(2))
|
||||
strm_path = filetools.join(path, "%s.strm" % season_episode)
|
||||
nfo_path = filetools.join(path, "%s.nfo" % season_episode)
|
||||
json_path = filetools.join(path, ("%s [%s].json" % (season_episode, e.channel)).lower())
|
||||
|
||||
if season_episode in nostrm_episodelist:
|
||||
logger.error('Error in the structure of the Video Library: Seriese ' + serie.contentSerieName + ' ' + season_episode)
|
||||
continue
|
||||
strm_exists = strm_path in ficheros
|
||||
nfo_exists = nfo_path in ficheros
|
||||
@@ -659,8 +706,10 @@ def save_episodes(path, episodelist, serie, silent=False, overwrite=True):
|
||||
if not item_nfo:
|
||||
head_nfo, item_nfo = read_nfo(nfo_path)
|
||||
|
||||
if not e.infoLabels["tmdb_id"] or (item_nfo.infoLabels["tmdb_id"] and e.infoLabels["tmdb_id"] != item_nfo.infoLabels["tmdb_id"]): #en series multicanal, prevalece el infolabels...
|
||||
e.infoLabels = item_nfo.infoLabels #... del canal actual y no el del original
|
||||
# En series multicanal, prevalece el infolabels del canal actual y no el del original
|
||||
if not e.infoLabels["tmdb_id"] or (item_nfo.infoLabels["tmdb_id"] \
|
||||
and e.infoLabels["tmdb_id"] != item_nfo.infoLabels["tmdb_id"]):
|
||||
e.infoLabels = item_nfo.infoLabels
|
||||
|
||||
if filetools.write(json_path, e.tojson()):
|
||||
if not json_exists:
|
||||
@@ -688,10 +737,12 @@ def save_episodes(path, episodelist, serie, silent=False, overwrite=True):
|
||||
if not silent and p_dialog.iscanceled():
|
||||
break
|
||||
|
||||
#logger.debug('high_sea x high_epi: %sx%s' % (str(high_sea), str(high_epi)))
|
||||
#logger.debug('max_sea x max_epi: %sx%s' % (str(max_sea), str(max_epi)))
|
||||
if not silent:
|
||||
p_dialog.close()
|
||||
|
||||
if news_in_playcounts:
|
||||
if news_in_playcounts or emergency_urls_succ or serie.infoLabels["status"] == "Ended" or serie.infoLabels["status"] == "Canceled":
|
||||
# Si hay nuevos episodios los marcamos como no vistos en tvshow.nfo ...
|
||||
tvshow_path = filetools.join(path, "tvshow.nfo")
|
||||
try:
|
||||
@@ -703,16 +754,27 @@ def save_episodes(path, episodelist, serie, silent=False, overwrite=True):
|
||||
if emergency_urls_succ:
|
||||
if tvshow_item.emergency_urls and not isinstance(tvshow_item.emergency_urls, dict):
|
||||
del tvshow_item.emergency_urls
|
||||
if emergency_urls_stat in [1, 3]: #Operación de guardar/actualizar enlaces
|
||||
if emergency_urls_stat in [1, 3]: #Operación de guardar/actualizar enlaces
|
||||
if not tvshow_item.emergency_urls:
|
||||
tvshow_item.emergency_urls = dict()
|
||||
tvshow_item.emergency_urls.update({serie.channel: True})
|
||||
elif emergency_urls_stat == 2: #Operación de Borrar enlaces
|
||||
if tvshow_item.library_urls.get(serie.channel, False):
|
||||
tvshow_item.emergency_urls.update({serie.channel: True})
|
||||
elif emergency_urls_stat == 2: #Operación de Borrar enlaces
|
||||
if tvshow_item.emergency_urls and tvshow_item.emergency_urls.get(serie.channel, False):
|
||||
tvshow_item.emergency_urls.pop(serie.channel, None) #borramos la entrada del .nfo
|
||||
tvshow_item.emergency_urls.pop(serie.channel, None) #borramos la entrada del .nfo
|
||||
|
||||
if tvshow_item.active == 30:
|
||||
tvshow_item.active = 1
|
||||
if tvshow_item.infoLabels["tmdb_id"] == serie.infoLabels["tmdb_id"]:
|
||||
tvshow_item.infoLabels = serie.infoLabels
|
||||
tvshow_item.infoLabels["title"] = tvshow_item.infoLabels["tvshowtitle"]
|
||||
|
||||
if max_sea == high_sea and max_epi == high_epi and (tvshow_item.infoLabels["status"] == "Ended"
|
||||
or tvshow_item.infoLabels["status"] == "Canceled") and insertados == 0 and fallidos == 0:
|
||||
tvshow_item.active = 0 # ... no la actualizaremos más
|
||||
logger.debug("%s [%s]: serie 'Terminada' o 'Cancelada'. Se desactiva la actualización periódica" % \
|
||||
(serie.contentSerieName, serie.channel))
|
||||
|
||||
update_last = datetime.date.today()
|
||||
tvshow_item.update_last = update_last.strftime('%Y-%m-%d')
|
||||
update_next = datetime.date.today() + datetime.timedelta(days=int(tvshow_item.active))
|
||||
@@ -819,10 +881,10 @@ def add_tvshow(item, channel=None):
|
||||
|
||||
if not channel:
|
||||
try:
|
||||
#channel = __import__('channels.%s' % item.channel, fromlist=["channels.%s" % item.channel])
|
||||
# channel = __import__('channels.%s' % item.channel, fromlist=["channels.%s" % item.channel])
|
||||
channel = __import__('specials.%s' % channel_alt, fromlist=["specials.%s" % channel_alt])
|
||||
except ImportError:
|
||||
exec "import channels." + item.channel + " as channel"
|
||||
exec("import channels." + item.channel + " as channel")
|
||||
|
||||
#Para desambiguar títulos, se provoca que TMDB pregunte por el título realmente deseado
|
||||
#El usuario puede seleccionar el título entre los ofrecidos en la primera pantalla
|
||||
@@ -836,15 +898,15 @@ def add_tvshow(item, channel=None):
|
||||
# del item.tmdb_stat #Limpiamos el status para que no se grabe en la Videoteca
|
||||
|
||||
# Obtiene el listado de episodios
|
||||
#if item.channel == 'community':
|
||||
itemlist = getattr(channel, item.action)(item)
|
||||
|
||||
global magnet_caching
|
||||
magnet_caching = False
|
||||
insertados, sobreescritos, fallidos, path = save_tvshow(item, itemlist)
|
||||
|
||||
if not insertados and not sobreescritos and not fallidos:
|
||||
platformtools.dialog_ok(config.get_localized_string(30131), config.get_localized_string(60067))
|
||||
logger.error("The %s series could not be added to the video library. Could not get any episode"
|
||||
% item.show)
|
||||
logger.error("The %s series could not be added to the video library. Could not get any episode" % item.show)
|
||||
|
||||
elif fallidos == -1:
|
||||
platformtools.dialog_ok(config.get_localized_string(30131), config.get_localized_string(60068))
|
||||
@@ -856,8 +918,7 @@ def add_tvshow(item, channel=None):
|
||||
|
||||
else:
|
||||
platformtools.dialog_ok(config.get_localized_string(30131), config.get_localized_string(60070))
|
||||
logger.info("%s episodes of the %s series have been added to the video library" %
|
||||
(insertados, item.show))
|
||||
logger.info("%s episodes of the %s series have been added to the video library" % (insertados, item.show))
|
||||
if config.is_xbmc():
|
||||
if config.get_setting("sync_trakt_new_tvshow", "videolibrary"):
|
||||
import xbmc
|
||||
@@ -872,10 +933,16 @@ def add_tvshow(item, channel=None):
|
||||
xbmc_videolibrary.sync_trakt_addon(path)
|
||||
|
||||
|
||||
def emergency_urls(item, channel=None, path=None):
|
||||
def emergency_urls(item, channel=None, path=None, headers={}):
|
||||
logger.info()
|
||||
import re
|
||||
"""
|
||||
from servers import torrent
|
||||
try:
|
||||
magnet_caching_e = magnet_caching
|
||||
except:
|
||||
magnet_caching_e = True
|
||||
|
||||
"""
|
||||
Llamamos a Findvideos del canal con la variable "item.videolibray_emergency_urls = True" para obtener la variable
|
||||
"item.emergency_urls" con la lista de listas de tuplas de los enlaces torrent y de servidores directos para ese episodio o película
|
||||
En la lista [0] siempre deben ir los enlaces torrents, si los hay. Si se desea cachear los .torrents, la búsqueda va contra esa lista.
|
||||
@@ -890,17 +957,28 @@ def emergency_urls(item, channel=None, path=None):
|
||||
if hasattr(channel, 'findvideos'): #Si el canal tiene "findvideos"...
|
||||
item.videolibray_emergency_urls = True #... se marca como "lookup"
|
||||
channel_save = item.channel #... guarda el canal original por si hay fail-over en Newpct1
|
||||
category_save = item.category #... guarda la categoría original por si hay fail-over o redirección en Newpct1
|
||||
if item.channel_redir: #... si hay un redir, se restaura temporamente el canal alternativo
|
||||
item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').lower()
|
||||
item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize()
|
||||
item_res = getattr(channel, 'findvideos')(item) #... se procesa Findvideos
|
||||
item_res.channel = channel_save #... restaura el canal original por si hay fail-over en Newpct1
|
||||
item_res.category = channel_save.capitalize() #... y la categoría
|
||||
item_res.category = category_save #... restaura la categoría original por si hay fail-over o redirección en Newpct1
|
||||
item.category = category_save #... restaura la categoría original por si hay fail-over o redirección en Newpct1
|
||||
del item_res.videolibray_emergency_urls #... y se borra la marca de lookup
|
||||
if item.videolibray_emergency_urls:
|
||||
del item.videolibray_emergency_urls #... y se borra la marca de lookup original
|
||||
except:
|
||||
logger.error('ERROR when processing the title in Findvideos del Canal: ' + item.channel + ' / ' + item.title)
|
||||
logger.error(traceback.format_exc())
|
||||
item.channel = channel_save #... restaura el canal original por si hay fail-over o redirección en Newpct1
|
||||
item.category = category_save #... restaura la categoría original por si hay fail-over o redirección en Newpct1
|
||||
item_res = item.clone() #Si ha habido un error, se devuelve el Item original
|
||||
if item_res.videolibray_emergency_urls:
|
||||
del item_res.videolibray_emergency_urls #... y se borra la marca de lookup
|
||||
|
||||
if item.videolibray_emergency_urls:
|
||||
del item.videolibray_emergency_urls #... y se borra la marca de lookup original
|
||||
|
||||
#Si el usuario ha activado la opción "emergency_urls_torrents", se descargarán los archivos .torrent de cada título
|
||||
else: #Si se han cacheado con éxito los enlaces...
|
||||
try:
|
||||
@@ -921,7 +999,9 @@ def emergency_urls(item, channel=None, path=None):
|
||||
if item_res.post: post = item_res.post
|
||||
for url in item_res.emergency_urls[0]: #Recorremos las urls de emergencia...
|
||||
torrents_path = re.sub(r'(?:\.\w+$)', '_%s.torrent' % str(i).zfill(2), path)
|
||||
path_real = caching_torrents(url, referer, post, torrents_path=torrents_path) #... para descargar los .torrents
|
||||
path_real = ''
|
||||
if magnet_caching_e or not url.startswith('magnet'):
|
||||
path_real = torrent.caching_torrents(url, referer, post, torrents_path=torrents_path, headers=headers) #... para descargar los .torrents
|
||||
if path_real: #Si ha tenido éxito...
|
||||
item_res.emergency_urls[0][i-1] = path_real.replace(videolibrary_path, '') #se guarda el "path" relativo
|
||||
i += 1
|
||||
@@ -944,140 +1024,3 @@ def emergency_urls(item, channel=None, path=None):
|
||||
|
||||
#logger.debug(item_res.emergency_urls)
|
||||
return item_res #Devolvemos el Item actualizado con los enlaces de emergencia
|
||||
|
||||
|
||||
def caching_torrents(url, referer=None, post=None, torrents_path=None, timeout=10, lookup=False, data_torrent=False):
|
||||
if torrents_path != None:
|
||||
logger.info("path = " + torrents_path)
|
||||
else:
|
||||
logger.info()
|
||||
if referer and post:
|
||||
logger.info('REFERER: ' + referer)
|
||||
from core import httptools
|
||||
torrent_file = ''
|
||||
headers = {'Content-Type': 'application/x-www-form-urlencoded', 'Referer': referer} #Necesario para el Post del .Torrent
|
||||
|
||||
"""
|
||||
Descarga en el path recibido el .torrent de la url recibida, y pasa el decode
|
||||
Devuelve el path real del .torrent, o el path vacío si la operación no ha tenido éxito
|
||||
"""
|
||||
|
||||
videolibrary_path = config.get_videolibrary_path() #Calculamos el path absoluto a partir de la Videoteca
|
||||
if torrents_path == None:
|
||||
if not videolibrary_path:
|
||||
torrents_path = ''
|
||||
if data_torrent:
|
||||
return (torrents_path, torrent_file)
|
||||
return torrents_path #Si hay un error, devolvemos el "path" vacío
|
||||
torrents_path = filetools.join(videolibrary_path, 'temp_torrents_Alfa', 'cliente_torrent_Alfa.torrent') #path de descarga temporal
|
||||
if '.torrent' not in torrents_path:
|
||||
torrents_path += '.torrent' #path para dejar el .torrent
|
||||
torrents_path_encode = filetools.encode(torrents_path) #encode utf-8 del path
|
||||
|
||||
if url.endswith(".rar") or url.startswith("magnet:"): #No es un archivo .torrent
|
||||
logger.error('It is not a Torrent file: ' + url)
|
||||
torrents_path = ''
|
||||
if data_torrent:
|
||||
return (torrents_path, torrent_file)
|
||||
return torrents_path #Si hay un error, devolvemos el "path" vacío
|
||||
|
||||
try:
|
||||
#Descargamos el .torrent
|
||||
if referer and post: #Descarga con POST
|
||||
response = httptools.downloadpage(url, headers=headers, post=post, follow_redirects=False, timeout=timeout)
|
||||
else: #Descarga sin post
|
||||
response = httptools.downloadpage(url, timeout=timeout)
|
||||
if not response.sucess:
|
||||
logger.error('.Torrent file not found: ' + url)
|
||||
torrents_path = ''
|
||||
if data_torrent:
|
||||
return (torrents_path, torrent_file)
|
||||
return torrents_path #Si hay un error, devolvemos el "path" vacío
|
||||
torrent_file = response.data
|
||||
|
||||
if "used CloudFlare" in torrent_file: #Si tiene CloudFlare, usamos este proceso
|
||||
response = httptools.downloadpage("http://anonymouse.org/cgi-bin/anon-www.cgi/" + url.strip(), timeout=timeout)
|
||||
if not response.sucess:
|
||||
logger.error('Archivo .torrent no encontrado: ' + url)
|
||||
torrents_path = ''
|
||||
if data_torrent:
|
||||
return (torrents_path, torrent_file)
|
||||
return torrents_path #Si hay un error, devolvemos el "path" vacío
|
||||
torrent_file = response.data
|
||||
|
||||
#Si es un archivo .ZIP tratamos de extraer el contenido
|
||||
if torrent_file.startswith("PK"):
|
||||
logger.info('It is a .ZIP file: ' + url)
|
||||
|
||||
torrents_path_zip = filetools.join(videolibrary_path, 'temp_torrents_zip') #Carpeta de trabajo
|
||||
torrents_path_zip = filetools.encode(torrents_path_zip)
|
||||
torrents_path_zip_file = filetools.join(torrents_path_zip, 'temp_torrents_zip.zip') #Nombre del .zip
|
||||
|
||||
import time
|
||||
filetools.rmdirtree(torrents_path_zip) #Borramos la carpeta temporal
|
||||
time.sleep(1) #Hay que esperar, porque si no da error
|
||||
filetools.mkdir(torrents_path_zip) #La creamos de nuevo
|
||||
|
||||
if filetools.write(torrents_path_zip_file, torrent_file): #Salvamos el .zip
|
||||
torrent_file = '' #Borramos el contenido en memoria
|
||||
try: #Extraemos el .zip
|
||||
from core import ziptools
|
||||
unzipper = ziptools.ziptools()
|
||||
unzipper.extract(torrents_path_zip_file, torrents_path_zip)
|
||||
except:
|
||||
import xbmc
|
||||
xbmc.executebuiltin('XBMC.Extract("%s", "%s")' % (torrents_path_zip_file, torrents_path_zip))
|
||||
time.sleep(1)
|
||||
|
||||
import os
|
||||
for root, folders, files in os.walk(torrents_path_zip): #Recorremos la carpeta para leer el .torrent
|
||||
for file in files:
|
||||
if file.endswith(".torrent"):
|
||||
input_file = filetools.join(root, file) #nombre del .torrent
|
||||
torrent_file = filetools.read(input_file) #leemos el .torrent
|
||||
|
||||
filetools.rmdirtree(torrents_path_zip) #Borramos la carpeta temporal
|
||||
|
||||
#Si no es un archivo .torrent (RAR, HTML,..., vacío) damos error
|
||||
if not scrapertools.find_single_match(torrent_file, '^d\d+:.*?\d+:'):
|
||||
logger.error('It is not a Torrent file: ' + url)
|
||||
torrents_path = ''
|
||||
if data_torrent:
|
||||
return (torrents_path, torrent_file)
|
||||
return torrents_path #Si hay un error, devolvemos el "path" vacío
|
||||
|
||||
#Salvamos el .torrent
|
||||
if not lookup:
|
||||
if not filetools.write(torrents_path_encode, torrent_file):
|
||||
logger.error('ERROR: Unwritten .torrent file: ' + torrents_path_encode)
|
||||
torrents_path = '' #Si hay un error, devolvemos el "path" vacío
|
||||
torrent_file = '' #... y el buffer del .torrent
|
||||
if data_torrent:
|
||||
return (torrents_path, torrent_file)
|
||||
return torrents_path
|
||||
except:
|
||||
torrents_path = '' #Si hay un error, devolvemos el "path" vacío
|
||||
torrent_file = '' #... y el buffer del .torrent
|
||||
logger.error('ERROR: .Torrent download process failed: ' + url + ' / ' + torrents_path_encode)
|
||||
logger.error(traceback.format_exc())
|
||||
|
||||
#logger.debug(torrents_path)
|
||||
if data_torrent:
|
||||
return (torrents_path, torrent_file)
|
||||
return torrents_path
|
||||
|
||||
|
||||
def verify_url_torrent(url, timeout=5):
|
||||
"""
|
||||
Verifica si el archivo .torrent al que apunta la url está disponible, descargándolo en un area temporal
|
||||
Entrada: url
|
||||
Salida: True o False dependiendo del resultado de la operación
|
||||
"""
|
||||
|
||||
if not url or url == 'javascript:;': #Si la url viene vacía...
|
||||
return False #... volvemos con error
|
||||
torrents_path = caching_torrents(url, timeout=timeout, lookup=True) #Descargamos el .torrent
|
||||
if torrents_path: #Si ha tenido éxito...
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
+35
-25
@@ -3,22 +3,26 @@
|
||||
# Zip Tools
|
||||
# --------------------------------------------------------------------------------
|
||||
|
||||
import io
|
||||
import os
|
||||
from builtins import object
|
||||
import sys
|
||||
PY3 = False
|
||||
VFS = True
|
||||
if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int; VFS = False
|
||||
|
||||
import zipfile
|
||||
|
||||
from platformcode import config, logger
|
||||
from core import filetools
|
||||
|
||||
|
||||
class ziptools:
|
||||
class ziptools(object):
|
||||
def extract(self, file, dir, folder_to_extract="", overwrite_question=False, backup=False):
|
||||
logger.info("file=%s" % file)
|
||||
logger.info("dir=%s" % dir)
|
||||
|
||||
if not dir.endswith(':') and not os.path.exists(dir):
|
||||
os.mkdir(dir)
|
||||
if not dir.endswith(':') and not filetools.exists(dir):
|
||||
filetools.mkdir(dir)
|
||||
|
||||
file = io.FileIO(file)
|
||||
zf = zipfile.ZipFile(file)
|
||||
if not folder_to_extract:
|
||||
self._createstructure(file, dir)
|
||||
@@ -30,60 +34,66 @@ class ziptools:
|
||||
if not name.endswith('/'):
|
||||
logger.info("no es un directorio")
|
||||
try:
|
||||
(path, filename) = os.path.split(os.path.join(dir, name))
|
||||
(path, filename) = filetools.split(filetools.join(dir, name))
|
||||
logger.info("path=%s" % path)
|
||||
logger.info("name=%s" % name)
|
||||
if folder_to_extract:
|
||||
if path != os.path.join(dir, folder_to_extract):
|
||||
if path != filetools.join(dir, folder_to_extract):
|
||||
break
|
||||
else:
|
||||
os.makedirs(path)
|
||||
filetools.mkdir(path)
|
||||
except:
|
||||
pass
|
||||
if folder_to_extract:
|
||||
outfilename = os.path.join(dir, filename)
|
||||
outfilename = filetools.join(dir, filename)
|
||||
|
||||
else:
|
||||
outfilename = os.path.join(dir, name)
|
||||
outfilename = filetools.join(dir, name)
|
||||
logger.info("outfilename=%s" % outfilename)
|
||||
try:
|
||||
if os.path.exists(outfilename) and overwrite_question:
|
||||
if filetools.exists(outfilename) and overwrite_question:
|
||||
from platformcode import platformtools
|
||||
dyesno = platformtools.dialog_yesno("El archivo ya existe",
|
||||
"El archivo %s a descomprimir ya existe" \
|
||||
", ¿desea sobrescribirlo?" \
|
||||
% os.path.basename(outfilename))
|
||||
% filetools.basename(outfilename))
|
||||
if not dyesno:
|
||||
break
|
||||
if backup:
|
||||
import time
|
||||
import shutil
|
||||
hora_folder = "Copia seguridad [%s]" % time.strftime("%d-%m_%H-%M", time.localtime())
|
||||
backup = os.path.join(config.get_data_path(), 'backups', hora_folder, folder_to_extract)
|
||||
if not os.path.exists(backup):
|
||||
os.makedirs(backup)
|
||||
shutil.copy2(outfilename, os.path.join(backup, os.path.basename(outfilename)))
|
||||
backup = filetools.join(config.get_data_path(), 'backups', hora_folder, folder_to_extract)
|
||||
if not filetools.exists(backup):
|
||||
filetools.mkdir(backup)
|
||||
filetools.copy(outfilename, filetools.join(backup, filetools.basename(outfilename)))
|
||||
|
||||
outfile = open(outfilename, 'wb')
|
||||
outfile.write(zf.read(nameo))
|
||||
if not filetools.write(outfilename, zf.read(nameo), silent=True, vfs=VFS): #TRUNCA en FINAL en Kodi 19 con VFS
|
||||
logger.error("Error en fichero " + nameo)
|
||||
except:
|
||||
import traceback
|
||||
logger.error(traceback.format_exc())
|
||||
logger.error("Error en fichero " + nameo)
|
||||
|
||||
try:
|
||||
zf.close()
|
||||
except:
|
||||
logger.info("Error cerrando .zip " + file)
|
||||
|
||||
def _createstructure(self, file, dir):
|
||||
self._makedirs(self._listdirs(file), dir)
|
||||
|
||||
def create_necessary_paths(filename):
|
||||
try:
|
||||
(path, name) = os.path.split(filename)
|
||||
os.makedirs(path)
|
||||
(path, name) = filetools.split(filename)
|
||||
filetools.mkdir(path)
|
||||
except:
|
||||
pass
|
||||
|
||||
def _makedirs(self, directories, basedir):
|
||||
for dir in directories:
|
||||
curdir = os.path.join(basedir, dir)
|
||||
if not os.path.exists(curdir):
|
||||
os.mkdir(curdir)
|
||||
curdir = filetools.join(basedir, dir)
|
||||
if not filetools.exists(curdir):
|
||||
filetools.mkdir(curdir)
|
||||
|
||||
def _listdirs(self, file):
|
||||
zf = zipfile.ZipFile(file)
|
||||
|
||||
Reference in New Issue
Block a user