Cacheo de enlace: nuevos canales y mejoras

Cacheo de enlaces:
- Mejores controles para el cacheo de enlaces para el contenido existiente en la Videoteca.
- Opción para cachear los archivos .torrent y almacenarlos en la Videoteca
- Mejoras en el "play" de enlaces torrent: ahora descarga siempre los .torrent en local y pasa al cliente Torrent el .torret descargado
- Usando la técnica anterior, permite al canal usar un enlace Torrent alternativo por si el enlace torrent principal no está activo.  El "play" de enlaces torrent seleciona automáticamente el .torrent alternativo si el principal no funciona.

Nuevos canales añadidos al cacheo de enlaces:
- DivxTotal
- EliteTorrent
- GranTorrent

Mejorado:
- Newpct1 (mejorada la Alta Disponibilidad en Findvideos)
This commit is contained in:
Kingbox
2018-11-07 14:21:13 +01:00
parent 615f0e3aa0
commit b51399e132
13 changed files with 689 additions and 195 deletions
+169 -16
View File
@@ -187,7 +187,7 @@ def save_movie(item):
try:
channel = generictools.verify_channel(item.channel)
if config.get_setting("emergency_urls", channel) in [1, 3]:
item = emergency_urls(item)
item = emergency_urls(item, None, json_path)
if item_nfo.emergency_urls and not isinstance(item_nfo.emergency_urls, dict):
del item_nfo.emergency_urls
if not item_nfo.emergency_urls:
@@ -396,6 +396,10 @@ def save_episodes(path, episodelist, serie, silent=False, overwrite=True):
emergency_urls_stat = config.get_setting("emergency_urls", channel_alt) #El canal quiere urls de emergencia?
emergency_urls_succ = False
channel = __import__('channels.%s' % channel_alt, fromlist=["channels.%s" % channel_alt])
if serie.torrent_caching_fail: #Si el proceso de conversión ha fallado, no se cachean
emergency_urls_stat = 0
del serie.torrent_caching_fail
new_episodelist = []
# Obtenemos el numero de temporada y episodio y descartamos los q no lo sean
tags = []
@@ -410,24 +414,24 @@ def save_episodes(path, episodelist, serie, silent=False, overwrite=True):
# Si se ha marcado la opción de url de emergencia, se añade ésta a cada episodio después de haber ejecutado Findvideos del canal
if e.emergency_urls and isinstance(e.emergency_urls, dict): del e.emergency_urls #Borramos trazas anterioires
json_path = filetools.join(path, ("%s [%s].json" % (season_episode, e.channel)).lower()) #Path del .json del episodio
if emergency_urls_stat == 1 and not e.emergency_urls and e.contentType == 'episode': #Guardamos urls de emergencia?
json_path = filetools.join(path, ("%s [%s].json" % (season_episode, e.channel)).lower()) #Path del .json del episodio
if json_path in ficheros: #Si existe el .json sacamos de ahí las urls
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) #... las generamos
e = emergency_urls(e, channel, json_path) #... las generamos
else:
e = emergency_urls(e, channel) #Si el episodio no existe, generamos las urls
e = emergency_urls(e, channel, json_path) #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?
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?
e = emergency_urls(e, channel) #generamos las urls
e = emergency_urls(e, channel, json_path) #generamos las urls
if e.emergency_urls: #Si ya tenemos urls...
emergency_urls_succ = True #... es un éxito y vamos a marcar el .nfo
@@ -711,22 +715,171 @@ def add_tvshow(item, channel=None):
xbmc_videolibrary.sync_trakt_addon(path)
def emergency_urls(item, channel=None):
def emergency_urls(item, channel=None, path=None):
logger.info()
import re
"""
Llamamos a Findvideos del canal con la variable "item.videolibray_emergency_urls = True" para obtener la variable
"item.matches" con la lista de listas de tuplas de los enlaces torrent y de servidores directos para ese episodio o película
"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.
En la lista dos irán los enlaces de servidores directos, pero también pueden ir enlaces magnet (que no son cacheables)
"""
#lanazamos un "lookup" en el "findvideos" del canal para obtener los enlaces de emergencia
try:
if channel == None:
channel = generictools.verify_channel(item.channel)
if channel == None: #Si el llamador no ha aportado la estructura de channel, se crea
channel = generictools.verify_channel(item.channel) #Se verifica si es un clon, que devuelva "newpct1"
channel = __import__('channels.%s' % channel, fromlist=["channels.%s" % channel])
if hasattr(channel, 'findvideos'):
item.videolibray_emergency_urls = True
item_res = getattr(channel, 'findvideos')(item)
del item_res.videolibray_emergency_urls
if hasattr(channel, 'findvideos'): #Si el canal tiene "findvideos"...
item.videolibray_emergency_urls = True #... se marca como "lookup"
item_res = getattr(channel, 'findvideos')(item) #... se procesa
del item_res.videolibray_emergency_urls #... y se borra la marca de lookup
except:
item_res = item.clone()
logger.error('ERROR al procesar el episodio')
item_res = item.clone() #Si ha habido un error, se devuelve el Item 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...
logger.debug('HOLA')
logger.debug(item_res.emergency_urls)
try:
channel_bis = generictools.verify_channel(item.channel)
if config.get_setting("emergency_urls_torrents", channel_bis) and item_res.emergency_urls and path != None:
videolibrary_path = config.get_videolibrary_path() #detectamos el path absoluto del título
movies = config.get_setting("folder_movies")
series = config.get_setting("folder_tvshows")
if movies in path:
folder = movies
else:
folder = series
videolibrary_path = filetools.join(videolibrary_path, folder)
i = 1
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, torrents_path=torrents_path) #... 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
except:
item_res = item.clone() #Si ha habido un error, se devuelve el Item original
#logger.debug(item_res.emergency_urls)
return item_res
return item_res #Devolvemos el Item actualizado con los enlaces de emergencia
def caching_torrents(url, torrents_path=None, decode_flag=False, timeout=10, lookup=False):
if torrents_path != None:
logger.info("path = " + torrents_path)
else:
logger.info()
import urllib
import re
from core import httptools
"""
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
"""
def decode(text):
try:
src = tokenize(text)
data = decode_item(src.next, src.next())
for token in src: # look for more tokens
raise SyntaxError("trailing junk")
except (AttributeError, ValueError, StopIteration):
try:
data = data
except:
data = src
return data
def tokenize(text, match=re.compile("([idel])|(\d+):|(-?\d+)").match):
i = 0
while i < len(text):
m = match(text, i)
s = m.group(m.lastindex)
i = m.end()
if m.lastindex == 2:
yield "s"
yield text[i:i + int(s)]
i = i + int(s)
else:
yield s
def decode_item(next, token):
if token == "i":
# integer: "i" value "e"
data = int(next())
if next() != "e":
raise ValueError
elif token == "s":
# string: "s" value (virtual tokens)
data = next()
elif token == "l" or token == "d":
# container: "l" (or "d") values "e"
data = []
tok = next()
while tok != "e":
data.append(decode_item(next, tok))
tok = next()
if token == "d":
data = dict(zip(data[0::2], data[1::2]))
else:
raise ValueError
return data
#Módulo PRINCIPAL
try:
if lookup:
torrents_path = lookup
else:
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
response = httptools.downloadpage(url, timeout=timeout) #Descargamos el .torrent
if not response.sucess:
logger.error('Archivo .torrent no encontrado: ' + url)
torrents_path = ''
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 = ''
return torrents_path #Si hay un error, devolvemos el "path" vacío
torrent_file = response.data
if decode_flag:
torrent_file = decode(torrent_file) #decodificamos el .torrent
if not lookup:
filetools.write(torrents_path_encode, torrent_file) #Salvamos el .torrent
except:
torrents_path = '' #Si hay un error, devolvemos el "path" vacío
#logger.debug(torrents_path)
return torrents_path
def verify_url_torrent(url, decode_flag=False, 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, sin decode
if torrents_path: #Si ha tenido éxito...
return True
try:
torrents_path = caching_torrents(url, timeout=timeout, lookup=True) #Descargamos el .torrent, sin decode
if torrents_path: #Si ha tenido éxito...
return True
except:
return False #en caso de error, False