Files
addon/plugin.video.alfa/channels/news.py
2017-07-28 19:37:39 -04:00

483 lines
19 KiB
Python
Executable File

# -*- coding: utf-8 -*-
# ------------------------------------------------------------
# Channel for recent videos on several channels
# ------------------------------------------------------------
import glob
import os
import re
import time
from threading import Thread
from core import channeltools
from core import config
from core import logger
from core import scrapertools
from core.item import Item
from platformcode import platformtools
THUMBNAILS = {'0': 'posters', '1': 'banners', '2': 'squares'}
__perfil__ = config.get_setting('perfil', "news")
# Fijar perfil de color
perfil = [['0xFF0B7B92', '0xFF89FDFB', '0xFFACD5D4'],
['0xFFB31313', '0xFFFF9000', '0xFFFFEE82'],
['0xFF891180', '0xFFCB22D7', '0xFFEEA1EB'],
['0xFFA5DEE5', '0xFFE0F9B5', '0xFFFEFDCA'],
['0xFFF23557', '0xFF22B2DA', '0xFFF0D43A']]
color1, color2, color3 = perfil[__perfil__]
list_newest = []
channels_id_name = {}
def mainlist(item):
logger.info()
itemlist = []
list_canales = get_channels_list()
if list_canales['peliculas']:
thumbnail = config.get_thumb("thumb_channels_movie.png")
new_item = Item(channel=item.channel, action="novedades", extra="peliculas", title="Películas",
thumbnail=thumbnail)
new_item.context = [{"title": "Canales incluidos en: %s" % new_item.title,
"extra": new_item.extra,
"action": "setting_channel",
"channel": new_item.channel}]
new_item.category = "Novedades en %s" % new_item.extra
itemlist.append(new_item)
if list_canales['infantiles']:
thumbnail = config.get_thumb("thumb_channels_children.png")
new_item = Item(channel=item.channel, action="novedades", extra="infantiles", title="Para niños",
thumbnail=thumbnail)
new_item.context = [{"title": "Canales incluidos en: %s" % new_item.title,
"extra": new_item.extra,
"action": "setting_channel",
"channel": new_item.channel}]
new_item.category = "Novedades en %s" % new_item.extra
itemlist.append(new_item)
if list_canales['series']:
thumbnail = config.get_thumb("thumb_channels_tvshow.png")
new_item = Item(channel=item.channel, action="novedades", extra="series", title="Episodios de series",
thumbnail=thumbnail)
new_item.context = [{"title": "Canales incluidos en: %s" % new_item.title,
"extra": new_item.extra,
"action": "setting_channel",
"channel": new_item.channel}]
new_item.category = "Novedades en %s" % new_item.extra
itemlist.append(new_item)
if list_canales['anime']:
thumbnail = config.get_thumb("thumb_channels_anime.png")
new_item = Item(channel=item.channel, action="novedades", extra="anime", title="Episodios de anime",
thumbnail=thumbnail)
new_item.context = [{"title": "Canales incluidos en: %s" % new_item.title,
"extra": new_item.extra,
"action": "setting_channel",
"channel": new_item.channel}]
new_item.category = "Novedades en %s" % new_item.extra
itemlist.append(new_item)
if list_canales['documentales']:
thumbnail = config.get_thumb("thumb_channels_documentary.png")
new_item = Item(channel=item.channel, action="novedades", extra="documentales", title="Documentales",
thumbnail=thumbnail)
new_item.context = [{"title": "Canales incluidos en: %s" % new_item.title,
"extra": new_item.extra,
"action": "setting_channel",
"channel": new_item.channel}]
new_item.category = "Novedades en %s" % new_item.extra
itemlist.append(new_item)
return itemlist
def get_channels_list():
logger.info()
list_canales = {'peliculas': [], 'infantiles': [], 'series': [], 'anime': [], 'documentales': []}
# Rellenar listas de canales disponibles
channels_path = os.path.join(config.get_runtime_path(), "channels", '*.json')
channel_language = config.get_setting("channel_language")
if channel_language == "":
channel_language = "all"
for infile in sorted(glob.glob(channels_path)):
channel_id = os.path.basename(infile)[:-5]
channel_parameters = channeltools.get_channel_parameters(channel_id)
# No incluir si es un canal inactivo
if not channel_parameters["active"]:
continue
# No incluir si es un canal para adultos, y el modo adulto está desactivado
if channel_parameters["adult"] and config.get_setting("adult_mode") == 0:
continue
# No incluir si el canal es en un idioma filtrado
if channel_language != "all" and channel_parameters["language"] != channel_language:
continue
# Incluir en cada categoria, si en su configuracion el canal esta activado para mostrar novedades
for categoria in list_canales:
include_in_newest = config.get_setting("include_in_newest_" + categoria, channel_id)
if include_in_newest:
channels_id_name[channel_id] = channel_parameters["title"]
list_canales[categoria].append((channel_id, channel_parameters["title"]))
return list_canales
def novedades(item):
logger.info()
global list_newest
threads = []
list_newest = []
start_time = time.time()
multithread = config.get_setting("multithread", "news")
logger.info("multithread= " + str(multithread))
if not multithread:
if platformtools.dialog_yesno("Búsqueda concurrente desactivada",
"La búsqueda concurrente de novedades proporciona",
"una mayor velocidad y su desactivación solo es aconsejable en caso de fallo.",
"¿Desea activar la búsqueda concurrente ahora?"):
if config.set_setting("multithread", True, "news"):
multithread = True
progreso = platformtools.dialog_progress(item.category, "Buscando canales...")
list_canales = get_channels_list()
import math
# fix float porque la division se hace mal en python 2.x
number_of_channels = float(100) / len(list_canales[item.extra])
for index, channel in enumerate(list_canales[item.extra]):
channel_id, channel_title = channel
percentage = int(math.ceil((index + 1) * number_of_channels))
# if progreso.iscanceled():
# progreso.close()
# logger.info("Búsqueda cancelada")
# return itemlist
# Modo Multi Thread
if multithread:
t = Thread(target=get_newest, args=[channel_id, item.extra], name=channel_title)
t.start()
threads.append(t)
progreso.update(percentage, "", "Buscando en '%s'..." % channel_title)
# Modo single Thread
else:
logger.info("Obteniendo novedades de channel_id=" + channel_id)
progreso.update(percentage, "", "Buscando en '%s'..." % channel_title)
get_newest(channel_id, item.extra)
# Modo Multi Thread: esperar q todos los hilos terminen
if multithread:
pendent = [a for a in threads if a.isAlive()]
t = float(100) / len(pendent)
while pendent:
index = (len(threads) - len(pendent)) + 1
percentage = int(math.ceil(index * t))
list_pendent_names = [a.getName() for a in pendent]
mensaje = "Buscando en %s" % (", ".join(list_pendent_names))
progreso.update(percentage, "Finalizado en %d/%d canales..." % (len(threads) - len(pendent), len(threads)),
mensaje)
logger.debug(mensaje)
if progreso.iscanceled():
logger.info("Busqueda de novedades cancelada")
break
time.sleep(0.5)
pendent = [a for a in threads if a.isAlive()]
mensaje = "Resultados obtenidos: %s | Tiempo: %2.f segundos" % (len(list_newest), time.time()-start_time)
progreso.update(100, mensaje, " ", " ")
logger.info(mensaje)
start_time = time.time()
# logger.debug(start_time)
result_mode = config.get_setting("result_mode", "news")
if result_mode == 0: # Agrupados por contenido
ret = group_by_content(list_newest)
elif result_mode == 1: # Agrupados por canales
ret = group_by_channel(list_newest)
else: # Sin agrupar
ret = no_group(list_newest)
while time.time() - start_time < 2:
# mostrar cuadro de progreso con el tiempo empleado durante almenos 2 segundos
time.sleep(0.5)
progreso.close()
return ret
def get_newest(channel_id, categoria):
logger.info("channel_id=" + channel_id + ", categoria=" + categoria)
global list_newest
# Solicitamos las novedades de la categoria (item.extra) buscada en el canal channel
# Si no existen novedades para esa categoria en el canal devuelve una lista vacia
try:
puede = True
try:
modulo = __import__('channels.%s' % channel_id, fromlist=["channels.%s" % channel_id])
except:
try:
exec "import channels." + channel_id + " as modulo"
except:
puede = False
if not puede:
return
logger.info("running channel " + modulo.__name__ + " " + modulo.__file__)
list_result = modulo.newest(categoria)
logger.info("canal= %s %d resultados" % (channel_id, len(list_result)))
for item in list_result:
# logger.info("item="+item.tostring())
item.channel = channel_id
list_newest.append(item)
except:
logger.error("No se pueden recuperar novedades de: " + channel_id)
import traceback
logger.error(traceback.format_exc())
def get_title(item):
if item.contentSerieName: # Si es una serie
title = item.contentSerieName
if not scrapertools.get_season_and_episode(title) and item.contentEpisodeNumber:
if not item.contentSeason:
item.contentSeason = '1'
title = "%s - %sx%s" % (title, item.contentSeason, str(item.contentEpisodeNumber).zfill(2))
elif item.contentTitle: # Si es una pelicula con el canal adaptado
title = item.contentTitle
elif item.fulltitle: # Si el canal no esta adaptado
title = item.fulltitle
else: # Como ultimo recurso
title = item.title
# Limpiamos el titulo de etiquetas de formato anteriores
title = re.compile("\[/*COLO.*?\]", re.DOTALL).sub("", title)
title = re.compile("\[/*B\]", re.DOTALL).sub("", title)
title = re.compile("\[/*I\]", re.DOTALL).sub("", title)
return title
def no_group(list_result_canal):
itemlist = []
global channels_id_name
for i in list_result_canal:
i.title = get_title(i) + " [" + channels_id_name[i.channel] + "]"
i.text_color = color3
itemlist.append(i.clone())
return sorted(itemlist, key=lambda it: it.title.lower())
def group_by_channel(list_result_canal):
global channels_id_name
dict_canales = {}
itemlist = []
for i in list_result_canal:
if i.channel not in dict_canales:
dict_canales[i.channel] = []
# Formatear titulo
i.title = get_title(i)
# Añadimos el contenido al listado de cada canal
dict_canales[i.channel].append(i)
# Añadimos el contenido encontrado en la lista list_result
for c in sorted(dict_canales):
itemlist.append(Item(channel="news", title=channels_id_name[c] + ':', text_color=color1, text_bold=True))
for i in dict_canales[c]:
if i.contentQuality:
i.title += ' (%s)' % i.contentQuality
if i.language:
i.title += ' [%s]' % i.language
i.title = ' %s' % i.title
i.text_color = color3
itemlist.append(i.clone())
return itemlist
def group_by_content(list_result_canal):
global channels_id_name
dict_contenidos = {}
list_result = []
for i in list_result_canal:
# Formatear titulo
i.title = get_title(i)
# Eliminar tildes y otros caracteres especiales para la key
import unicodedata
try:
new_key = i.title.lower().strip().decode("UTF-8")
new_key = ''.join((c for c in unicodedata.normalize('NFD', new_key) if unicodedata.category(c) != 'Mn'))
except:
new_key = i.title
if new_key in dict_contenidos:
# Si el contenido ya estaba en el diccionario añadirlo a la lista de opciones...
dict_contenidos[new_key].append(i)
else: # ...sino añadirlo al diccionario
dict_contenidos[new_key] = [i]
# Añadimos el contenido encontrado en la lista list_result
for v in dict_contenidos.values():
title = v[0].title
if len(v) > 1:
# Eliminar de la lista de nombres de canales los q esten duplicados
canales_no_duplicados = []
for i in v:
if i.channel not in canales_no_duplicados:
canales_no_duplicados.append(channels_id_name[i.channel])
if len(canales_no_duplicados) > 1:
canales = ', '.join([i for i in canales_no_duplicados[:-1]])
title += " (En %s y %s)" % (canales, canales_no_duplicados[-1])
else:
title += " (En %s)" % (', '.join([i for i in canales_no_duplicados]))
new_item = v[0].clone(channel="news", title=title, action="show_channels",
sub_list=[i.tourl() for i in v], extra=channels_id_name)
else:
new_item = v[0].clone(title=title)
new_item.text_color = color3
list_result.append(new_item)
return sorted(list_result, key=lambda it: it.title.lower())
def show_channels(item):
logger.info()
global channels_id_name
channels_id_name = item.extra
itemlist = []
for i in item.sub_list:
new_item = Item()
new_item = new_item.fromurl(i)
# logger.debug(new_item.tostring())
if new_item.contentQuality:
new_item.title += ' (%s)' % new_item.contentQuality
if new_item.language:
new_item.title += ' [%s]' % new_item.language
new_item.title += ' (%s)' % channels_id_name[new_item.channel]
new_item.text_color = color1
itemlist.append(new_item.clone())
return itemlist
def menu_opciones(item):
itemlist = list()
itemlist.append(Item(channel=item.channel, title="Canales incluidos en:",
thumbnail=config.get_thumb("thumb_setting_0.png"),
folder=False))
itemlist.append(Item(channel=item.channel, action="setting_channel", extra="peliculas", title=" - Películas ",
thumbnail=config.get_thumb("thumb_channels_movie.png"),
folder=False))
itemlist.append(Item(channel=item.channel, action="setting_channel", extra="infantiles", title=" - Para niños",
thumbnail=config.get_thumb("thumb_channels_children.png"),
folder=False))
itemlist.append(Item(channel=item.channel, action="setting_channel", extra="series",
title=" - Episodios de series",
thumbnail=config.get_thumb("thumb_channels_tvshow.png"),
folder=False))
itemlist.append(Item(channel=item.channel, action="setting_channel", extra="anime",
title=" - Episodios de anime",
thumbnail=config.get_thumb("thumb_channels_anime.png"),
folder=False))
itemlist.append(Item(channel=item.channel, action="setting_channel", extra="documentales",
title=" - Documentales",
thumbnail=config.get_thumb("thumb_channels_documentary.png"),
folder=False))
itemlist.append(Item(channel=item.channel, action="settings", title="Otros ajustes",
thumbnail=config.get_thumb("thumb_setting_0.png"),
folder=False))
return itemlist
def settings(item):
return platformtools.show_channel_settings(caption="configuración -- Novedades")
def setting_channel(item):
channels_path = os.path.join(config.get_runtime_path(), "channels", '*.json')
channel_language = config.get_setting("channel_language")
if channel_language == "":
channel_language = "all"
list_controls = []
for infile in sorted(glob.glob(channels_path)):
channel_id = os.path.basename(infile)[:-5]
channel_parameters = channeltools.get_channel_parameters(channel_id)
# No incluir si es un canal inactivo
if not channel_parameters["active"]:
continue
# No incluir si es un canal para adultos, y el modo adulto está desactivado
if channel_parameters["adult"] and config.get_setting("adult_mode") == 0:
continue
# No incluir si el canal es en un idioma filtrado
if channel_language != "all" and channel_parameters["language"] != channel_language:
continue
# No incluir si en su configuracion el canal no existe 'include_in_newest'
include_in_newest = config.get_setting("include_in_newest_" + item.extra, channel_id)
if include_in_newest is None:
continue
control = {'id': channel_id,
'type': "bool",
'label': channel_parameters["title"],
'default': include_in_newest,
'enabled': True,
'visible': True}
list_controls.append(control)
caption = "Canales incluidos en Novedades " + item.title.replace("Canales incluidos en: ", "- ").strip()
return platformtools.show_channel_settings(list_controls=list_controls, callback="save_settings", item=item,
caption=caption, custom_button={"visible": False})
def save_settings(item, dict_values):
for v in dict_values:
config.set_setting("include_in_newest_" + item.extra, dict_values[v], v)