KoD 1.6.1

-Migliorata l'efficacia del riconoscimento dei contenuti in ricerca film/serie
- corretti alcuni bug e fatti alcuni fix per i soliti cambi di struttura
This commit is contained in:
mac12m99
2021-03-09 22:08:09 +01:00
parent f1da5c7a0b
commit fa0fe6e534
29 changed files with 377 additions and 330 deletions
+8 -8
View File
@@ -477,15 +477,15 @@ def get_server_position(server):
def get_match_list(data, match_list, order_list=None, only_ascii=False, ignorecase=False):
"""
Search for matches in a text string, with a dictionary of "ID" / "List of search strings":
    {"ID1": ["String 1", "String 2", "String 3"],
      "ID2": ["String 4", "String 5", "String 6"]
    }
{"ID1": ["String 1", "String 2", "String 3"],
"ID2": ["String 4", "String 5", "String 6"]
}
    The dictionary could not contain the same search string in several IDs.
    The search is performed in order of search string size (from longest to shortest) if a string matches,
    it is removed from the search string for the following, so that two categories are not detected if one string is part of another:
    for example: "Spanish Language" and "Spanish" if the first appears in the string "Pablo knows how to speak the Spanish Language"
    It will match "Spanish Language" but not "Spanish" since the longest match has priority.
The dictionary could not contain the same search string in several IDs.
The search is performed in order of search string size (from longest to shortest) if a string matches,
it is removed from the search string for the following, so that two categories are not detected if one string is part of another:
for example: "Spanish Language" and "Spanish" if the first appears in the string "Pablo knows how to speak the Spanish Language"
It will match "Spanish Language" but not "Spanish" since the longest match has priority.
"""
match_dict = dict()
+6 -4
View File
@@ -235,23 +235,25 @@ def new_search(item):
def live(item):
import sys
import channelselector
if sys.version_info[0] >= 3:
from concurrent import futures
else:
from concurrent_py2 import futures
itemlist = []
channels_dict = {}
channels = ['raiplay', 'mediasetplay', 'la7', 'paramount']
channels = channelselector.filterchannels('live')
with futures.ThreadPoolExecutor() as executor:
itlist = [executor.submit(load_live, channel) for channel in channels]
itlist = [executor.submit(load_live, ch.channel) for ch in channels]
for res in futures.as_completed(itlist):
if res.result():
channel_name, itlist = res.result()
channels_dict[channel_name] = itlist
for channel in channels:
itemlist += channels_dict[channel]
for ch in channels:
itemlist += channels_dict[ch.channel]
return itemlist
+75 -36
View File
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
import xbmc, xbmcgui, sys, channelselector, time, os
from core import support
from core.support import dbg, tmdb
from core.item import Item
from core import channeltools, servertools, scrapertools
@@ -8,8 +9,12 @@ from platformcode import platformtools, config, logger
from platformcode.launcher import run
from threading import Thread
if sys.version_info[0] >= 3: from concurrent import futures
else: from concurrent_py2 import futures
if sys.version_info[0] >= 3:
PY3 = True
from concurrent import futures
else:
PY3 = False
from concurrent_py2 import futures
info_language = ["de", "en", "es", "fr", "it", "pt"] # from videolibrary.json
def_lang = info_language[config.get_setting("info_language", "videolibrary")]
@@ -75,17 +80,14 @@ class SearchWindow(xbmcgui.WindowXML):
self.channels = []
self.persons = []
self.episodes = []
self.servers = []
self.results = {}
self.focus = SEARCH
self.process = True
self.page = 1
self.moduleDict = moduleDict
self.searchActions = searchActions
self.thread = None
self.selected = False
self.pos = 0
selfeppos = 0
self.items = []
if not searchActions:
@@ -116,6 +118,7 @@ class SearchWindow(xbmcgui.WindowXML):
from specials.search import save_search
save_search(self.item.text)
def getActions(self):
logger.debug()
count = 0
@@ -144,9 +147,12 @@ class SearchWindow(xbmcgui.WindowXML):
if self.item.mode == 'movie':
title = result['title']
result['mode'] = 'movie'
else:
elif self.item.mode == 'tvshow':
title = result['name']
result['mode'] = 'tvshow'
else:
title = result.get('title', '')
result['mode'] = result['media_type'].replace('tv', 'tvshow')
thumbnail = result.get('thumbnail', '')
noThumb = 'Infoplus/' + result['mode'].replace('show','') + '.png'
@@ -304,16 +310,12 @@ class SearchWindow(xbmcgui.WindowXML):
logger.debug('end search for:', searchAction.channel)
def get_channel_results(self, searchAction):
logger.debug()
channel = searchAction.channel
results = []
valid = []
other = []
try:
results = self.moduleDict[channel].search(searchAction, self.item.text)
def search(text):
valid = []
other = []
results = self.moduleDict[channel].search(searchAction, text)
if len(results) == 1:
if not results[0].action or config.get_localized_string(70006).lower() in results[0].title.lower():
if not results[0].action or results[0].nextPage:
results = []
if self.item.mode != 'all':
@@ -324,6 +326,23 @@ class SearchWindow(xbmcgui.WindowXML):
valid.append(elem)
else:
other.append(elem)
return results, valid, other
logger.debug()
channel = searchAction.channel
results = []
valid = []
other = []
try:
results, valid, other = search(self.item.text)
# if we are on movie search but no valid results is found, and there's a lot of results (more pages), try
# to add year to search text for better filtering
if self.item.contentType == 'movie' and not valid and other and other[-1].nextPage \
and self.item.infoLabels['year']:
logger.debug('retring adding year on channel ' + channel)
dummy, valid, dummy = search(self.item.text + " " + str(self.item.infoLabels['year']))
except:
pass
@@ -424,9 +443,15 @@ class SearchWindow(xbmcgui.WindowXML):
self.channels = []
self.moduleDict = {}
self.searchActions = []
if percent == 100 and not self.results:
self.PROGRESS.setVisible(False)
self.NORESULTS.setVisible(True)
# if no results
total = 0
for num in self.results.values():
total += num
if not total:
self.PROGRESS.setVisible(False)
self.NORESULTS.setVisible(True)
self.setFocusId(CLOSE)
def onInit(self):
self.time = time.time()
@@ -453,7 +478,9 @@ class SearchWindow(xbmcgui.WindowXML):
if self.type:
self.type = None
if self.item.mode in ['all', 'search']:
if self.item.type: self.item.mode = self.item.type
if self.item.type:
self.item.mode = self.item.type
self.item.text = title_unify(self.item.text)
self.thread = Thread(target=self.search)
self.thread.start()
elif self.item.mode in ['movie', 'tvshow', 'person_']:
@@ -507,9 +534,12 @@ class SearchWindow(xbmcgui.WindowXML):
elif self.EPISODES.isVisible(): self.setFocusId(EPISODESLIST)
elif self.RESULTS.isVisible(): self.setFocusId(RESULTS)
elif focus in [RESULTS] and self.item.mode == 'all':
elif focus in [RESULTS]:
pos = self.RESULTS.getSelectedPosition()
self.CHANNELS.getSelectedItem().setProperty('position', str(pos))
try:
self.CHANNELS.getSelectedItem().setProperty('position', str(pos))
except:
pass
elif action == ENTER and focus in [CHANNELS]:
self.setFocusId(RESULTS)
@@ -559,25 +589,14 @@ class SearchWindow(xbmcgui.WindowXML):
self.actors()
elif search == 'persons':
item = self.item.clone(mode='person_', discovery=self.persons[pos])
# self.close()
Search(item, self.moduleDict, self.searchActions)
if close_action:
self.close
self.close()
else:
item = Item().fromurl(self.RESULTS.getSelectedItem().getProperty('item'))
if self.item.mode == 'movie': item.contentTitle = self.RESULTS.getSelectedItem().getLabel()
else: item.contentSerieName = self.RESULTS.getSelectedItem().getLabel()
self.RESULTS.reset()
self.RESULTS.setVisible(False)
self.PROGRESS.setVisible(True)
self.selected = True
self.thActions.join()
self.RESULTS.addItems(self.items)
self.RESULTS.setVisible(True)
self.PROGRESS.setVisible(False)
# self.close()
Search(item, self.moduleDict, self.searchActions)
if close_action:
self.close()
@@ -589,7 +608,6 @@ class SearchWindow(xbmcgui.WindowXML):
self.pos = self.RESULTS.getSelectedPosition()
item = Item().fromurl(self.RESULTS.getSelectedItem().getProperty('item'))
else:
self.eppos = self.EPISODESLIST.getSelectedPosition()
item_url = self.EPISODESLIST.getSelectedItem().getProperty('item')
if item_url:
item = Item().fromurl(item_url)
@@ -706,8 +724,6 @@ class SearchWindow(xbmcgui.WindowXML):
self.Focus(SEARCH)
self.setFocusId(RESULTS)
self.RESULTS.selectItem(self.pos)
elif self.item.mode in ['person']:
self.actors()
else:
self.Close()
@@ -746,3 +762,26 @@ class SearchWindow(xbmcgui.WindowXML):
server.globalsearch = True
return run(server)
def title_unify(title):
import unicodedata
u_title = ''
if type(title) == str: title = u'' + title
for c in unicodedata.normalize('NFD', title):
cat = unicodedata.category(c)
if cat != 'Mn':
if cat == 'Pd':
c_new = '-'
elif cat in ['Ll', 'Lu'] or c == ':':
c_new = c
else:
c_new = ' '
u_title += c_new
if (u_title.count(':') + u_title.count('-')) == 1:
# subtitle, split but only if there's one, it might be part of title
spl = u_title.replace(':', '-').split('-')
u_title = spl[0] if len(spl[0]) > 5 else spl[1]
return u_title.strip()
+119 -113
View File
@@ -13,7 +13,6 @@ from core import filetools, scrapertools, videolibrarytools
from core.support import typo, thumb
from core.item import Item
from platformcode import config, logger, platformtools
from distutils import dir_util
if PY3:
from concurrent import futures
else:
@@ -202,14 +201,14 @@ def configure_update_videolibrary(item):
# Select Dialog
ret = platformtools.dialog_multiselect(config.get_localized_string(60601), lista, preselect=preselect, useDetails=True)
if ret < 0:
if ret is None:
return False # order cancel
seleccionados = [ids[i] for i in ret]
selection = [ids[i] for i in ret]
for tvshow in ids:
if tvshow not in seleccionados:
if tvshow not in selection:
tvshow.active = 0
elif tvshow in seleccionados:
elif tvshow in selection:
tvshow.active = 1
mark_tvshow_as_updatable(tvshow, silent=True)
@@ -416,124 +415,129 @@ def findvideos(item):
itemlist = []
all_videolibrary = []
for nom_canal, json_path in list(list_canales.items()):
if filtro_canal and filtro_canal != nom_canal.capitalize():
continue
item_canal = Item()
# We import the channel of the selected part
try:
if nom_canal == 'community':
channel = __import__('specials.%s' % nom_canal, fromlist=["channels.%s" % nom_canal])
else:
channel = __import__('channels.%s' % nom_canal, fromlist=["channels.%s" % nom_canal])
except ImportError:
exec("import channels." + nom_canal + " as channel")
except:
dead_list = []
zombie_list = []
if nom_canal not in dead_list and nom_canal not in zombie_list: confirm = platformtools.dialog_yesno(config.get_localized_string(30131), config.get_localized_string(30132) % nom_canal.upper() + '\n' + config.get_localized_string(30133))
elif nom_canal in zombie_list: confirm = False
else: confirm = True
if confirm:
# delete the channel from all movie and tvshow
from past.utils import old_div
num_enlaces = 0
dialog = platformtools.dialog_progress(config.get_localized_string(30131), config.get_localized_string(60005) % nom_canal)
if not all_videolibrary:
all_videolibrary = list_movies(Item()) + list_tvshows(Item())
for n, it in enumerate(all_videolibrary):
if nom_canal in it.library_urls:
dead_item = Item(multichannel=len(it.library_urls) > 1,
contentType=it.contentType,
dead=nom_canal,
path=filetools.split(it.nfo)[0],
nfo=it.nfo,
library_urls=it.library_urls,
infoLabels={'title': it.contentTitle})
num_enlaces += delete(dead_item)
dialog.update(old_div(100*n, len(all_videolibrary)))
dialog.close()
msg_txt = config.get_localized_string(70087) % (num_enlaces, nom_canal)
logger.info(msg_txt)
platformtools.dialog_notification(config.get_localized_string(30131), msg_txt)
platformtools.itemlist_refresh()
if nom_canal not in dead_list:
dead_list.append(nom_canal)
ch_results = []
with futures.ThreadPoolExecutor() as executor:
for nom_canal, json_path in list(list_canales.items()):
if filtro_canal and filtro_canal != nom_canal.capitalize():
continue
else:
if nom_canal not in zombie_list:
zombie_list.append(nom_canal)
if len(dead_list) > 0:
for nom_canal in dead_list:
if nom_canal in item.library_urls:
del item.library_urls[nom_canal]
# We import the channel of the selected part
try:
if nom_canal == 'community':
channel = __import__('specials.%s' % nom_canal, fromlist=["channels.%s" % nom_canal])
else:
channel = __import__('channels.%s' % nom_canal, fromlist=["channels.%s" % nom_canal])
except ImportError:
exec("import channels." + nom_canal + " as channel")
except:
dead_list = []
zombie_list = []
item_json = Item().fromjson(filetools.read(json_path))
list_servers = []
if nom_canal not in dead_list and nom_canal not in zombie_list: confirm = platformtools.dialog_yesno(config.get_localized_string(30131), config.get_localized_string(30132) % nom_canal.upper() + '\n' + config.get_localized_string(30133))
elif nom_canal in zombie_list: confirm = False
else: confirm = True
try:
# FILTERTOOLS
# if the channel has a filter, the name it has saved is passed to it so that it filters correctly.
if "list_language" in item_json:
# if it comes from the addon video library
if "library_filter_show" in item:
item_json.show = item.library_filter_show.get(nom_canal, "")
if confirm:
# delete the channel from all movie and tvshow
from past.utils import old_div
num_enlaces = 0
dialog = platformtools.dialog_progress(config.get_localized_string(30131), config.get_localized_string(60005) % nom_canal)
if not all_videolibrary:
all_videolibrary = list_movies(Item()) + list_tvshows(Item())
for n, it in enumerate(all_videolibrary):
if nom_canal in it.library_urls:
dead_item = Item(multichannel=len(it.library_urls) > 1,
contentType=it.contentType,
dead=nom_canal,
path=filetools.split(it.nfo)[0],
nfo=it.nfo,
library_urls=it.library_urls,
infoLabels={'title': it.contentTitle})
num_enlaces += delete(dead_item)
dialog.update(old_div(100*n, len(all_videolibrary)))
# We run find_videos, from the channel or common
item_json.contentChannel = 'videolibrary'
item_json.play_from = item.play_from
item_json.nfo = item.nfo
item_json.strm_path = item.strm_path
if hasattr(channel, 'findvideos'):
from core import servertools
if item_json.videolibray_emergency_urls:
del item_json.videolibray_emergency_urls
list_servers = getattr(channel, 'findvideos')(item_json)
elif item_json.action == 'play':
from platformcode import platformtools
# autoplay.set_status(True)
item_json.contentChannel = item_json.channel
item_json.channel = "videolibrary"
platformtools.play_video(item_json)
return ''
else:
from core import servertools
list_servers = servertools.find_video_items(item_json)
except Exception as ex:
logger.error("The findvideos function for the channel %s failed" % nom_canal)
template = "An exception of type %s occured. Arguments:\n%r"
message = template % (type(ex).__name__, ex.args)
logger.error(message)
logger.error(traceback.format_exc())
dialog.close()
msg_txt = config.get_localized_string(70087) % (num_enlaces, nom_canal)
logger.info(msg_txt)
platformtools.dialog_notification(config.get_localized_string(30131), msg_txt)
platformtools.itemlist_refresh()
# Change the title to the servers adding the name of the channel in front and the infoLabels and the images of the item if the server does not have
for server in list_servers:
server.contentChannel = server.channel
server.channel = "videolibrary"
server.nfo = item.nfo
server.strm_path = item.strm_path
server.play_from = item.play_from
if nom_canal not in dead_list:
dead_list.append(nom_canal)
continue
else:
if nom_canal not in zombie_list:
zombie_list.append(nom_canal)
# Kodi 18 Compatibility - Prevents wheel from spinning around in Direct Links
if server.action == 'play':
server.folder = False
if len(dead_list) > 0:
for nom_canal in dead_list:
if nom_canal in item.library_urls:
del item.library_urls[nom_canal]
# Channel name is added if desired
if config.get_setting("quit_channel_name", "videolibrary") == 0:
server.title = "%s: %s" % (nom_canal.capitalize(), server.title)
item_json = Item().fromjson(filetools.read(json_path))
list_servers = []
if not server.thumbnail:
server.thumbnail = item.thumbnail
try:
# FILTERTOOLS
# if the channel has a filter, the name it has saved is passed to it so that it filters correctly.
if "list_language" in item_json:
# if it comes from the addon video library
if "library_filter_show" in item:
item_json.show = item.library_filter_show.get(nom_canal, "")
# logger.debug("server:\n%s" % server.tostring('\n'))
itemlist.append(server)
# We run find_videos, from the channel or common
item_json.contentChannel = 'videolibrary'
item_json.play_from = item.play_from
item_json.nfo = item.nfo
item_json.strm_path = item.strm_path
if hasattr(channel, 'findvideos'):
from core import servertools
if item_json.videolibray_emergency_urls:
del item_json.videolibray_emergency_urls
ch_results.append(executor.submit(getattr(channel, 'findvideos'), item_json))
elif item_json.action == 'play':
from platformcode import platformtools
# autoplay.set_status(True)
item_json.contentChannel = item_json.channel
item_json.channel = "videolibrary"
platformtools.play_video(item_json)
return ''
else:
from core import servertools
ch_results.append(executor.submit(servertools.find_video_items, item_json))
except Exception as ex:
logger.error("The findvideos function for the channel %s failed" % nom_canal)
template = "An exception of type %s occured. Arguments:\n%r"
message = template % (type(ex).__name__, ex.args)
logger.error(message)
logger.error(traceback.format_exc())
for ris in futures.as_completed(ch_results):
list_servers.extend(ris.result())
# Change the title to the servers adding the name of the channel in front and the infoLabels and the images of the item if the server does not have
for server in list_servers:
server.contentChannel = server.channel
server.channel = "videolibrary"
server.nfo = item.nfo
server.strm_path = item.strm_path
server.play_from = item.play_from
# Kodi 18 Compatibility - Prevents wheel from spinning around in Direct Links
if server.action == 'play':
server.folder = False
# Channel name is added if desired
if config.get_setting("quit_channel_name", "videolibrary") == 0:
server.title = "%s: %s" % (server.contentChannel.capitalize(), server.title)
if not server.thumbnail:
server.thumbnail = item.thumbnail
# logger.debug("server:\n%s" % server.tostring('\n'))
itemlist.append(server)
if autoplay.play_multi_channel(item, itemlist): # hideserver
return []
@@ -605,6 +609,8 @@ def update_videolibrary(item=''):
def move_videolibrary(current_path, new_path, current_movies_folder, new_movies_folder, current_tvshows_folder, new_tvshows_folder):
from distutils import dir_util
logger.debug()
backup_current_path = current_path