KoD 0.7.1
- A grande richiesta, è ora possibile riprodurre in automatico l'episodio successivo di una serie in libreria - aggiunta la possibilità di nascondere la lista dei server, quando si usa l'autoplay - aggiunto canale pufimovies.com - fix vari
This commit is contained in:
+1
-1
@@ -123,7 +123,7 @@ def cuadro_completar(item):
|
||||
global dict_default
|
||||
dict_default = {}
|
||||
|
||||
COLOR = ["0xFF8A4B08", "0xFFF7BE81"]
|
||||
COLOR = ["0xFF65B3DA", "0xFFFFFFFF"]
|
||||
# Creamos la lista de campos del infoLabel
|
||||
controls = [("title", "text", config.get_localized_string(60230)),
|
||||
("originaltitle", "text", config.get_localized_string(60231)),
|
||||
|
||||
+90
-28
@@ -180,7 +180,7 @@ def scrapeBlock(item, args, block, patron, headers, action, pagination, debug, t
|
||||
if debug:
|
||||
regexDbg(item, patron, headers, block)
|
||||
|
||||
known_keys = ['url', 'title', 'title2', 'season', 'episode', 'thumb', 'quality', 'year', 'plot', 'duration', 'genere', 'rating', 'type', 'lang']
|
||||
known_keys = ['url', 'title', 'title2', 'season', 'episode', 'thumb', 'quality', 'year', 'plot', 'duration', 'genere', 'rating', 'type', 'lang', 'other']
|
||||
# Legenda known_keys per i groups nei patron
|
||||
# known_keys = ['url', 'title', 'title2', 'season', 'episode', 'thumb', 'quality',
|
||||
# 'year', 'plot', 'duration', 'genere', 'rating', 'type', 'lang']
|
||||
@@ -201,8 +201,8 @@ def scrapeBlock(item, args, block, patron, headers, action, pagination, debug, t
|
||||
|
||||
stagione = '' # per quei siti che hanno la stagione nel blocco ma non nelle puntate
|
||||
for i, match in enumerate(matches):
|
||||
if pagination and (pag - 1) * pagination > i: continue # pagination
|
||||
if pagination and i >= pag * pagination: break # pagination
|
||||
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()
|
||||
|
||||
@@ -214,12 +214,12 @@ def scrapeBlock(item, args, block, patron, headers, action, pagination, debug, t
|
||||
for kk in known_keys:
|
||||
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
|
||||
val = scrapertools.find_single_match(item.url, 'https?://[a-z0-9.-]+') + (val if val.startswith('/') else '/' + val)
|
||||
scraped[kk] = val
|
||||
|
||||
if scraped['season']:
|
||||
stagione = scraped['season']
|
||||
episode = scraped['season'] +'x'+ scraped['episode']
|
||||
episode = scraped['season'] +'x'+ scraped['episode'].zfill(2)
|
||||
elif item.season:
|
||||
episode = item.season +'x'+ scraped['episode']
|
||||
elif item.contentType == 'tvshow' and (scraped['episode'] == '' and scraped['season'] == '' and stagione == ''):
|
||||
@@ -295,13 +295,14 @@ def scrapeBlock(item, args, block, patron, headers, action, pagination, debug, t
|
||||
quality=quality,
|
||||
url=scraped["url"],
|
||||
infoLabels=infolabels,
|
||||
thumbnail=item.thumbnail if function == 'episodios' else scraped["thumb"] ,
|
||||
thumbnail=item.thumbnail if function == 'episodios' and not scraped["thumb"] else scraped["thumb"] ,
|
||||
args=item.args,
|
||||
contentSerieName= scraped['title'] if item.contentType or CT != 'movie' and function != 'episodios' else item.fulltitle if function == 'episodios' else '',
|
||||
contentTitle= scraped['title'] if item.contentType or CT == 'movie' else '',
|
||||
contentLanguage = lang1,
|
||||
contentEpisodeNumber=episode if episode else '',
|
||||
news= item.news if item.news else ''
|
||||
news= item.news if item.news else '',
|
||||
other = scraped['other'] if scraped['other'] else ''
|
||||
)
|
||||
|
||||
for lg in list(set(listGroups).difference(known_keys)):
|
||||
@@ -445,7 +446,7 @@ def scrape(func):
|
||||
if anime:
|
||||
if function == 'episodios' or item.action == 'episodios': autorenumber.renumber(itemlist, item, 'bold')
|
||||
else: autorenumber.renumber(itemlist)
|
||||
if anime and autorenumber.check(item) == False and not scrapertools.find_single_match(itemlist[0].title, r'(\d+.\d+)'):
|
||||
if anime and autorenumber.check(item) == False and len(itemlist)>0 and not scrapertools.find_single_match(itemlist[0].title, r'(\d+.\d+)'):
|
||||
pass
|
||||
else:
|
||||
if addVideolibrary and (item.infoLabels["title"] or item.fulltitle):
|
||||
@@ -637,8 +638,9 @@ def menu(func):
|
||||
|
||||
item = args['item']
|
||||
host = func.__globals__['host']
|
||||
list_servers = func.__globals__['list_servers'] if 'list_servers' in func.__globals__ else 'directo'
|
||||
list_quality = func.__globals__['list_quality'] if 'list_quality' in func.__globals__ else 'default'
|
||||
list_servers = func.__globals__['list_servers'] if 'list_servers' in func.__globals__ else ['directo']
|
||||
list_quality = func.__globals__['list_quality'] if 'list_quality' in func.__globals__ else ['default']
|
||||
log('LIST QUALITY', list_quality)
|
||||
filename = func.__module__.split('.')[1]
|
||||
global_search = False
|
||||
# listUrls = ['film', 'filmSub', 'tvshow', 'tvshowSub', 'anime', 'animeSub', 'search', 'top', 'topSub']
|
||||
@@ -772,31 +774,91 @@ def typo(string, typography=''):
|
||||
return string
|
||||
|
||||
|
||||
def match(item, patron='', patronBlock='', headers='', url='', post=''):
|
||||
def match(item_url_string, **args):
|
||||
'''
|
||||
match is a function that combines httptools and scraper tools:
|
||||
'''
|
||||
log(item_url_string)
|
||||
|
||||
matches = []
|
||||
if type(item) == str:
|
||||
data = item
|
||||
url = None
|
||||
# arguments allowed for scrape
|
||||
patron = args.get('patron', None)
|
||||
patronBlock = args.get('patronBlock', None)
|
||||
patronBlocks = args.get('patronBlock', None)
|
||||
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
|
||||
else : data = item_url_string
|
||||
else:
|
||||
url = url if url else item.url
|
||||
if post:
|
||||
data = httptools.downloadpage(url, headers=headers, ignore_response_code=True, post=post).data.replace("'", '"')
|
||||
else:
|
||||
data = httptools.downloadpage(url, headers=headers, ignore_response_code=True).data.replace("'", '"')
|
||||
# if item_url_string is an item use item.url as url
|
||||
url = item_url_string.url
|
||||
|
||||
# if there is a url, download the page
|
||||
if url:
|
||||
if args.get('ignore_response_code', None) is None:
|
||||
args['ignore_response_code'] = True
|
||||
data = httptools.downloadpage(url, **args).data.replace("'", '"')
|
||||
|
||||
# format page data
|
||||
data = re.sub(r'\n|\t', ' ', data)
|
||||
data = re.sub(r'>\s\s*<', '><', data)
|
||||
log('DATA= ', data)
|
||||
|
||||
# collect blocks of a page
|
||||
if patronBlock:
|
||||
block = scrapertools.find_single_match(data, patronBlock)
|
||||
log('BLOCK= ',block)
|
||||
blocks = [scrapertools.find_single_match(data, patronBlock)]
|
||||
elif patronBlocks:
|
||||
blocks = scrapertools.find_multiple_matches(data, patronBlock)
|
||||
else:
|
||||
block = data
|
||||
blocks = [data]
|
||||
|
||||
# match
|
||||
if patron:
|
||||
matches = scrapertools.find_multiple_matches(block, patron)
|
||||
log('MATCHES= ',matches)
|
||||
if type(patron) == str: patron = [patron]
|
||||
for b in blocks:
|
||||
for p in patron:
|
||||
matches += scrapertools.find_multiple_matches(b, p)
|
||||
|
||||
return matches, block
|
||||
# debug mode
|
||||
if config.dev_mode():
|
||||
if debugBlock:
|
||||
match_dbg(data, patronBlock)
|
||||
if debug:
|
||||
for block in blocks:
|
||||
for p in patron:
|
||||
match_dbg(block, p)
|
||||
|
||||
# create a item
|
||||
item = Item(data=data,
|
||||
blocks=blocks,
|
||||
block=blocks[0] if len(blocks) > 0 else '',
|
||||
matches=matches,
|
||||
match=matches[0] if len(matches) > 0 else '')
|
||||
|
||||
return item
|
||||
|
||||
|
||||
def match_dbg(data, patron):
|
||||
import json, urllib2, webbrowser
|
||||
url = 'https://regex101.com'
|
||||
headers = {'content-type': 'application/json'}
|
||||
data = {
|
||||
'regex': patron,
|
||||
'flags': 'gm',
|
||||
'testString': data,
|
||||
'delimiter': '"""',
|
||||
'flavor': 'python'
|
||||
}
|
||||
r = urllib2.Request(url + '/api/regex', json.dumps(data, encoding='latin1'), headers=headers)
|
||||
r = urllib2.urlopen(r).read()
|
||||
permaLink = json.loads(r)['permalinkFragment']
|
||||
webbrowser.open(url + "/r/" + permaLink)
|
||||
|
||||
|
||||
def download(itemlist, item, typography='', function_level=1, function=''):
|
||||
@@ -981,7 +1043,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']
|
||||
APS = get_setting('autoplay_server_list')
|
||||
HS = config.get_setting('hide_servers')
|
||||
|
||||
if CL and not AP:
|
||||
if get_setting('checklinks', item.channel):
|
||||
@@ -994,7 +1056,7 @@ def controls(itemlist, item, AutoPlay=True, CheckLinks=True, down_load=True):
|
||||
checklinks_number = get_setting('checklinks_number')
|
||||
itemlist = servertools.check_list_links(itemlist, checklinks_number)
|
||||
|
||||
if AutoPlay == True and not 'downloads' in inspect.stack()[3][1] + inspect.stack()[4][1] and item.contentChannel != 'videolibrary':
|
||||
if AutoPlay == True and not 'downloads' in inspect.stack()[3][1] + inspect.stack()[4][1]:
|
||||
autoplay.start(itemlist, item)
|
||||
|
||||
if item.contentChannel != 'videolibrary': videolibrary(itemlist, item, function_level=3)
|
||||
@@ -1010,7 +1072,7 @@ def controls(itemlist, item, AutoPlay=True, CheckLinks=True, down_load=True):
|
||||
VL = True
|
||||
except:
|
||||
pass
|
||||
if not AP or VL or not APS:
|
||||
if not AP or VL or not HS:
|
||||
return itemlist
|
||||
|
||||
def filterLang(item, itemlist):
|
||||
|
||||
+26
-25
@@ -160,7 +160,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)
|
||||
# logger.error('la url %s' % url)
|
||||
url_base64 = base64.b64encode(url)
|
||||
c.execute("SELECT response, added FROM tmdb_cache WHERE url=?", (url_base64,))
|
||||
row = c.fetchone()
|
||||
@@ -185,7 +185,7 @@ def cache_response(fn):
|
||||
# error al obtener los datos
|
||||
except Exception, ex:
|
||||
message = "An exception of type %s occured. Arguments:\n%s" % (type(ex).__name__, repr(ex.args))
|
||||
logger.error("error en: %s" % message)
|
||||
logger.error("error in: %s" % message)
|
||||
|
||||
return result
|
||||
|
||||
@@ -214,10 +214,10 @@ def set_infoLabels(source, seekTmdb=True, idioma_busqueda=def_lang, forced=False
|
||||
start_time = time.time()
|
||||
if type(source) == list:
|
||||
ret = set_infoLabels_itemlist(source, seekTmdb, idioma_busqueda)
|
||||
logger.debug("Se han obtenido los datos de %i enlaces en %f segundos" % (len(source), time.time() - start_time))
|
||||
logger.debug("The data of %i links were obtained in %f seconds" % (len(source), time.time() - start_time))
|
||||
else:
|
||||
ret = set_infoLabels_item(source, seekTmdb, idioma_busqueda)
|
||||
logger.debug("Se han obtenido los datos del enlace en %f segundos" % (time.time() - start_time))
|
||||
logger.debug("The data of %i links were obtained in %f seconds" % (time.time() - start_time))
|
||||
return ret
|
||||
|
||||
|
||||
@@ -242,6 +242,7 @@ def set_infoLabels_itemlist(item_list, seekTmdb=False, idioma_busqueda=def_lang,
|
||||
negativo en caso contrario.
|
||||
@rtype: list
|
||||
"""
|
||||
|
||||
if not config.get_setting('tmdb_active') and not forced:
|
||||
return
|
||||
import threading
|
||||
@@ -314,7 +315,7 @@ def set_infoLabels_item(item, seekTmdb=True, idioma_busqueda=def_lang, lock=None
|
||||
try:
|
||||
numtemporada = int(item.infoLabels['season'])
|
||||
except ValueError:
|
||||
logger.debug("El numero de temporada no es valido")
|
||||
logger.debug("The season number is not valid.")
|
||||
return -1 * len(item.infoLabels)
|
||||
|
||||
if lock:
|
||||
@@ -340,7 +341,7 @@ def set_infoLabels_item(item, seekTmdb=True, idioma_busqueda=def_lang, lock=None
|
||||
try:
|
||||
episode = int(item.infoLabels['episode'])
|
||||
except ValueError:
|
||||
logger.debug("El número de episodio (%s) no es valido" % repr(item.infoLabels['episode']))
|
||||
logger.debug("The episode number (%s) is not valid" % repr(item.infoLabels['episode']))
|
||||
return -1 * len(item.infoLabels)
|
||||
|
||||
# Tenemos numero de temporada y numero de episodio validos...
|
||||
@@ -847,7 +848,7 @@ class Tmdb(object):
|
||||
self.__discover()
|
||||
|
||||
else:
|
||||
logger.debug("Creado objeto vacio")
|
||||
logger.debug("Created empty object")
|
||||
|
||||
@staticmethod
|
||||
@cache_response
|
||||
@@ -879,7 +880,7 @@ class Tmdb(object):
|
||||
# error al obtener los datos
|
||||
except Exception, ex:
|
||||
message = "An exception of type %s occured. Arguments:\n%s" % (type(ex).__name__, repr(ex.args))
|
||||
logger.error("error en: %s" % message)
|
||||
logger.error("error in: %s" % message)
|
||||
dict_data = {}
|
||||
|
||||
return dict_data
|
||||
@@ -895,7 +896,7 @@ class Tmdb(object):
|
||||
url = ('http://api.themoviedb.org/3/genre/%s/list?api_key=a1ab8b8669da03637a4b98fa39c39228&language=%s'
|
||||
% (tipo, idioma))
|
||||
try:
|
||||
logger.info("[Tmdb.py] Rellenando dicionario de generos")
|
||||
logger.info("[Tmdb.py] Filling in dictionary of genres")
|
||||
|
||||
resultado = cls.get_json(url)
|
||||
lista_generos = resultado["genres"]
|
||||
@@ -903,7 +904,7 @@ class Tmdb(object):
|
||||
for i in lista_generos:
|
||||
cls.dic_generos[idioma][tipo][str(i["id"])] = i["name"]
|
||||
except:
|
||||
logger.error("Error generando diccionarios")
|
||||
logger.error("Error generating dictionaries")
|
||||
|
||||
def __by_id(self, source='tmdb'):
|
||||
|
||||
@@ -923,7 +924,7 @@ class Tmdb(object):
|
||||
'&language=%s' % (self.busqueda_id, source, self.busqueda_idioma))
|
||||
buscando = "%s: %s" % (source.capitalize(), self.busqueda_id)
|
||||
|
||||
logger.info("[Tmdb.py] Buscando %s:\n%s" % (buscando, url))
|
||||
logger.info("[Tmdb.py] Searching %s:\n%s" % (buscando, url))
|
||||
resultado = self.get_json(url)
|
||||
|
||||
if resultado:
|
||||
@@ -940,8 +941,8 @@ class Tmdb(object):
|
||||
|
||||
else:
|
||||
# No hay resultados de la busqueda
|
||||
msg = "La busqueda de %s no dio resultados." % buscando
|
||||
logger.debug(msg)
|
||||
msg = "The search of %s gave no results" % buscando
|
||||
# logger.debug(msg)
|
||||
|
||||
def __search(self, index_results=0, page=1):
|
||||
self.result = ResultDictDefault()
|
||||
@@ -963,7 +964,7 @@ class Tmdb(object):
|
||||
url += '&year=%s' % self.busqueda_year
|
||||
|
||||
buscando = self.busqueda_texto.capitalize()
|
||||
logger.info("[Tmdb.py] Buscando %s en pagina %s:\n%s" % (buscando, page, url))
|
||||
logger.info("[Tmdb.py] Searching %s on page %s:\n%s" % (buscando, page, url))
|
||||
resultado = self.get_json(url)
|
||||
|
||||
total_results = resultado.get("total_results", 0)
|
||||
@@ -984,7 +985,7 @@ class Tmdb(object):
|
||||
if index_results >= len(results):
|
||||
# Se ha solicitado un numero de resultado mayor de los obtenidos
|
||||
logger.error(
|
||||
"La busqueda de '%s' dio %s resultados para la pagina %s\nImposible mostrar el resultado numero %s"
|
||||
"The search for '%s' gave %s results for the page %s \n It is impossible to show the result number %s"
|
||||
% (buscando, len(results), page, index_results))
|
||||
return 0
|
||||
|
||||
@@ -997,7 +998,7 @@ class Tmdb(object):
|
||||
|
||||
else:
|
||||
# No hay resultados de la busqueda
|
||||
msg = "La busqueda de '%s' no dio resultados para la pagina %s" % (buscando, page)
|
||||
msg = "The search for '%s' gave no results for page %s" % (buscando, page)
|
||||
logger.error(msg)
|
||||
return 0
|
||||
|
||||
@@ -1021,7 +1022,7 @@ class Tmdb(object):
|
||||
url = ('http://api.themoviedb.org/3/%s?api_key=a1ab8b8669da03637a4b98fa39c39228&%s'
|
||||
% (type_search, "&".join(params)))
|
||||
|
||||
logger.info("[Tmdb.py] Buscando %s:\n%s" % (type_search, url))
|
||||
logger.info("[Tmdb.py] Searcing %s:\n%s" % (type_search, url))
|
||||
resultado = self.get_json(url)
|
||||
|
||||
total_results = resultado.get("total_results", -1)
|
||||
@@ -1045,7 +1046,7 @@ class Tmdb(object):
|
||||
|
||||
if index_results >= len(results):
|
||||
logger.error(
|
||||
"La busqueda de '%s' no dio %s resultados" % (type_search, index_results))
|
||||
"The search for '%s' did not give %s results" % (type_search, index_results))
|
||||
return 0
|
||||
|
||||
# Retornamos el numero de resultados de esta pagina
|
||||
@@ -1061,7 +1062,7 @@ class Tmdb(object):
|
||||
return len(self.results)
|
||||
else:
|
||||
# No hay resultados de la busqueda
|
||||
logger.error("La busqueda de '%s' no dio resultados" % type_search)
|
||||
logger.error("The search for '%s' gave no results" % type_search)
|
||||
return 0
|
||||
|
||||
def load_resultado(self, index_results=0, page=1):
|
||||
@@ -1311,20 +1312,20 @@ class Tmdb(object):
|
||||
url = "http://api.themoviedb.org/3/tv/%s/season/%s?api_key=a1ab8b8669da03637a4b98fa39c39228&language=%s" \
|
||||
"&append_to_response=credits" % (self.result["id"], numtemporada, self.busqueda_idioma)
|
||||
|
||||
buscando = "id_Tmdb: " + str(self.result["id"]) + " temporada: " + str(numtemporada) + "\nURL: " + url
|
||||
logger.info("[Tmdb.py] Buscando " + buscando)
|
||||
buscando = "id_Tmdb: " + str(self.result["id"]) + " season: " + str(numtemporada) + "\nURL: " + url
|
||||
logger.info("[Tmdb.py] Searcing " + buscando)
|
||||
try:
|
||||
self.temporada[numtemporada] = self.get_json(url)
|
||||
|
||||
except:
|
||||
logger.error("No se ha podido obtener la temporada")
|
||||
logger.error("Unable to get the season")
|
||||
self.temporada[numtemporada] = {"status_code": 15, "status_message": "Failed"}
|
||||
self.temporada[numtemporada] = {"episodes": {}}
|
||||
|
||||
if "status_code" in self.temporada[numtemporada]:
|
||||
#Se ha producido un error
|
||||
msg = config.get_localized_string(70496) + buscando + config.get_localized_string(70497)
|
||||
msg += "\nError de tmdb: %s %s" % (
|
||||
msg += "\nTmdb error: %s %s" % (
|
||||
self.temporada[numtemporada]["status_code"], self.temporada[numtemporada]["status_message"])
|
||||
logger.debug(msg)
|
||||
self.temporada[numtemporada] = {}
|
||||
@@ -1351,7 +1352,7 @@ class Tmdb(object):
|
||||
capitulo = int(capitulo)
|
||||
numtemporada = int(numtemporada)
|
||||
except ValueError:
|
||||
logger.debug("El número de episodio o temporada no es valido")
|
||||
logger.debug("The episode or season number is not valid")
|
||||
return {}
|
||||
|
||||
temporada = self.get_temporada(numtemporada)
|
||||
@@ -1361,7 +1362,7 @@ class Tmdb(object):
|
||||
|
||||
if len(temporada["episodes"]) == 0 or len(temporada["episodes"]) < capitulo:
|
||||
# Se ha producido un error
|
||||
logger.error("Episodio %d de la temporada %d no encontrado." % (capitulo, numtemporada))
|
||||
logger.error("Episode %d of the season %d not found." % (capitulo, numtemporada))
|
||||
return {}
|
||||
|
||||
ret_dic = dict()
|
||||
|
||||
Reference in New Issue
Block a user