Files
addon/specials/search.py
2019-12-14 13:14:43 +01:00

694 lines
24 KiB
Python
Executable File

# -*- coding: utf-8 -*-
# -*- Channel New Search -*-
# -*- Created for Alfa-addon -*-
# -*- By the Alfa Develop Group -*-
import os
import json
import time
from lib.concurrent import futures
from core.item import Item
from core import tmdb
from core import scrapertools
from core import channeltools
import channelselector
from channelselector import get_thumb
from platformcode import logger
from platformcode import config
from platformcode import platformtools
from platformcode import unify
def mainlist(item):
logger.info()
itemlist = list()
itemlist.append(Item(channel=item.channel, title='Búsqueda General', action='new_search', mode='all',
thumbnail=get_thumb("search_generic.png")))
itemlist.append(Item(channel=item.channel, title='Buscar Película', action='new_search', mode='movie',
thumbnail=get_thumb("search.png")))
itemlist.append(Item(channel=item.channel, title='Buscar Serie', action='new_search', mode='tvshow',
thumbnail=get_thumb("search_tvshow.png")))
itemlist.append(Item(channel=item.channel, title='Buscar Actor/Actriz', action='new_search',
page=1, mode='person', thumbnail=get_thumb("search_star.png")))
itemlist.append(Item(channel=item.channel, title='Más opciones de búsqueda', action='sub_menu',
thumbnail=get_thumb('search_more.png')))
itemlist.append(Item(channel=item.channel, title='Seleccionar canales para la búsqueda', action='opciones',
thumbnail=get_thumb('setting_0.png')))
itemlist = set_context(itemlist)
return itemlist
def sub_menu(item):
logger.info()
itemlist = list()
itemlist.append(Item(channel="tvmoviedb", action="mainlist", title=config.get_localized_string(70274),
thumbnail=get_thumb("search.png")))
itemlist.append(Item(channel=item.channel, action='genres_menu', title=config.get_localized_string(70306),
mode='movie', thumbnail=get_thumb("genres.png")))
itemlist.append(Item(channel=item.channel, action='years_menu', title='Películas por Año',
mode='movie', thumbnail=get_thumb("years.png")))
itemlist.append(Item(channel=item.channel, action='discover_list', title=config.get_localized_string(70307),
search_type='list', list_type='movie/popular', mode='movie',
thumbnail=get_thumb("popular.png")))
itemlist.append(Item(channel=item.channel, action='discover_list', title=config.get_localized_string(70308),
search_type='list', list_type='movie/top_rated', mode='movie',
thumbnail=get_thumb("top_rated.png")))
itemlist.append(Item(channel=item.channel, action='discover_list', title=config.get_localized_string(70309),
search_type='list', list_type='movie/now_playing', mode='movie',
thumbnail=get_thumb("now_playing.png")))
itemlist.append(Item(channel=item.channel, action='genres_menu', title=config.get_localized_string(70310),
mode='tvshow', thumbnail=get_thumb("genres.png")))
itemlist.append(Item(channel=item.channel, action='years_menu', title='Series por Año',
mode='tvshow', thumbnail=get_thumb("years.png")))
itemlist.append(Item(channel=item.channel, action='discover_list', title=config.get_localized_string(70311),
search_type='list', list_type='tv/popular', mode='tvshow',
thumbnail=get_thumb("popular.png")))
itemlist.append(Item(channel=item.channel, action='discover_list', title=config.get_localized_string(70312),
search_type='list', list_type='tv/on_the_air', mode='tvshow',
thumbnail=get_thumb("on_the_air.png")))
itemlist.append(Item(channel=item.channel, action='discover_list', title=config.get_localized_string(70313),
search_type='list', list_type='tv/top_rated', mode='tvshow',
thumbnail=get_thumb("top_rated.png")))
itemlist = set_context(itemlist)
return itemlist
def new_search(item):
logger.info()
itemlist = []
last_search = channeltools.get_channel_setting('Last_searched', 'search', '')
searched_text = platformtools.dialog_input(default=last_search, heading='Alfa (Busqueda)')
if not searched_text:
return
channeltools.set_channel_setting('Last_searched', searched_text, 'search')
searched_text = searched_text.replace("+", " ")
if item.mode == 'person':
item.searched_text = searched_text
return actor_list(item)
if item.mode != 'all':
tmdb_info = tmdb.Tmdb(texto_buscado=searched_text, tipo=item.mode.replace('show', ''))
results = tmdb_info.results
for result in results:
result = tmdb_info.get_infoLabels(result, origen=result)
if item.mode == 'movie':
title = result['title']
else:
title = result['name']
item.mode = 'tvshow'
thumbnail = result.get('thumbnail', '')
fanart = result.get('fanart', '')
new_item = Item(channel=item.channel,
action='channel_search',
title=title,
text=searched_text,
thumbnail=thumbnail,
fanart=fanart,
mode=item.mode,
infoLabels=result)
if item.mode == 'movie':
new_item.contentTitle = result['title']
else:
new_item.contentSerieName = result['name']
itemlist.append(new_item)
if item.mode == 'all' or not itemlist:
itemlist = channel_search(Item(channel=item.channel,
title=searched_text,
text=searched_text,
mode='all',
infoLabels={}))
return itemlist
def channel_search(item):
logger.info()
start = time.time()
searching = list()
results = list()
valid = list()
ch_list = dict()
to_temp = dict()
mode = item.mode
max_results = 10
searched_id = item.infoLabels['tmdb_id']
channel_list = get_channels(item)
searching += channel_list
cnt = 0
progress = platformtools.dialog_progress('Buscando %s ...' % item.title, "Restan %s canales" % len(channel_list),
str(searching))
config.set_setting('tmdb_active', False)
with futures.ThreadPoolExecutor() as executor:
c_results = [executor.submit(get_channel_results, ch, item) for ch in channel_list]
for res in futures.as_completed(c_results):
cnt += 1
finished = res.result()[0]
if res.result()[1]:
ch_list[res.result()[0]] = res.result()[1]
if progress.iscanceled():
break
if finished in searching:
searching.remove(finished)
progress.update((cnt * 100) / len(channel_list), "Restan %s canales" % str(len(channel_list) - cnt),
str(searching))
progress.close()
cnt = 0
progress = platformtools.dialog_progress('Buscando %s ...' % item.title, "Preparando Resultados",
'Por favor espere...')
config.set_setting('tmdb_active', True)
for key, value in ch_list.items():
grouped = list()
cnt += 1
progress.update((cnt * 100) / len(ch_list), "Preparando Resultados", 'Por favor espere...')
if len(value) <= max_results and item.mode != 'all':
if len(value) == 1:
if not value[0].action or 'siguiente' in value[0].title.lower():
continue
tmdb.set_infoLabels_itemlist(value, True, forced=True)
for elem in value:
if not elem.infoLabels.get('year', ""):
elem.infoLabels['year'] = '-'
tmdb.set_infoLabels_item(elem, True)
if elem.infoLabels['tmdb_id'] == searched_id:
elem.from_channel = key
if not config.get_setting('unify'):
elem.title += ' [%s]' % key
valid.append(elem)
for it in value:
if it.channel == item.channel:
it.channel = key
if it in valid:
continue
if mode == 'all' or (it.contentType and mode == it.contentType):
grouped.append(it)
elif (mode == 'movie' and it.contentTitle) or (mode == 'tvshow' and (it.contentSerieName or it.show)):
grouped.append(it)
else:
continue
if not grouped:
continue
to_temp[key] = grouped
if not config.get_setting('unify'):
title = '[COLOR yellow](%s) RESULTADOS EN[/COLOR] [%s]' % (len(grouped), key)
else:
title = '[COLOR yellow](%s) RESULTADOS EN[/COLOR]' % (len(grouped))
ch_thumb = channeltools.get_channel_parameters(key)['thumbnail']
results.append(Item(channel='search', title=title,
action='get_from_temp', thumbnail=ch_thumb, from_channel=key, page=1))
results = sorted(results, key=lambda it: it.from_channel)
send_to_temp(to_temp)
config.set_setting('tmdb_active', True)
logger.debug('Finalizada en %s segs (%s canales)' % (str(time.time() - start), str(len(channel_list))))
return valid + results
def get_channel_results(ch, item):
max_results = 10
results = list()
ch_params = channeltools.get_channel_parameters(ch)
exec "from channels import " + ch_params["channel"] + " as module"
mainlist = module.mainlist(Item(channel=ch_params["channel"]))
search_action = [elem for elem in mainlist if elem.action == "search"]
if search_action:
for search_ in search_action:
try:
results.extend(module.search(search_, item.text))
except:
pass
else:
try:
results.extend(module.search(item, item.text))
except:
pass
if len(results) < 0 and len(results) < max_results and item.mode != 'all':
if len(results) == 1:
if not results[0].action or 'siguiente' in results[0].title.lower():
return [ch, []]
results = get_info(results)
return [ch, results]
def get_info(itemlist):
logger.info()
tmdb.set_infoLabels_itemlist(itemlist, True, forced=True)
return itemlist
def get_channels(item):
logger.info()
channels_list = list()
all_channels = channelselector.filterchannels('all')
for ch in all_channels:
channel = ch.channel
ch_param = channeltools.get_channel_parameters(channel)
if not ch_param.get("active", False):
continue
list_cat = ch_param.get("categories", [])
if not ch_param.get("include_in_global_search", False):
continue
if 'anime' in list_cat:
n = list_cat.index('anime')
list_cat[n] = 'tvshow'
if item.mode == 'all' or (item.mode in list_cat):
if config.get_setting("include_in_global_search", channel):
channels_list.append(channel)
return channels_list
def opciones(item):
return setting_channel_new(item)
def setting_channel_new(item):
import xbmcgui
# Cargar lista de opciones (canales activos del usuario y que permitan búsqueda global)
# ------------------------
lista = []
ids = []
lista_lang = []
lista_ctgs = []
channels_list = channelselector.filterchannels('all')
for channel in channels_list:
if channel.action == '':
continue
channel_parameters = channeltools.get_channel_parameters(channel.channel)
# No incluir si en la configuracion del canal no existe "include_in_global_search"
if not channel_parameters['include_in_global_search']:
continue
lbl = '%s' % channel_parameters['language']
lbl += ' %s' % ', '.join(config.get_localized_category(categ) for categ in channel_parameters['categories'])
it = xbmcgui.ListItem(channel.title, lbl)
it.setArt({'thumb': channel.thumbnail, 'fanart': channel.fanart})
lista.append(it)
ids.append(channel.channel)
lista_lang.append(channel_parameters['language'])
lista_ctgs.append(channel_parameters['categories'])
# Diálogo para pre-seleccionar
# ----------------------------
preselecciones = [
'Buscar con la selección actual',
'Modificar selección actual',
'Modificar partiendo de Recomendados',
'Modificar partiendo de Frecuentes',
'Modificar partiendo de Todos',
'Modificar partiendo de Ninguno',
'Modificar partiendo de Castellano',
'Modificar partiendo de Latino'
]
presel_values = ['skip', 'actual', 'recom', 'freq', 'all', 'none', 'cast', 'lat']
categs = ['movie', 'tvshow', 'documentary', 'anime', 'vos', 'direct', 'torrent']
if config.get_setting('adult_mode') > 0:
categs.append('adult')
for c in categs:
preselecciones.append('Modificar partiendo de %s' % config.get_localized_category(c))
presel_values.append(c)
if item.action == 'setting_channel': # Configuración de los canales incluídos en la búsqueda
del preselecciones[0]
del presel_values[0]
# else: # Llamada desde "buscar en otros canales" (se puede saltar la selección e ir directo a la búsqueda)
ret = platformtools.dialog_select(config.get_localized_string(59994), preselecciones)
if ret == -1:
return False # pedido cancel
if presel_values[ret] == 'skip':
return True # continuar sin modificar
elif presel_values[ret] == 'none':
preselect = []
elif presel_values[ret] == 'all':
preselect = range(len(ids))
elif presel_values[ret] in ['cast', 'lat']:
preselect = []
for i, lg in enumerate(lista_lang):
if presel_values[ret] in lg or '*' in lg:
preselect.append(i)
elif presel_values[ret] == 'actual':
preselect = []
for i, canal in enumerate(ids):
channel_status = config.get_setting('include_in_global_search', canal)
if channel_status:
preselect.append(i)
elif presel_values[ret] == 'recom':
preselect = []
for i, canal in enumerate(ids):
_not, set_canal_list = channeltools.get_channel_controls_settings(canal)
if set_canal_list.get('include_in_global_search', False):
preselect.append(i)
elif presel_values[ret] == 'freq':
preselect = []
for i, canal in enumerate(ids):
frequency = channeltools.get_channel_setting('frequency', canal, 0)
if frequency > 0:
preselect.append(i)
else:
preselect = []
for i, ctgs in enumerate(lista_ctgs):
if presel_values[ret] in ctgs:
preselect.append(i)
# Diálogo para seleccionar
# ------------------------
ret = xbmcgui.Dialog().multiselect(config.get_localized_string(59994), lista, preselect=preselect, useDetails=True)
if not ret:
return False # pedido cancel
seleccionados = [ids[i] for i in ret]
# Guardar cambios en canales para la búsqueda
# -------------------------------------------
for canal in ids:
channel_status = config.get_setting('include_in_global_search', canal)
# if not channel_status:
# channel_status = True
if channel_status and canal not in seleccionados:
config.set_setting('include_in_global_search', False, canal)
elif not channel_status and canal in seleccionados:
config.set_setting('include_in_global_search', True, canal)
return True
def genres_menu(item):
itemlist = []
mode = item.mode.replace('show', '')
genres = tmdb.get_genres(mode)
for key, value in genres[mode].items():
discovery = {'url': 'discover/%s' % mode, 'with_genres': key,
'language': 'es', 'page': '1'}
itemlist.append(Item(channel=item.channel, title=value, page=1,
action='discover_list', discovery=discovery,
mode=item.mode))
return sorted(itemlist, key=lambda it: it.title)
def years_menu(item):
import datetime
itemlist = []
mode = item.mode.replace('show', '')
par_year = 'primary_release_year'
if mode != 'movie':
par_year = 'first_air_date_year'
c_year = datetime.datetime.now().year + 1
l_year = c_year - 31
for year in range(l_year, c_year):
discovery = {'url': 'discover/%s' % mode, 'page': '1',
'%s' % par_year: '%s' % year,
'sort_by': 'popularity.desc', 'language': 'es'}
itemlist.append(Item(channel=item.channel, title=str(year), action='discover_list',
discovery=discovery, mode=item.mode, year_=str(year)))
itemlist.reverse()
itemlist.append(Item(channel=item.channel, title='Introduzca otro año...', url='',
action="year_cus", mode=item.mode, par_year=par_year))
return itemlist
def year_cus(item):
mode = item.mode.replace('show', '')
heading = 'Introduzca Año (4 digitos)'
year = platformtools.dialog_numeric(0, heading, default="")
item.discovery = {'url': 'discover/%s' % mode, 'page': '1',
'%s' % item.par_year: '%s' % year,
'sort_by': 'popularity.desc', 'language': 'es'}
item.action = "discover_list"
if year and len(year) == 4:
return discover_list(item)
def actor_list(item):
itemlist = []
dict_ = {'url': 'search/person', 'language': 'es', 'query': item.searched_text, 'page': item.page}
prof = {'Acting': 'Actor', 'Directing': 'Director', 'Production': 'Productor'}
plot = ''
item.search_type = 'person'
tmdb_inf = tmdb.discovery(item, dict_=dict_)
results = tmdb_inf.results
if not results:
return results
for elem in results:
name = elem.get('name', '')
if not name:
continue
rol = elem.get('known_for_department', '')
rol = prof.get(rol, rol)
genero = elem.get('gender', 0)
if genero == 1 and rol in prof:
rol += 'a'
rol = rol.replace('Actora', 'Actriz')
know_for = elem.get('known_for', '')
cast_id = elem.get('id', '')
if know_for:
t_k = know_for[0].get('title', '')
if t_k:
plot = '%s en [COLOR limegreen]%s[/COLOR] y otras' % (rol, t_k)
thumbnail = 'http://image.tmdb.org/t/p/original%s' % elem.get('profile_path', '')
title = '%s [COLOR grey](%s)[/COLOR]' % (name, rol)
discovery = {'url': 'person/%s/combined_credits' % cast_id, 'page': '1',
'sort_by': 'primary_release_date.desc', 'language': 'es'}
itemlist.append(Item(channel=item.channel, title=title, action='discover_list', cast_='cast',
discovery=discovery, thumbnail=thumbnail, plot=plot, page=1))
if len(results) > 19:
next_ = item.page + 1
itemlist.append(Item(channel=item.channel, title="Pagina Siguiente >>", action='actor_list',
page=next_, thumbnail=thumbnail, text_color='gold',
searched_text=item.searched_text))
return itemlist
def discover_list(item):
import datetime
itemlist = []
year = 0
tmdb_inf = tmdb.discovery(item, dict_=item.discovery, cast=item.cast_)
result = tmdb_inf.results
tvshow = False
for elem in result:
elem = tmdb_inf.get_infoLabels(elem, origen=elem)
if 'title' in elem:
title = unify.normalize(elem['title']).capitalize()
else:
title = unify.normalize(elem['name']).capitalize()
tvshow = True
elem['tmdb_id'] = elem['id']
mode = item.mode or elem['media_type']
thumbnail = elem.get('thumbnail', '')
fanart = elem.get('fanart', '')
if item.cast_:
release = elem.get('release_date', '0000') or elem.get('first_air_date', '0000')
year = scrapertools.find_single_match(release, r'(\d{4})')
if not item.cast_ or (item.cast_ and (int(year) <= int(datetime.datetime.today().year))):
new_item = Item(channel='search', title=title, infoLabels=elem,
action='channel_search', text=title,
thumbnail=thumbnail, fanart=fanart,
context='', mode=mode,
release_date=year)
if tvshow:
new_item.contentSerieName = title
else:
new_item.contentTitle = title
itemlist.append(new_item)
itemlist = set_context(itemlist)
if item.cast_:
itemlist.sort(key=lambda it: int(it.release_date), reverse=True)
return itemlist
elif len(result) > 19 and item.discovery:
item.discovery['page'] = str(int(item.discovery['page']) + 1)
itemlist.append(Item(channel=item.channel, action='discover_list', title=config.get_localized_string(70065),
list_type=item.list_type, discovery=item.discovery, text_color='gold'))
elif len(result) > 19:
next_page = str(int(item.page) + 1)
itemlist.append(Item(channel=item.channel, action='discover_list', title=config.get_localized_string(70065),
list_type=item.list_type, search_type=item.search_type, mode=item.mode, page=next_page,
text_color='gold'))
return itemlist
def from_context(item):
logger.info()
select = setting_channel_new(item)
if not select:
return
if 'infoLabels' in item and 'mediatype' in item.infoLabels:
item.mode = item.infoLabels['mediatype']
else:
return
if 'list_type' not in item:
if 'wanted' in item:
item.title = item.wanted
return channel_search(item)
return discover_list(item)
def set_context(itemlist):
logger.info()
for elem in itemlist:
elem.context = [{"title": "Elegir canales",
"action": "setting_channel_new",
"channel": "search"}]
return itemlist
def send_to_temp(to_temp):
logger.info()
temp_path = os.path.join(config.get_data_path(), 'temp_search.json')
temp = dict()
for key, value in to_temp.items():
new_list = list()
for elem in value:
new_list.append(elem.tourl())
temp[key] = new_list
with open(temp_path, "w") as temp_file:
json.dump(temp, temp_file)
def get_from_temp(item):
logger.info()
n = 30
nextp = n * item.page
prevp = n * (item.page - 1)
temp_path = os.path.join(config.get_data_path(), 'temp_search.json')
results = list()
with open(temp_path, "r") as temp_list:
from_temp = json.load(temp_list)
for elem in from_temp[item.from_channel]:
results.append(Item().fromurl(elem))
old_results = results
results = results[prevp:nextp]
if len(results) == n and len(old_results * item.page) != n:
results.append(Item(channel='search', title='[COLOR yellow]Pagina Siguiente >>[/COLOR]',
action='get_from_temp', from_channel=item.from_channel, page=item.page + 1))
tmdb.set_infoLabels_itemlist(results, True)
for elem in results:
if not elem.infoLabels.get('year', ""):
elem.infoLabels['year'] = '-'
tmdb.set_infoLabels_item(elem, True)
return results