- completato il supporto al futuro Kodi 19\n- ridisegnato infoplus\n- fix vari ed eventuali\n
This commit is contained in:
marco
2020-09-29 21:08:25 +02:00
parent d153ac5918
commit 8a8d1e4f5e
195 changed files with 20697 additions and 23038 deletions
+285
View File
@@ -0,0 +1,285 @@
# -*- coding: utf-8 -*-
from core import filetools, jsontools
from core.item import Item
from platformcode import config, logger, platformtools
from time import sleep
__channel__ = "autoplay"
PLAYED = False
quality_list = ['4k', '2160p', '2160', '4k2160p', '4k2160', '4k 2160p', '4k 2160', '2k',
'fullhd', 'fullhd 1080', 'fullhd 1080p', 'full hd', 'full hd 1080', 'full hd 1080p', 'hd1080', 'hd1080p', 'hd 1080', 'hd 1080p', '1080', '1080p',
'hd', 'hd720', 'hd720p', 'hd 720', 'hd 720p', '720', '720p', 'hdtv',
'sd', '480p', '480', '360p', '360', '240p', '240',
'default']
def start(itemlist, item):
'''
Main method from which the links are automatically reproduced
- In case the option to activate it will use the options defined by the user.
- Otherwise it will try to reproduce any link that has the preferred language.
:param itemlist: list (list of items ready to play, ie with action = 'play')
:param item: item (the main item of the channel)
:return: try to auto-reproduce, in case of failure it returns the itemlist that it received in the beginning
'''
if item.global_search:
return itemlist
logger.info()
global PLAYED
PLAYED = False
base_item = item
if not config.is_xbmc():
return itemlist
if config.get_setting('autoplay'):
url_list_valid = []
autoplay_list = []
autoplay_b = []
favorite_quality = []
favorite_servers = []
blacklisted_servers = config.get_setting("black_list", server='servers')
if not blacklisted_servers: blacklisted_servers = []
from core import servertools
servers_list = list(servertools.get_servers_list().items())
for server, server_parameters in servers_list:
if config.get_setting('favorites_servers_list', server=server):
favorite_servers.append(server.lower())
if not favorite_servers:
config.set_setting('favorites_servers_list', [], server='servers')
favorite_servers = []
else:
favorite_servers = list(set(favorite_servers) - set(blacklisted_servers))
# Save the current value of "Action and Player Mode" in preferences
user_config_setting_action = config.get_setting("default_action")
user_config_setting_player = config.get_setting("player_mode")
# Enable the "View in high quality" action (if the server returns more than one quality, eg gdrive)
if not user_config_setting_action: config.set_setting("default_action", 2)
if user_config_setting_player != 0: config.set_setting("player_mode", 0)
# Priorities when ordering itemlist:
# 0: Servers and qualities
# 1: Qualities and servers
# 2: Servers only
# 3: Only qualities
# 4: Do not order
if config.get_setting('favorites_servers') and favorite_servers and config.get_setting('default_action'):
priority = 0 # 0: Servers and qualities or 1: Qualities and servers
elif config.get_setting('favorites_servers') and favorite_servers:
priority = 2 # Servers only
elif config.get_setting('default_action'):
priority = 3 # Only qualities
else:
priority = 4 # Do not order
if config.get_setting('default_action') == 1:
quality_list.reverse()
favorite_quality = quality_list
for item in itemlist:
autoplay_elem = dict()
b_dict = dict()
# We check that it is a video item
if 'server' not in item:
continue
if item.server.lower() in blacklisted_servers:
continue
# If it does not have a defined quality, it assigns a 'default' quality.
if item.quality.lower() not in quality_list:
item.quality = 'default'
# The list for custom settings is created
if priority < 2: # 0: Servers and qualities or 1: Qualities and servers
# if the server and the quality are not in the favorites lists or the url is repeated, we discard the item
if item.server.lower() not in favorite_servers or item.quality.lower() not in favorite_quality or item.url in url_list_valid:
item.type_b = True
item.play_from = base_item.play_from
b_dict['videoitem']= item
autoplay_b.append(b_dict)
continue
autoplay_elem["indice_server"] = favorite_servers.index(item.server.lower())
autoplay_elem["indice_quality"] = favorite_quality.index(item.quality.lower())
elif priority == 2: # Servers only
# if the server is not in the favorites list or the url is repeated, we discard the item
if item.server.lower() not in favorite_servers or item.url in url_list_valid:
item.type_b = True
item.play_from = base_item.play_from
b_dict['videoitem'] = item
autoplay_b.append(b_dict)
continue
autoplay_elem["indice_server"] = favorite_servers.index(item.server.lower())
elif priority == 3: # Only qualities
# if the quality is not in the favorites list or the url is repeated, we discard the item
if item.quality.lower() not in favorite_quality or item.url in url_list_valid:
item.type_b = True
item.play_from = base_item.play_from
b_dict['videoitem'] = item
autoplay_b.append(b_dict)
continue
autoplay_elem["indice_quality"] = favorite_quality.index(item.quality.lower())
else: # Do not order
# if the url is repeated, we discard the item
item.play_from = base_item.play_from
if item.url in url_list_valid:
continue
# If the item reaches here we add it to the list of valid urls and to autoplay_list
url_list_valid.append(item.url)
item.plan_b=True
item.play_from = base_item.play_from
autoplay_elem['videoitem'] = item
autoplay_list.append(autoplay_elem)
# We order according to priority
if priority == 0: autoplay_list.sort(key=lambda orden: (orden['indice_quality'], orden['indice_server'])) # Servers and qualities
elif priority == 1: autoplay_list.sort(key=lambda orden: (orden['indice_quality'], orden['indice_server'])) # Qualities and servers
elif priority == 2: autoplay_list.sort(key=lambda orden: (orden['indice_server'])) # Servers only
elif priority == 3: autoplay_list.sort(key=lambda orden: (orden['indice_quality'])) # Only qualities
# if quality priority is active
if priority == 0 and config.get_setting('quality_priority'):
max_quality = autoplay_list[0]["indice_quality"] if autoplay_list and "indice_quality" in autoplay_list[0] else 0
for n, item in enumerate(itemlist):
if 'server' not in item:
continue
if item.server.lower() in blacklisted_servers:
continue
# If it does not have a defined quality, it assigns a 'default' quality.
if item.quality == '':
item.quality = 'default'
if favorite_quality.index(item.quality.lower()) < max_quality:
item.type_b = False
autoplay_elem["indice_server"] = n
autoplay_elem["indice_quality"] = favorite_quality.index(item.quality.lower())
autoplay_elem['videoitem'] = item
autoplay_list.append(autoplay_elem)
autoplay_list.sort(key=lambda orden: (orden['indice_quality'], orden['indice_server']))
# Plan b is prepared, in case it is active the non-favorite elements are added at the end
# try: plan_b = settings_node['plan_b']
# except:
plan_b = True
text_b = ''
if plan_b: autoplay_list.extend(autoplay_b)
# If there are elements in the autoplay list, an attempt is made to reproduce each element, until one is found or all fail.
if autoplay_list or (plan_b and autoplay_b):
max_intentos = 5
max_intentos_servers = {}
# If something is playing it stops playing
if platformtools.is_playing():
platformtools.stop_video()
for autoplay_elem in autoplay_list:
play_item = Item
channel_id = autoplay_elem['videoitem'].channel
if autoplay_elem['videoitem'].channel == 'videolibrary':
channel_id = autoplay_elem['videoitem'].contentChannel
# If it is not a favorite element if you add the text plan b
if autoplay_elem['videoitem'].type_b:
text_b = '(Plan B)'
if not platformtools.is_playing() and not PLAYED:
videoitem = autoplay_elem['videoitem']
if videoitem.server.lower() not in max_intentos_servers:
max_intentos_servers[videoitem.server.lower()] = max_intentos
# If the maximum number of attempts of this server have been reached, we jump to the next
if max_intentos_servers[videoitem.server.lower()] == 0:
continue
lang = " "
if hasattr(videoitem, 'language') and videoitem.language != "":
lang = " '%s' " % videoitem.language
name = servername(videoitem.server)
platformtools.dialog_notification("AutoPlay %s" %text_b, "%s%s%s" % (name, lang, videoitem.quality.upper()), sound=False)
# Try to play the links If the channel has its own play method, use it
try: channel = __import__('channels.%s' % channel_id, None, None, ["channels.%s" % channel_id])
except: channel = __import__('specials.%s' % channel_id, None, None, ["specials.%s" % channel_id])
if hasattr(channel, 'play'):
resolved_item = getattr(channel, 'play')(videoitem)
if len(resolved_item) > 0:
if isinstance(resolved_item[0], list): videoitem.video_urls = resolved_item
else: videoitem = resolved_item[0]
# If not directly reproduce and mark as seen
# Check if the item comes from the video library
try:
if base_item.contentChannel == 'videolibrary' or base_item.nfo:
# Fill the video with the data of the main item and play
play_item = base_item.clone(**videoitem.__dict__)
platformtools.play_video(play_item, autoplay=True)
else:
# If it doesn't come from the video library, just play
platformtools.play_video(videoitem, autoplay=True)
except:
pass
sleep(3)
try:
if platformtools.is_playing():
PLAYED = True
break
except:
logger.debug(str(len(autoplay_list)))
# If we have come this far, it is because it could not be reproduced
max_intentos_servers[videoitem.server.lower()] -= 1
# If the maximum number of attempts of this server has been reached, ask if we want to continue testing or ignore it.
if max_intentos_servers[videoitem.server.lower()] == 0:
text = config.get_localized_string(60072) % name
if not platformtools.dialog_yesno("AutoPlay", text, config.get_localized_string(60073)):
max_intentos_servers[videoitem.server.lower()] = max_intentos
# If there are no items in the list, it is reported
if autoplay_elem == autoplay_list[-1]:
platformtools.dialog_notification('AutoPlay', config.get_localized_string(60072) % name)
else:
platformtools.dialog_notification(config.get_localized_string(60074), config.get_localized_string(60075))
# Restore if necessary the previous value of "Action and Player Mode" in preferences
if not user_config_setting_action: config.set_setting("default_action", user_config_setting_action)
if user_config_setting_player != 0: config.set_setting("player_mode", user_config_setting_player)
return itemlist
def play_multi_channel(item, itemlist):
logger.info()
start(itemlist, item)
def servername(server):
from core.servertools import translate_server_name
path = filetools.join(config.get_runtime_path(), 'servers', server.lower() + '.json')
name = jsontools.load(open(path, "r").read())['name'].upper()
return translate_server_name(name)
+1 -1
View File
@@ -113,7 +113,7 @@ class Downloader(object):
line2 = config.get_localized_string(59983) % ( self.downloaded[1], self.downloaded[2], self.size[1], self.size[2], self.speed[1], self.speed[2], self.connections[0], self.connections[1])
line3 = config.get_localized_string(60202) % (self.remaining_time)
progreso.update(int(self.progress), line1, line2 + " " + line3)
progreso.update(int(self.progress), line1 + '\n' + line2 + " " + line3)
self.__update_json()
finally:
progreso.close()
+4 -4
View File
@@ -271,7 +271,7 @@ def downloadfile(url, nombrefichero, headers=None, silent=False, continuar=False
# Create the progress dialog
if not silent:
progreso = platformtools.dialog_progress(header, "Downloading...", url, nombrefichero)
progreso = platformtools.dialog_progress(header, "Downloading..." + '\n' + url + '\n' + nombrefichero)
# If the platform does not return a valid dialog box, it assumes silent mode
if progreso is None:
@@ -408,7 +408,7 @@ def downloadfile(url, nombrefichero, headers=None, silent=False, continuar=False
error = downloadfileRTMP(url, nombrefichero, silent)
if error and not silent:
from platformcode import platformtools
platformtools.dialog_ok("You cannot download that video "," RTMP downloads not yet "," are supported")
platformtools.dialog_ok("You cannot download that video "," RTMP downloads not yet supported")
else:
import traceback
from pprint import pprint
@@ -480,7 +480,7 @@ def downloadfileRTMP(url, nombrefichero, silent):
rtmpdump_exit = spawnv(P_NOWAIT, rtmpdump_cmd, rtmpdump_args)
if not silent:
from platformcode import platformtools
advertencia = platformtools.dialog_ok("RTMP download option is experimental", "and the video will download in the background.", "No progress bar will be displayed.")
advertencia = platformtools.dialog_ok("RTMP download option is experimental", "and the video will download in the background. \n No progress bar will be displayed.")
except:
return True
@@ -520,7 +520,7 @@ def downloadfileGzipped(url, pathfichero):
# Create the progress dialog
from platformcode import platformtools
progreso = platformtools.dialog_progress("addon", config.get_localized_string(60200), url.split("|")[0], nombrefichero)
progreso = platformtools.dialog_progress("addon", config.get_localized_string(60200) + '\n' + url.split("|")[0] + '\n' + nombrefichero)
# Socket timeout at 60 seconds
socket.setdefaulttimeout(10)
+658
View File
@@ -0,0 +1,658 @@
# -*- coding: utf-8 -*-
# ------------------------------------------------------------
# filtertools - is responsible for filtering results
# ------------------------------------------------------------
from builtins import object
from core import jsontools
from core.item import Item
from platformcode import config, logger
from platformcode import platformtools
from core import channeltools
TAG_TVSHOW_FILTER = "TVSHOW_FILTER"
TAG_NAME = "name"
TAG_ACTIVE = "active"
TAG_LANGUAGE = "language"
TAG_QUALITY_ALLOWED = "quality_allowed"
COLOR = {"parent_item": "yellow", "error": "red", "striped_even_active": "blue",
"striped_even_inactive": "0xff00bfff", "striped_odd_active": "0xff008000",
"striped_odd_inactive": "0xff00fa9a", "selected": "blue"
}
filter_global = None
__channel__ = "filtertools"
# TODO take a look at https://pyformat.info/, you can format the style and make references directly to elements
class ResultFilter(object):
def __init__(self, dict_filter):
self.active = dict_filter[TAG_ACTIVE]
self.language = dict_filter[TAG_LANGUAGE]
self.quality_allowed = dict_filter[TAG_QUALITY_ALLOWED]
def __str__(self):
return "{active: '%s', language: '%s', quality_allowed: '%s'}" % (self.active, self.language, self.quality_allowed)
class Filter(object):
def __init__(self, item, global_filter_lang_id):
self.result = None
self.__get_data(item, global_filter_lang_id)
def __get_data(self, item, global_filter_lang_id):
dict_filtered_shows = jsontools.get_node_from_file(item.channel, TAG_TVSHOW_FILTER)
tvshow = item.show.lower().strip()
global_filter_language = config.get_setting(global_filter_lang_id, item.channel)
if tvshow in list(dict_filtered_shows.keys()):
self.result = ResultFilter({TAG_ACTIVE: dict_filtered_shows[tvshow][TAG_ACTIVE],
TAG_LANGUAGE: dict_filtered_shows[tvshow][TAG_LANGUAGE],
TAG_QUALITY_ALLOWED: dict_filtered_shows[tvshow][TAG_QUALITY_ALLOWED]})
# general option "do not filter"
elif global_filter_language != 0:
from core import channeltools
list_controls, dict_settings = channeltools.get_channel_controls_settings(item.channel)
for control in list_controls:
if control["id"] == global_filter_lang_id:
try:
language = control["lvalues"][global_filter_language]
# logger.debug("language %s" % language)
except:
logger.error("The value associated with the code was not found '%s': %s" % (global_filter_lang_id, global_filter_language))
break
self.result = ResultFilter({TAG_ACTIVE: True, TAG_LANGUAGE: language, TAG_QUALITY_ALLOWED: []})
break
def __str__(self):
return "{'%s'}" % self.result
def access():
"""
Returns whether or not filtertools can be used
"""
allow = False
if config.is_xbmc() or config.get_platform() == "mediaserver":
allow = True
return allow
def context(item, list_language=None, list_quality=None, exist=False):
"""
For xbmc / kodi and mediaserver since they can show the contextual menu, a filter option is added to the configuration menu, only if it is for series.
Depending on the place and if there is a filter, more options will be added to show.
The context -is shown only for series-.
@param item: eelement to get the information and see what context to add
@type item: item
param list_language: list of possible languages
@type list_language: list[str]
@param list_quality: list of possible qualities
@type list_quality: list[str]
@param exist: if the filter exists
@type exist: bool
@return: list of options to display in the context menu
@rtype: list
"""
# Depending on how the context is, we save it and add the filtertools options.
if isinstance(item.context, str):
_context = item.context.split("|")
elif isinstance(item.context, list):
_context = item.context
else:
_context = []
if access():
dict_data = {"title": config.get_localized_string(60426), "action": "config_item", "channel": "filtertools"}
if list_language:
dict_data["list_language"] = list_language
if list_quality:
dict_data["list_quality"] = list_quality
added = False
if isinstance(_context, list):
for x in _context:
if x and isinstance(x, dict):
if x["channel"] == "filtertools":
added = True
break
if not added:
_context.append(dict_data)
if item.action == "play":
if not exist:
_context.append({"title": config.get_localized_string(60427) % item.language, "action": "save_from_context",
"channel": "filtertools", "from_channel": item.channel})
else:
_context.append({"title": config.get_localized_string(60428) % item.language, "action": "delete_from_context",
"channel": "filtertools", "from_channel": item.channel})
return _context
def show_option(itemlist, channel, list_language, list_quality):
if access():
itemlist.append(Item(channel=__channel__, title=config.get_localized_string(60429) % COLOR.get("parent_item", "auto"), action="load",
list_language=list_language, list_quality=list_quality, from_channel=channel))
return itemlist
def load(item):
return mainlist(channel=item.from_channel, list_language=item.list_language, list_quality=item.list_quality)
def check_conditions(_filter, list_item, item, list_language, list_quality, quality_count=0, language_count=0):
is_language_valid = True
if _filter.language:
# logger.debug("title es %s" % item.title)
# 2nd lang
from platformcode import unify
_filter.language = unify.set_lang(_filter.language).upper()
# comes from episodes
if isinstance(item.language, list):
# 2nd lang
for n, lang in enumerate(item.language):
item.language[n] = unify.set_lang(lang).upper()
if _filter.language in item.language:
language_count += 1
else:
is_language_valid = False
# comes from findvideos
else:
# 2nd lang
item.language = unify.set_lang(item.language).upper()
if item.language.lower() == _filter.language.lower():
language_count += 1
else:
is_language_valid = False
is_quality_valid = True
quality = ""
if _filter.quality_allowed and item.quality != "":
# if hasattr (item, 'quality'): # this validation is not necessary because the empty attribute is ALWAYS returned
if item.quality.lower() in _filter.quality_allowed:
quality = item.quality.lower()
quality_count += 1
else:
is_quality_valid = False
if is_language_valid and is_quality_valid:
#TODO 2nd lang: we should see if it is convenient to unify the language here or not
item.list_language = list_language
if list_quality:
item.list_quality = list_quality
item.context = context(item, exist=True)
list_item.append(item)
# logger.debug("{0} | context: {1}".format(item.title, item.context))
# logger.debug(" -Enlace añadido")
elif not item.language:
list_item.append(item)
logger.debug(" idioma valido?: %s, item.language: %s, filter.language: %s" % (is_language_valid, item.language, _filter.language))
logger.debug(" calidad valida?: %s, item.quality: %s, filter.quality_allowed: %s" % (is_quality_valid, quality, _filter.quality_allowed))
return list_item, quality_count, language_count, _filter.language
def get_link(list_item, item, list_language, list_quality=None, global_filter_lang_id="filter_languages"):
"""
Returns a list of links, if the item is correctly filtered it is added to the received list.
@param list_item: list of links
@type list_item: list[Item]
@param item: element to filter
@type item: Item
@param list_language: list of possible languages
@type list_language: list[str]
@param list_quality: list of possible qualities
@type list_quality: list[str]
@param global_filter_lang_id: id of the filtering variable by language that is in settings
@type global_filter_lang_id: str
@return: Item list
@rtype: list[Item]
"""
logger.info()
# if the required fields are None we leave
if list_item is None or item is None:
return []
logger.debug("total de items : %s" % len(list_item))
global filter_global
if not filter_global:
filter_global = Filter(item, global_filter_lang_id).result
logger.debug("filter: '%s' datos: '%s'" % (item.show, filter_global))
if filter_global and filter_global.active:
list_item, quality_count, language_count = check_conditions(filter_global, list_item, item, list_language, list_quality)[:3]
else:
item.context = context(item)
list_item.append(item)
return list_item
def get_links(list_item, item, list_language, list_quality=None, global_filter_lang_id="filter_languages"):
"""
Returns a list of filtered links.
@param list_item: list of links
@type list_item: list[Item]
@param item: element to filter
@type item: item
@param list_language: list of possible languages
@type list_language: list[str]
@param list_quality: list of possible qualities
@type list_quality: list[str]
@param global_filter_lang_id: id of the filtering variable by language that is in settings
@type global_filter_lang_id: str
@return: lista de Item
@rtype: list[Item]
"""
logger.info()
# if the required fields are None we leave
if list_item is None or item is None:
return []
# if list_item is empty we go back, no platform validation is added so Plex can do global filter
if len(list_item) == 0:
return list_item
second_lang = config.get_setting('second_language')
logger.debug("total de items : %s" % len(list_item))
new_itemlist = []
quality_count = 0
language_count = 0
_filter = Filter(item, global_filter_lang_id).result
logger.debug("filter: '%s' datos: '%s'" % (item.show, _filter))
if _filter and _filter.active:
for item in list_item:
new_itemlist, quality_count, language_count, first_lang = check_conditions(_filter, new_itemlist, item, list_language, list_quality, quality_count, language_count)
#2nd lang
if second_lang and second_lang != 'No' and first_lang.lower() != second_lang.lower() :
second_list= []
_filter2 = _filter
_filter2.language = second_lang
for it in new_itemlist:
if isinstance(it.language, list):
if not second_lang in it.language:
second_list.append(it)
else:
second_list = new_itemlist
break
for item in list_item:
new_itemlist, quality_count, language_count, second_lang = check_conditions(_filter2, second_list, item, list_language, list_quality, quality_count, language_count)
logger.debug("FILTERED ITEMS: %s/%s, language [%s]: %s, allowed quality %s: %s" % (len(new_itemlist), len(list_item), _filter.language, language_count, _filter.quality_allowed, quality_count))
if len(new_itemlist) == 0:
list_item_all = []
for i in list_item:
list_item_all.append(i.tourl())
_context = [{"title": config.get_localized_string(60430) % _filter.language, "action": "delete_from_context", "channel": "filtertools", "to_channel": item.channel}]
if _filter.quality_allowed:
msg_quality_allowed = " y calidad %s" % _filter.quality_allowed
else:
msg_quality_allowed = ""
msg_lang = ' %s' % first_lang.upper()
if second_lang and second_lang != 'No':
msg_lang = 's %s ni %s' % (first_lang.upper(), second_lang.upper())
new_itemlist.append(Item(channel=__channel__, action="no_filter", list_item_all=list_item_all,
show=item.show,
title=config.get_localized_string(60432) % (_filter.language, msg_quality_allowed),
context=_context))
else:
for item in list_item:
item.list_language = list_language
if list_quality:
item.list_quality = list_quality
item.context = context(item)
new_itemlist = list_item
return new_itemlist
def no_filter(item):
"""
Muestra los enlaces sin filtrar
@param item: item
@type item: Item
@return: lista de enlaces
@rtype: list[Item]
"""
logger.info()
itemlist = []
for i in item.list_item_all:
itemlist.append(Item().fromurl(i))
return itemlist
def mainlist(channel, list_language, list_quality):
"""
Shows a list of the leaked series
@param channel: channel name to get filtered series
@type channel: str
@param list_language: channel language list
@type list_language: list[str]
@param list_quality: channel quality list
@type list_quality: list[str]
@return: Item list
@rtype: list[Item]
"""
logger.info()
itemlist = []
dict_series = jsontools.get_node_from_file(channel, TAG_TVSHOW_FILTER)
idx = 0
for tvshow in sorted(dict_series):
if idx % 2 == 0:
if dict_series[tvshow][TAG_ACTIVE]:
tag_color = COLOR.get("striped_even_active", "auto")
else:
tag_color = COLOR.get("striped_even_inactive", "auto")
else:
if dict_series[tvshow][TAG_ACTIVE]:
tag_color = COLOR.get("striped_odd_active", "auto")
else:
tag_color = COLOR.get("striped_odd_inactive", "auto")
idx += 1
name = dict_series.get(tvshow, {}).get(TAG_NAME, tvshow)
activo = config.get_localized_string(60433)
if dict_series[tvshow][TAG_ACTIVE]:
activo = ""
title = config.get_localized_string(60434) % (tag_color, name, activo)
itemlist.append(Item(channel=__channel__, action="config_item", title=title, show=name,
list_language=list_language, list_quality=list_quality, from_channel=channel))
if len(itemlist) == 0:
itemlist.append(Item(channel=channel, action="mainlist", title=config.get_localized_string(60435)))
return itemlist
def config_item(item):
"""
displays a filtered series for your setup
@param item: item
@type item: Item
"""
logger.info()
logger.info("item %s" % item.tostring())
# WE GET THE JSON DATA
dict_series = jsontools.get_node_from_file(item.from_channel, TAG_TVSHOW_FILTER)
tvshow = item.show.lower().strip()
default_lang = ''
channel_parameters = channeltools.get_channel_parameters(item.from_channel)
list_language = channel_parameters["filter_languages"]
try:
if channel_parameters["filter_languages"] != '' and len(list_language) > 0:
default_lang = list_language[1]
except:
pass
if default_lang == '':
platformtools.dialog_notification("FilterTools", "There are no defined languages")
return
else:
lang_selected = dict_series.get(tvshow, {}).get(TAG_LANGUAGE, default_lang)
list_quality = dict_series.get(tvshow, {}).get(TAG_QUALITY_ALLOWED, [x.lower() for x in item.list_quality])
# logger.info("lang selected {}".format(lang_selected))
# logger.info("list quality {}".format(list_quality))
active = True
custom_button = {'visible': False}
allow_option = False
if item.show.lower().strip() in dict_series:
allow_option = True
active = dict_series.get(item.show.lower().strip(), {}).get(TAG_ACTIVE, False)
custom_button = {'label': config.get_localized_string(60437), 'function': 'delete', 'visible': True, 'close': True}
list_controls = []
if allow_option:
active_control = {
"id": "active",
"type": "bool",
"label": config.get_localized_string(60438),
"color": "",
"default": active,
"enabled": allow_option,
"visible": allow_option,
}
list_controls.append(active_control)
language_option = {
"id": "language",
"type": "list",
"label": config.get_localized_string(60439),
# "color": "0xFFee66CC",
"default": item.list_language.index(lang_selected),
"enabled": True,
"visible": True,
"lvalues": item.list_language
}
list_controls.append(language_option)
if item.list_quality:
list_controls_calidad = [
{
"id": "textoCalidad",
"type": "label",
"label": "Calidad permitida",
"color": "0xffC6C384",
"enabled": True,
"visible": True,
},
]
for element in sorted(item.list_quality, key=str.lower):
list_controls_calidad.append({
"id": element,
"type": "bool",
"label": element,
"default": (False, True)[element.lower() in list_quality],
"enabled": True,
"visible": True,
})
# we concatenate list_controls with list_controls_quality
list_controls.extend(list_controls_calidad)
title = config.get_localized_string(60441) % (COLOR.get("selected", "auto"), item.show)
platformtools.show_channel_settings(list_controls=list_controls, callback='save', item=item,
caption=title, custom_button=custom_button)
def delete(item, dict_values):
logger.info()
if item:
dict_series = jsontools.get_node_from_file(item.from_channel, TAG_TVSHOW_FILTER)
tvshow = item.show.strip().lower()
heading = config.get_localized_string(60442)
line1 = config.get_localized_string(60443) % (COLOR.get("selected", "auto"), item.show.strip())
if platformtools.dialog_yesno(heading, line1) == 1:
lang_selected = dict_series.get(tvshow, {}).get(TAG_LANGUAGE, "")
dict_series.pop(tvshow, None)
result, json_data = jsontools.update_node(dict_series, item.from_channel, TAG_TVSHOW_FILTER)
sound = False
if result:
message = config.get_localized_string(60444)
else:
message = config.get_localized_string(60445)
sound = True
heading = "%s [%s]" % (item.show.strip(), lang_selected)
platformtools.dialog_notification(heading, message, sound=sound)
if item.action in ["findvideos", "play"]:
platformtools.itemlist_refresh()
def save(item, dict_data_saved):
"""
Save the configured values in the window
@param item: item
@type item: Item
@param dict_data_saved: dictionary with saved data
@type dict_data_saved: dict
"""
logger.info()
if item and dict_data_saved:
logger.debug('item: %s\ndatos: %s' % (item.tostring(), dict_data_saved))
if item.from_channel == "videolibrary":
item.from_channel = item.contentChannel
dict_series = jsontools.get_node_from_file(item.from_channel, TAG_TVSHOW_FILTER)
tvshow = item.show.strip().lower()
logger.info("Data is updated")
list_quality = []
for _id, value in list(dict_data_saved.items()):
if _id in item.list_quality and value:
list_quality.append(_id.lower())
lang_selected = item.list_language[dict_data_saved[TAG_LANGUAGE]]
dict_filter = {TAG_NAME: item.show, TAG_ACTIVE: dict_data_saved.get(TAG_ACTIVE, True),
TAG_LANGUAGE: lang_selected, TAG_QUALITY_ALLOWED: list_quality}
dict_series[tvshow] = dict_filter
result, json_data = jsontools.update_node(dict_series, item.from_channel, TAG_TVSHOW_FILTER)
sound = False
if result:
message = config.get_localized_string(60446)
else:
message = config.get_localized_string(70593)
sound = True
heading = "%s [%s]" % (item.show.strip(), lang_selected)
platformtools.dialog_notification(heading, message, sound=sound)
if item.from_action in ["findvideos", "play"]:
platformtools.itemlist_refresh()
def save_from_context(item):
"""
Save the filter through the context menu
@param item: item
@type item: item
"""
logger.info()
dict_series = jsontools.get_node_from_file(item.from_channel, TAG_TVSHOW_FILTER)
tvshow = item.show.strip().lower()
dict_filter = {TAG_NAME: item.show, TAG_ACTIVE: True, TAG_LANGUAGE: item.language, TAG_QUALITY_ALLOWED: []}
dict_series[tvshow] = dict_filter
result, json_data = jsontools.update_node(dict_series, item.from_channel, TAG_TVSHOW_FILTER)
sound = False
if result:
message = "SAVED FILTER"
else:
message = "Error saving to disk"
sound = True
heading = "%s [%s]" % (item.show.strip(), item.language)
platformtools.dialog_notification(heading, message, sound=sound)
if item.from_action in ["findvideos", "play"]:
platformtools.itemlist_refresh()
def delete_from_context(item):
"""
Delete the filter through the context menu
@param item: item
@type item: item
"""
logger.info()
# We come from get_links and no result has been obtained, in context menu and we delete
if item.to_channel != "":
item.from_channel = item.to_channel
dict_series = jsontools.get_node_from_file(item.from_channel, TAG_TVSHOW_FILTER)
tvshow = item.show.strip().lower()
lang_selected = dict_series.get(tvshow, {}).get(TAG_LANGUAGE, "")
dict_series.pop(tvshow, None)
result, json_data = jsontools.update_node(dict_series, item.from_channel, TAG_TVSHOW_FILTER)
sound = False
if result:
message = "FILTER REMOVED"
else:
message = "Error saving to disk"
sound = True
heading = "%s [%s]" % (item.show.strip(), lang_selected)
platformtools.dialog_notification(heading, message, sound=sound)
if item.from_action in ["findvideos", "play", "no_filter"]: # 'no_filter' es el mismo caso que L#601
platformtools.itemlist_refresh()
+19 -16
View File
@@ -137,7 +137,7 @@ load_cookies()
def save_cookies(alfa_s=False):
cookies_lock.acquire()
if not alfa_s: logger.info("Saving cookies...")
if not alfa_s: logger.debug("Saving cookies...")
cj.save(cookies_file, ignore_discard=True)
cookies_lock.release()
@@ -161,7 +161,7 @@ def random_useragent():
def show_infobox(info_dict):
logger.info()
logger.debug()
from textwrap import wrap
box_items_kodi = {'r_up_corner': u'\u250c',
@@ -186,16 +186,16 @@ def show_infobox(info_dict):
width = 60
width = 100
version = '%s: %s' % (config.get_localized_string(20000), __version)
if config.is_xbmc():
box = box_items_kodi
else:
box = box_items
logger.info('%s%s%s' % (box['r_up_corner'], box['fill'] * width, box['l_up_corner']))
logger.info('%s%s%s' % (box['center'], version.center(width), box['center']))
logger.info('%s%s%s' % (box['r_center'], box['fill'] * width, box['l_center']))
logger.debug('%s%s%s' % (box['r_up_corner'], box['fill'] * width, box['l_up_corner']))
logger.debug('%s%s%s' % (box['center'], version.center(width), box['center']))
logger.debug('%s%s%s' % (box['r_center'], box['fill'] * width, box['l_center']))
count = 0
for key, value in info_dict:
@@ -210,13 +210,13 @@ def show_infobox(info_dict):
for line in text:
if len(line) < width:
line = line.ljust(width, ' ')
logger.info('%s%s%s' % (box['center'], line, box['center']))
logger.debug('%s%s%s' % (box['center'], line, box['center']))
else:
logger.info('%s%s%s' % (box['center'], text, box['center']))
logger.debug('%s%s%s' % (box['center'], text, box['center']))
if count < len(info_dict):
logger.info('%s%s%s' % (box['r_center'], box['fill'] * width, box['l_center']))
logger.debug('%s%s%s' % (box['r_center'], box['fill'] * width, box['l_center']))
else:
logger.info('%s%s%s' % (box['r_dn_corner'], box['fill'] * width, box['l_dn_corner']))
logger.debug('%s%s%s' % (box['r_dn_corner'], box['fill'] * width, box['l_dn_corner']))
return
@@ -284,7 +284,7 @@ def downloadpage(url, **opt):
CF = True
if config.get_setting('resolver_dns') and not opt.get('use_requests', False):
from specials import resolverdns
from core import resolverdns
session.mount('https://', resolverdns.CipherSuiteAdapter(domain, CF))
req_headers = default_headers.copy()
@@ -402,6 +402,13 @@ def downloadpage(url, **opt):
response['data'] = req.content if req.content else ''
response['url'] = req.url
if type(response['data']) != str:
try: response['data'] = response['data'].decode('utf-8')
except: response['data'] = response['data'].decode('ISO-8859-1')
if not response['data']:
response['data'] = ''
if req.headers.get('Server', '').startswith('cloudflare') and response_code in [429, 503, 403]\
and not opt.get('CF', False) and 'Please turn JavaScript on and reload the page' in response['data']:
# if domain not in CF_LIST:
@@ -416,15 +423,11 @@ def downloadpage(url, **opt):
response['data'] = re.sub('["|\']/save/[^"]*(https?://[^"]+)', '"\\1', response['data'])
response['url'] = response['url'].replace('https://web.archive.org/save/', '')
if type(response['data']) != str:
response['data'] = response['data'].decode('UTF-8')
if not response['data']:
response['data'] = ''
try:
response['json'] = to_utf8(req.json())
except:
response['json'] = dict()
response['code'] = response_code
response['headers'] = req.headers
response['cookies'] = req.cookies
+2 -2
View File
@@ -90,7 +90,7 @@ def get_node_from_file(name_file, node, path=None):
@return: dict with the node to return
@rtype: dict
"""
logger.info()
logger.debug()
from platformcode import config
from core import filetools
@@ -129,7 +129,7 @@ def check_to_backup(data, fname, dict_data):
@param dict_data: dictionary name
@type dict_data: dict
"""
logger.info()
logger.debug()
if not dict_data:
logger.error("Error loading json from file %s" % fname)
+151
View File
@@ -0,0 +1,151 @@
# -*- coding: utf-8 -*-
import os, sys, ssl
PY3 = False
if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int
if PY3:
import urllib.parse as urlparse
import _ssl
DEFAULT_CIPHERS = _ssl._DEFAULT_CIPHERS
else:
import urlparse
DEFAULT_CIPHERS = ssl._DEFAULT_CIPHERS
from lib.requests_toolbelt.adapters import host_header_ssl
from lib import doh
from platformcode import logger, config
import requests
from core import scrapertools
try:
import _sqlite3 as sql
except:
import sqlite3 as sql
db = os.path.join(config.get_data_path(), 'kod_db.sqlite')
if 'PROTOCOL_TLS' in ssl.__dict__:
protocol = ssl.PROTOCOL_TLS
elif 'PROTOCOL_SSLv23' in ssl.__dict__:
protocol = ssl.PROTOCOL_SSLv23
else:
protocol = ssl.PROTOCOL_SSLv3
class CustomContext(ssl.SSLContext):
def __init__(self, protocol, hostname, *args, **kwargs):
self.hostname = hostname
if PY3:
super(CustomContext, self).__init__()
else:
super(CustomContext, self).__init__(protocol)
self.verify_mode = ssl.CERT_NONE
def wrap_socket(self, *args, **kwargs):
kwargs['server_hostname'] = self.hostname
self.verify_mode = ssl.CERT_NONE
return super(CustomContext, self).wrap_socket(*args, **kwargs)
class CipherSuiteAdapter(host_header_ssl.HostHeaderSSLAdapter):
def __init__(self, domain, CF=False, *args, **kwargs):
self.conn = sql.connect(db)
self.cur = self.conn.cursor()
self.ssl_context = CustomContext(protocol, domain)
self.CF = CF # if cloudscrape is in action
self.cipherSuite = kwargs.pop('cipherSuite', DEFAULT_CIPHERS)
super(CipherSuiteAdapter, self).__init__(**kwargs)
def flushDns(self, request, domain, **kwargs):
self.cur.execute('delete from dnscache where domain=?', (domain,))
self.conn.commit()
return self.send(request, flushedDns=True, **kwargs)
def getIp(self, domain):
ip = None
try:
self.cur.execute('select ip from dnscache where domain=?', (domain,))
ip = self.cur.fetchall()[0][0]
logger.info('Cache DNS: ' + domain + ' = ' + str(ip))
except:
pass
if not ip: # not cached
try:
ip = doh.query(domain)[0]
logger.info('Query DoH: ' + domain + ' = ' + str(ip))
self.writeToCache(domain, ip)
except Exception:
logger.error('Failed to resolve hostname, fallback to normal dns')
import traceback
logger.error(traceback.print_exc())
return ip
def writeToCache(self, domain, ip):
try:
self.cur.execute('insert into dnscache values(?,?)', (domain, ip))
except:
self.cur.execute("""CREATE TABLE IF NOT EXISTS dnscache(
"domain" TEXT NOT NULL UNIQUE,
"ip" TEXT NOT NULL,
PRIMARY KEY("domain")
);""")
self.conn.commit()
def init_poolmanager(self, *args, **kwargs):
kwargs['ssl_context'] = self.ssl_context
return super(CipherSuiteAdapter, self).init_poolmanager(*args, **kwargs)
def proxy_manager_for(self, *args, **kwargs):
kwargs['ssl_context'] = self.ssl_context
return super(CipherSuiteAdapter, self).proxy_manager_for(*args, **kwargs)
def send(self, request, flushedDns=False, **kwargs):
try:
parse = urlparse.urlparse(request.url)
except:
raise requests.exceptions.InvalidURL
if parse.netloc:
domain = parse.netloc
else:
raise requests.exceptions.URLRequired
if not scrapertools.find_single_match(domain, '\d+\.\d+\.\d+\.\d+'):
ip = self.getIp(domain)
else:
ip = None
if ip:
self.ssl_context = CustomContext(protocol, domain)
if self.CF:
self.ssl_context.options |= (ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 | ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1)
self.ssl_context.set_ciphers(self.cipherSuite)
self.init_poolmanager(self._pool_connections, self._pool_maxsize, block=self._pool_block)
realUrl = request.url
if request.headers:
request.headers["Host"] = domain
else:
request.headers = {"Host": domain}
ret = None
tryFlush = False
parse = list(parse)
parse[1] = ip
request.url = urlparse.urlunparse(parse)
try:
ret = super(CipherSuiteAdapter, self).send(request, **kwargs)
except Exception as e:
logger.info('Request for ' + domain + ' with ip ' + ip + ' failed')
logger.info(e)
# if 'SSLError' in str(e):
# # disabilito
# config.set_setting("resolver_dns", False)
# request.url = realUrl
# ret = super(CipherSuiteAdapter, self).send(request, **kwargs)
# else:
tryFlush = True
if tryFlush and not flushedDns: # re-request ips and update cache
logger.info('Flushing dns cache for ' + domain)
return self.flushDns(request, domain, **kwargs)
ret.url = realUrl
else:
ret = super(host_header_ssl.HostHeaderSSLAdapter, self).send(request, **kwargs)
return ret
+7 -4
View File
@@ -85,11 +85,12 @@ def decodeHtmlentities(data):
if match.group(1) == "#" and ent.replace(";", "").isdigit():
ent = unichr(int(ent.replace(";", "")))
return ent.encode('utf-8')
return ent if PY3 else ent.encode('utf-8')
else:
cp = html5.get(ent)
if cp:
return cp.decode("unicode-escape").encode('utf-8') + res
if PY3: return cp + res
else: return cp.decode("unicode-escape").encode('utf-8') + res
else:
return match.group()
@@ -112,9 +113,11 @@ def unescape(text):
# character reference
try:
if text[:3] == "&#x":
return unichr(int(text[3:-1], 16)).encode("utf-8")
ret = unichr(int(text[3:-1], 16))
return ret if PY3 else ret.encode("utf-8")
else:
return unichr(int(text[2:-1])).encode("utf-8")
ret = unichr(int(text[2:-1]))
return ret if PY3 else ret.encode("utf-8")
except ValueError:
logger.error("error de valor")
+7 -20
View File
@@ -148,26 +148,13 @@ def findvideos(data, skip=False):
devuelve = []
skip = int(skip)
servers_list = list(get_servers_list().keys())
# is_filter_servers = False
# Run findvideos on each active server
for serverid in servers_list:
'''if not is_server_enabled(serverid):
continue'''
if config.get_setting('servers_blacklist') and serverid not in config.get_setting("black_list", server='servers'):
# if config.get_setting("filter_servers") == True and config.get_setting("black_list", server=serverid):
# is_filter_servers = True
continue
devuelve.extend(findvideosbyserver(data, serverid))
if skip and len(devuelve) >= skip:
devuelve = devuelve[:skip]
break
# if config.get_setting("filter_servers") == False: is_filter_servers = False
# logger.info('DEVUELVE: ' + str(devuelve))
# if not devuelve and is_filter_servers:
# platformtools.dialog_ok(config.get_localized_string(60000), config.get_localized_string(60001))
if is_server_enabled(serverid) :
devuelve.extend(findvideosbyserver(data, serverid))
if skip and len(devuelve) >= skip:
devuelve = devuelve[:skip]
break
return devuelve
@@ -710,9 +697,9 @@ def sort_servers(servers_list):
"""
if servers_list and config.get_setting('favorites_servers'):
if isinstance(servers_list[0], Item):
servers_list = sorted(servers_list, key=lambda x: config.get_setting("favorites_servers_list", server=x.server) or 100)
servers_list = sorted(servers_list, key=lambda x: config.get_setting("favorites_servers_list", server=x.server))
else:
servers_list = sorted(servers_list, key=lambda x: config.get_setting("favorites_servers_list", server=x) or 100)
servers_list = sorted(servers_list, key=lambda x: config.get_setting("favorites_servers_list", server=x))
return servers_list
+193 -116
View File
@@ -1,34 +1,29 @@
# -*- coding: utf-8 -*-
# -----------------------------------------------------------
# support functions that are needed by many channels, to no repeat the same code
import base64
import inspect
import os
import re
import sys
from time import time
import base64, inspect, os, re, sys
PY3 = False
if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int
if PY3:
from concurrent import futures
else:
from concurrent_py2 import futures
try:
import urllib.request as urllib
from urllib.request import Request, urlopen
import urllib.parse as urlparse
from urllib.parse import urlencode
except ImportError:
import urllib, urlparse
else:
from concurrent_py2 import futures
import urlparse
from urllib2 import Request, urlopen
from urllib import urlencode
from channelselector import thumb
from core import httptools, scrapertools, servertools, tmdb, channeltools
from time import time
from core import httptools, scrapertools, servertools, tmdb, channeltools, autoplay
from core.item import Item
from lib import unshortenit
from platformcode import logger, config
from specials import autoplay
from platformcode import config
from platformcode.logger import info
from platformcode import logger
def hdpass_get_servers(item):
def get_hosts(url, quality):
@@ -38,29 +33,21 @@ def hdpass_get_servers(item):
for mir_url, srv in scrapertools.find_multiple_matches(mir, patron_option):
mir_url = scrapertools.decodeHtmlentities(mir_url)
log(mir_url)
it = item.clone(action="play",
quality=quality,
title=srv,
server=srv,
url= mir_url)
if not servertools.get_server_parameters(srv.lower()): # do not exists or it's empty
it = hdpass_get_url(it)[0]
info(mir_url)
it = item.clone(action="play", quality=quality, title=srv, server=srv, url= mir_url)
if not servertools.get_server_parameters(srv.lower()): it = hdpass_get_url(it)[0] # do not exists or it's empty
ret.append(it)
return ret
# Carica la pagina
itemlist = []
if 'hdpass' in item.url or 'hdplayer' in item.url:
url = item.url
if 'hdpass' in item.url or 'hdplayer' in item.url: url = item.url
else:
data = httptools.downloadpage(item.url, CF=False).data.replace('\n', '')
patron = r'<iframe(?: id="[^"]+")? width="[^"]+" height="[^"]+" src="([^"]+)"[^>]+><\/iframe>'
url = scrapertools.find_single_match(data, patron)
url = url.replace("&download=1", "")
if 'hdpass' not in url and 'hdplayer' not in url:
return itemlist
if not url.startswith('http'):
url = 'https:' + url
if 'hdpass' not in url and 'hdplayer' not in url: return itemlist
if not url.startswith('http'): url = 'https:' + url
data = httptools.downloadpage(url, CF=False).data
patron_res = '<div class="buttons-bar resolutions-bar">(.*?)<div class="buttons-bar'
@@ -68,7 +55,6 @@ def hdpass_get_servers(item):
patron_option = r'<a href="([^"]+?)"[^>]+>([^<]+?)</a'
res = scrapertools.find_single_match(data, patron_res)
# dbg()
with futures.ThreadPoolExecutor() as executor:
thL = []
@@ -78,15 +64,14 @@ def hdpass_get_servers(item):
for res in futures.as_completed(thL):
if res.result():
itemlist.extend(res.result())
return server(item, itemlist=itemlist)
return server(item, itemlist=itemlist)
def hdpass_get_url(item):
data = httptools.downloadpage(item.url, CF=False).data
src = scrapertools.find_single_match(data, r'<iframe allowfullscreen custom-src="([^"]+)')
if src:
item.url = base64.b64decode(src)
else:
item.url = scrapertools.find_single_match(data, r'<iframe allowfullscreen src="([^"]+)')
if src: item.url = base64.b64decode(src)
else: item.url = scrapertools.find_single_match(data, r'<iframe allowfullscreen src="([^"]+)')
item.url, c = unshortenit.unshorten_only(item.url)
return [item]
@@ -96,9 +81,8 @@ def color(text, color):
def search(channel, item, texto):
log(item.url + " search " + texto)
if 'findhost' in dir(channel):
channel.findhost()
info(item.url + " search " + texto)
if 'findhost' in dir(channel): channel.findhost()
item.url = channel.host + "/?s=" + texto
try:
return channel.peliculas(item)
@@ -121,7 +105,7 @@ def dbg():
def regexDbg(item, patron, headers, data=''):
if config.dev_mode():
import json, urllib2, webbrowser
import json, webbrowser
url = 'https://regex101.com'
if not data:
@@ -132,14 +116,15 @@ def regexDbg(item, patron, headers, data=''):
html = data
headers = {'content-type': 'application/json'}
data = {
'regex': patron.decode('utf-8'),
'regex': patron if PY3 else patron.decode('utf-8'),
'flags': 'gm',
'testString': html.decode('utf-8'),
'testString': html if PY3 else html.decode('utf-8'),
'delimiter': '"""',
'flavor': 'python'
}
r = urllib2.Request(url + '/api/regex', json.dumps(data, encoding='latin1'), headers=headers)
r = urllib2.urlopen(r).read()
data = json.dumps(data).encode() if PY3 else json.dumps(data, encoding='latin1')
r = Request(url + '/api/regex', data, headers=headers)
r = urlopen(r).read()
permaLink = json.loads(r)['permalinkFragment']
webbrowser.open(url + "/r/" + permaLink)
@@ -152,10 +137,8 @@ def scrapeLang(scraped, lang, longtitle):
language = ''
if scraped['lang']:
if 'ita' in scraped['lang'].lower():
language = 'ITA'
if 'sub' in scraped['lang'].lower():
language = 'Sub-' + language
if 'ita' in scraped['lang'].lower(): language = 'ITA'
if 'sub' in scraped['lang'].lower(): language = 'Sub-' + language
if not language: language = lang
if language: longtitle += typo(language, '_ [] color kod')
@@ -177,11 +160,10 @@ def unifyEp(ep):
def scrapeBlock(item, args, block, patron, headers, action, pagination, debug, typeContentDict, typeActionDict, blacklist, search, pag, function, lang, sceneTitle):
itemlist = []
log("scrapeBlock qui")
if debug:
regexDbg(item, patron, headers, block)
matches = scrapertools.find_multiple_matches_groups(block, patron)
log('MATCHES =', matches)
logger.debug('MATCHES =', matches)
known_keys = ['url', 'title', 'title2', 'season', 'episode', 'thumb', 'quality', 'year', 'plot', 'duration', 'genere', 'rating', 'type', 'lang', 'other', 'size', 'seed']
# Legenda known_keys per i groups nei patron
@@ -298,7 +280,7 @@ def scrapeBlock(item, args, block, patron, headers, action, pagination, debug, t
try:
parsedTitle = guessit(title)
title = longtitle = parsedTitle.get('title', '')
log('TITOLO',title)
logger.debug('TITOLO',title)
if parsedTitle.get('source'):
quality = str(parsedTitle.get('source'))
if parsedTitle.get('screen_size'):
@@ -332,7 +314,7 @@ def scrapeBlock(item, args, block, patron, headers, action, pagination, debug, t
longtitle += s + parsedTitle.get('episode_title')
item.contentEpisodeTitle = parsedTitle.get('episode_title')
except:
log('Error')
logger.debug('Error')
longtitle = typo(longtitle, 'bold')
lang1, longtitle = scrapeLang(scraped, lang, longtitle)
@@ -419,7 +401,7 @@ def scrape(func):
args = func(*args)
function = func.__name__ if not 'actLike' in args else args['actLike']
# log('STACK= ',inspect.stack()[1][3])
# info('STACK= ',inspect.stack()[1][3])
item = args['item']
@@ -451,12 +433,13 @@ def scrape(func):
matches = []
for n in range(2):
log('PATRON= ', patron)
logger.debug('PATRON= ', patron)
if not data:
page = httptools.downloadpage(item.url, headers=headers, ignore_response_code=True)
data = re.sub("='([^']+)'", '="\\1"', page.data)
data = data.replace('\n', ' ')
data = data.replace('\t', ' ')
data = data.replace('&nbsp;', ' ')
data = re.sub(r'>\s+<', '> <', data)
# replace all ' with " and eliminate newline, so we don't need to worry about
scrapingTime = time()
@@ -466,7 +449,7 @@ def scrape(func):
blocks = scrapertools.find_multiple_matches_groups(data, patronBlock)
block = ""
for bl in blocks:
# log(len(blocks),bl)
# info(len(blocks),bl)
if 'season' in bl and bl['season']:
item.season = bl['season']
blockItemlist, blockMatches = scrapeBlock(item, args, bl['block'], patron, headers, action, pagination, debug,
@@ -491,7 +474,7 @@ def scrape(func):
# if url may be changed and channel has findhost to update
if 'findhost' in func.__globals__ and not itemlist:
logger.info('running findhost ' + func.__module__)
info('running findhost ' + func.__module__)
host = func.__globals__['findhost']()
parse = list(urlparse.urlparse(item.url))
from core import jsontools
@@ -505,7 +488,7 @@ def scrape(func):
break
if (pagination and len(matches) <= pag * pagination) or not pagination: # next page with pagination
if patronNext and inspect.stack()[1][3] not in ['newest', 'search']:
if patronNext and inspect.stack()[1][3] not in ['newest']:
nextPage(itemlist, item, data, patronNext, function)
# next page for pagination
@@ -526,7 +509,7 @@ def scrape(func):
tmdb.set_infoLabels_itemlist(itemlist, seekTmdb=True)
if anime:
from specials import autorenumber
from platformcode import autorenumber
if function == 'episodios' or item.action == 'episodios': autorenumber.renumber(itemlist, item, 'bold')
else: autorenumber.renumber(itemlist)
# if anime and autorenumber.check(item) == False and len(itemlist)>0 and not scrapertools.find_single_match(itemlist[0].title, r'(\d+.\d+)'):
@@ -548,7 +531,7 @@ def scrape(func):
if config.get_setting('trakt_sync'):
from core import trakt_tools
trakt_tools.trakt_check(itemlist)
log('scraping time: ', time()-scrapingTime)
logger.debug('scraping time: ', time()-scrapingTime)
return itemlist
return wrapper
@@ -726,15 +709,11 @@ def menuItem(itemlist, filename, title='', action='', url='', contentType='undef
def menu(func):
def wrapper(*args):
log()
args = func(*args)
item = args['item']
log(item.channel + ' start')
logger.debug(item.channel + ' menu start')
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']
log('LIST QUALITY', list_quality)
filename = func.__module__.split('.')[1]
single_search = False
# listUrls = ['film', 'filmSub', 'tvshow', 'tvshowSub', 'anime', 'animeSub', 'search', 'top', 'topSub']
@@ -749,7 +728,7 @@ def menu(func):
for name in listUrls:
dictUrl[name] = args[name] if name in args else None
log(dictUrl[name])
logger.debug(dictUrl[name])
if name == 'film': title = 'Film'
if name == 'tvshow': title = 'Serie TV'
if name == 'anime': title = 'Anime'
@@ -816,9 +795,8 @@ def menu(func):
channel_config(item, itemlist)
# Apply auto Thumbnails at the menus
from channelselector import thumb
thumb(itemlist)
log(item.channel + ' end')
logger.debug(item.channel + ' menu end')
return itemlist
return wrapper
@@ -944,6 +922,7 @@ def match(item_url_string, **args):
data = re.sub("='([^']+)'", '="\\1"', data)
data = data.replace('\n', ' ')
data = data.replace('\t', ' ')
data = data.replace('&nbsp;', ' ')
data = re.sub(r'>\s+<', '><', data)
data = re.sub(r'([a-zA-Z])"([a-zA-Z])', "\1'\2", data)
@@ -984,7 +963,7 @@ def match(item_url_string, **args):
def match_dbg(data, patron):
import json, urllib2, webbrowser
import json, webbrowser
url = 'https://regex101.com'
headers = {'content-type': 'application/json'}
data = {
@@ -994,8 +973,9 @@ def match_dbg(data, patron):
'delimiter': '"""',
'flavor': 'python'
}
r = urllib2.Request(url + '/api/regex', json.dumps(data, encoding='latin1'), headers=headers)
r = urllib2.urlopen(r).read()
js = json.dumps(data).encode() if PY3 else json.dumps(data, encoding='latin1')
r = Request(url + '/api/regex', js, headers=headers)
r = urlopen(r).read()
permaLink = json.loads(r)['permalinkFragment']
webbrowser.open(url + "/r/" + permaLink)
@@ -1051,7 +1031,7 @@ def download(itemlist, item, typography='', function_level=1, function=''):
from_action=from_action,
contentTitle=contentTitle,
path=item.path,
thumbnail=thumb(thumb='downloads.png'),
thumbnail=thumb('downloads'),
downloadItemlist=downloadItemlist
))
if from_action == 'episodios':
@@ -1068,7 +1048,7 @@ def download(itemlist, item, typography='', function_level=1, function=''):
from_action=from_action,
contentTitle=contentTitle,
download='season',
thumbnail=thumb(thumb='downloads.png'),
thumbnail=thumb('downloads'),
downloadItemlist=downloadItemlist
))
@@ -1079,7 +1059,7 @@ def videolibrary(itemlist, item, typography='', function_level=1, function=''):
# Simply add this function to add video library support
# Function_level is useful if the function is called by another function.
# If the call is direct, leave it blank
log()
info()
if item.contentType == 'movie':
action = 'add_pelicula_to_library'
@@ -1108,7 +1088,6 @@ def videolibrary(itemlist, item, typography='', function_level=1, function=''):
if (function == 'findvideos' and contentType == 'movie') \
or (function == 'episodios' and contentType != 'movie'):
if config.get_videolibrary_support() and len(itemlist) > 0:
from channelselector import get_thumb
itemlist.append(
Item(channel=item.channel,
title=title,
@@ -1122,7 +1101,7 @@ def videolibrary(itemlist, item, typography='', function_level=1, function=''):
from_action=item.action,
extra=extra,
path=item.path,
thumbnail=get_thumb('add_to_videolibrary.png')
thumbnail=thumb('add_to_videolibrary')
))
return itemlist
@@ -1130,7 +1109,7 @@ def videolibrary(itemlist, item, typography='', function_level=1, function=''):
def nextPage(itemlist, item, data='', patron='', function_or_level=1, next_page='', resub=[]):
# Function_level is useful if the function is called by another function.
# If the call is direct, leave it blank
log()
info()
action = inspect.stack()[function_or_level][3] if type(function_or_level) == int else function_or_level
if next_page == '':
next_page = scrapertools.find_single_match(data, patron)
@@ -1140,7 +1119,7 @@ def nextPage(itemlist, item, data='', patron='', function_or_level=1, next_page=
if 'http' not in next_page:
next_page = scrapertools.find_single_match(item.url, 'https?://[a-z0-9.-]+') + (next_page if next_page.startswith('/') else '/' + next_page)
next_page = next_page.replace('&amp;', '&')
log('NEXT= ', next_page)
info('NEXT= ', next_page)
itemlist.append(
Item(channel=item.channel,
action = action,
@@ -1168,7 +1147,9 @@ def pagination(itemlist, item, page, perpage, function_level=1):
def server(item, data='', itemlist=[], headers='', AutoPlay=True, CheckLinks=True, Download=True, patronTag=None, Videolibrary=True):
log()
info()
blacklisted_servers = config.get_setting("black_list", server='servers')
if not blacklisted_servers: blacklisted_servers = []
if not data and not itemlist:
data = httptools.downloadpage(item.url, headers=headers, ignore_response_code=True).data
if data:
@@ -1179,7 +1160,7 @@ def server(item, data='', itemlist=[], headers='', AutoPlay=True, CheckLinks=Tru
def getItem(videoitem):
if not servertools.get_server_parameters(videoitem.server.lower()): # do not exists or it's empty
findS = servertools.get_server_from_url(videoitem.url)
log(findS)
info(findS)
if not findS:
if item.channel == 'community':
findS= (config.get_localized_string(30137), videoitem.url, 'directo')
@@ -1187,7 +1168,7 @@ def server(item, data='', itemlist=[], headers='', AutoPlay=True, CheckLinks=Tru
videoitem.url = unshortenit.unshorten_only(videoitem.url)[0]
findS = servertools.get_server_from_url(videoitem.url)
if not findS:
log(videoitem, 'Non supportato')
info(videoitem, 'Non supportato')
return
videoitem.server = findS[2]
videoitem.title = findS[0]
@@ -1213,7 +1194,7 @@ def server(item, data='', itemlist=[], headers='', AutoPlay=True, CheckLinks=Tru
with futures.ThreadPoolExecutor() as executor:
thL = [executor.submit(getItem, videoitem) for videoitem in itemlist if videoitem.url]
for it in futures.as_completed(thL):
if it.result():
if it.result() and it.result().server.lower() not in blacklisted_servers:
verifiedItemlist.append(it.result())
try:
verifiedItemlist.sort(key=lambda it: int(re.sub(r'\D','',it.quality)))
@@ -1247,39 +1228,19 @@ def filterLang(item, itemlist):
# import channeltools
list_language = channeltools.get_lang(item.channel)
if len(list_language) > 1:
from specials import filtertools
from core import filtertools
itemlist = filtertools.get_links(itemlist, item, list_language)
return itemlist
# def aplay(item, itemlist, list_servers='', list_quality=''):
# if inspect.stack()[1][3] == 'mainlist':
# autoplay.init(item.channel, list_servers, list_quality)
# autoplay.show_option(item.channel, itemlist)
# else:
# autoplay.start(itemlist, item)
def log(*args):
# Function to simplify the log
# Automatically returns File Name and Function Name
string = ''
for arg in args:
string += ' '+str(arg)
frame = inspect.stack()[1]
filename = frame[0].f_code.co_filename
filename = os.path.basename(filename)
logger.info("[" + filename + "] - [" + inspect.stack()[1][3] + "] " + string)
def channel_config(item, itemlist):
from channelselector import get_thumb
itemlist.append(
Item(channel='setting',
action="channel_config",
title=typo(config.get_localized_string(60587), 'color kod bold'),
config=item.channel,
folder=False,
thumbnail=get_thumb('setting_0.png'))
thumbnail=thumb('setting_0'))
)
@@ -1288,6 +1249,7 @@ def extract_wrapped(decorated):
closure = (c.cell_contents for c in decorated.__closure__)
return next((c for c in closure if isinstance(c, FunctionType)), None)
def addQualityTag(item, itemlist, data, patron):
if itemlist:
defQualVideo = {
@@ -1332,10 +1294,8 @@ def addQualityTag(item, itemlist, data, patron):
"RESYNC": "il film è stato lavorato e re sincronizzato con una traccia audio. A volte potresti riscontrare una mancata sincronizzazione tra audio e video.",
}
qualityStr = scrapertools.find_single_match(data, patron).strip().upper()
if PY3:
qualityStr = qualityStr.encode('ascii', 'ignore')
else:
qualityStr = qualityStr.decode('unicode_escape').encode('ascii', 'ignore')
# if PY3: qualityStr = qualityStr.encode('ascii', 'ignore')
if not PY3: qualityStr = qualityStr.decode('unicode_escape').encode('ascii', 'ignore')
if qualityStr:
try:
@@ -1354,14 +1314,14 @@ def addQualityTag(item, itemlist, data, patron):
descr += typo(audio + ': ', 'color kod') + defQualAudio.get(audio, '') + '\n'
except:
descr = ''
itemlist.insert(0,
Item(channel=item.channel,
action="",
title=typo(qualityStr, '[] color kod bold'),
plot=descr,
folder=False))
itemlist.insert(0,Item(channel=item.channel,
action="",
title=typo(qualityStr, '[] color kod bold'),
plot=descr,
folder=False,
thumbnail=thumb('info')))
else:
log('nessun tag qualità trovato')
info('nessun tag qualità trovato')
def get_jwplayer_mediaurl(data, srvName, onlyHttp=False):
video_urls = []
@@ -1378,4 +1338,121 @@ def get_jwplayer_mediaurl(data, srvName, onlyHttp=False):
video_urls.append(['.' + url.split('.')[-1] + ' [' + quality + '] [' + srvName + ']', url if not onlyHttp else url.replace('https://', 'http://')])
video_urls.sort(key=lambda x: x[0].split()[1])
return video_urls
return video_urls
def thumb(item_itemlist_string=None, genre=False, live=False):
from channelselector import get_thumb
if live:
if type(item_itemlist_string) == list:
for item in item_itemlist_string:
item.thumbnail = "https://raw.githubusercontent.com/kodiondemand/media/master/live/" + item.fulltitle.lower().replace(' ','_') + '.png'
else:
item_itemlist_string.thumbnail = "https://raw.githubusercontent.com/kodiondemand/media/master/live/" + item.fulltitle.lower().replace(' ','_') + '.png'
return item_itemlist_string
icon_dict = {'movie':['film', 'movie'],
'tvshow':['serie','tv','episodi','episodio','fiction', 'show'],
'documentary':['documentari','documentario', 'documentary', 'documentaristico'],
'teenager':['ragazzi','teenager', 'teen'],
'learning':['learning', 'school', 'scuola'],
'all':['tutti', 'all'],
'news':['novità', "novita'", 'aggiornamenti', 'nuovi', 'nuove', 'new', 'newest', 'news', 'ultimi', 'notizie'],
'now_playing':['cinema', 'in sala'],
'anime':['anime'],
'genres':['genere', 'generi', 'categorie', 'categoria', 'category'],
'animation': ['animazione', 'cartoni', 'cartoon', 'animation'],
'action':['azione', 'marziali', 'action', 'martial'],
'adventure': ['avventura', 'adventure'],
'biographical':['biografico', 'biographical', 'biografia'],
'comedy':['comico', 'commedia', 'demenziale', 'comedy', 'brillante', 'demential', 'parody'],
'adult':['erotico', 'hentai', 'harem', 'ecchi', 'adult'],
'drama':['drammatico', 'drama', 'dramma'],
'syfy':['fantascienza', 'science fiction', 'syfy', 'sci-fi'],
'fantasy':['fantasy', 'magia', 'magic', 'fantastico'],
'crime':['gangster','poliziesco', 'crime', 'crimine', 'police'],
'grotesque':['grottesco', 'grotesque'],
'war':['guerra', 'war', 'military'],
'children':['bambini', 'kids'],
'horror':['horror', 'orrore'],
'music':['musical', 'musica', 'music', 'musicale'],
'mistery':['mistero', 'giallo', 'mystery'],
'noir':['noir'],
'popular':['popolari','popolare', 'più visti', 'raccomandati', 'raccomandazioni' 'recommendations'],
'thriller':['thriller'],
'top_rated' : ['fortunato', 'votati', 'lucky', 'top'],
'on_the_air' : ['corso', 'onda', 'diretta', 'dirette'],
'western':['western'],
'vos':['sub','sub-ita'],
'romance':['romantico','sentimentale', 'romance', 'soap'],
'family':['famiglia','famiglie', 'family'],
'historical':['storico', 'history', 'storia', 'historical'],
'az':['lettera','lista','alfabetico','a-z', 'alphabetical'],
'year':['anno', 'anni', 'year'],
'update':['replay', 'update'],
'videolibrary':['teche'],
'info':['info','information','informazioni'],
'star':['star', 'personaggi', 'interpreti', 'stars', 'characters', 'performers', 'staff', 'actors', 'attori'],
'winter':['inverno', 'winter'],
'spring':['primavera', 'spring'],
'summer':['estate', 'summer'],
'autumn':['autunno', 'autumn'],
'autoplay':[config.get_localized_string(60071)]
}
suffix_dict = {'_hd':['hd','altadefinizione','alta definizione'],
'_4k':['4K'],
'_az':['lettera','lista','alfabetico','a-z', 'alphabetical'],
'_year':['anno', 'anni', 'year'],
'_genre':['genere', 'generi', 'categorie', 'categoria']}
search = ['cerca', 'search']
search_suffix ={'_movie':['film', 'movie'],
'_tvshow':['serie','tv', 'fiction']}
def autoselect_thumb(item, genre):
info('SPLIT',re.split(r'\.|\{|\}|\[|\]|\(|\)|/| ',item.title.lower()))
if genre == False:
for thumb, titles in icon_dict.items():
if any(word in re.split(r'\.|\{|\}|\[|\]|\(|\)|/| ',item.title.lower()) for word in search):
thumb = 'search'
for suffix, titles in search_suffix.items():
if any(word in re.split(r'\.|\{|\}|\[|\]|\(|\)|/| ',item.title.lower()) for word in titles ):
thumb = thumb + suffix
item.thumbnail = get_thumb(thumb + '.png')
elif any(word in re.split(r'\.|\{|\}|\[|\]|\(|\)| ',item.title.lower()) for word in titles ):
if thumb == 'movie' or thumb == 'tvshow':
for suffix, titles in suffix_dict.items():
if any(word in re.split(r'\.|\{|\}|\[|\]|\(|\)|/| ',item.title.lower()) for word in titles ):
thumb = thumb + suffix
item.thumbnail = get_thumb(thumb + '.png')
else: item.thumbnail = get_thumb(thumb + '.png')
else:
thumb = item.thumbnail
else:
for thumb, titles in icon_dict.items():
if any(word in re.split(r'\.|\{|\}|\[|\]|\(|\)|/| ',item.title.lower()) for word in titles ):
item.thumbnail = get_thumb(thumb + '.png')
else:
thumb = item.thumbnail
item.title = re.sub(r'\s*\{[^\}]+\}','',item.title)
return item
if item_itemlist_string:
if type(item_itemlist_string) == list:
for item in item_itemlist_string:
autoselect_thumb(item, genre)
return item_itemlist_string
elif type(item_itemlist_string) == str:
filename, file_extension = os.path.splitext(item_itemlist_string)
if not file_extension: item_itemlist_string += '.png'
return get_thumb(item_itemlist_string)
else:
return autoselect_thumb(item_itemlist_string, genre)
else:
return get_thumb('next.png')
+4 -1
View File
@@ -950,7 +950,10 @@ class Tmdb(object):
if self.busqueda_tipo == "movie":
resultado = resultado["movie_results"][0]
else:
resultado = resultado["tv_results"][0]
if resultado["tv_results"]:
resultado = resultado["tv_results"][0]
else:
resultado = resultado['tv_episode_results'][0]
self.results = [resultado]
self.total_results = 1
+4 -3
View File
@@ -71,9 +71,8 @@ def token_trakt(item):
else:
import time
dialog_auth = platformtools.dialog_progress(config.get_localized_string(60251),
config.get_localized_string(60252) % item.verify_url,
config.get_localized_string(60253)
% item.user_code,
config.get_localized_string(60252) % item.verify_url + '\n' +
config.get_localized_string(60253) % item.user_code + '\n' +
config.get_localized_string(60254))
# Generalmente cada 5 segundos se intenta comprobar si el usuario ha introducido el código
@@ -199,6 +198,8 @@ def get_trakt_watched(id_type, mediatype, update=False):
def trakt_check(itemlist):
if type(itemlist) != list:
return
def sync(item, id_result):
info = item.infoLabels
try:
+51 -100
View File
@@ -6,13 +6,17 @@
# Used to obtain series data for the video library
# ------------------------------------------------------------
import sys
if sys.version_info[0] >= 3: PY3 = True
else: PY3 = False
from future import standard_library
standard_library.install_aliases()
from future.builtins import object
import urllib.request, urllib.error, urllib.parse
import re
import re, requests
from core import jsontools
from core import scrapertools
@@ -100,12 +104,12 @@ def find_and_set_infoLabels(item):
otvdb_global = Tvdb(tvdb_id=item.infoLabels['tvdb_id'])
if not item.contentSeason:
p_dialog.update(50, config.get_localized_string(60296), config.get_localized_string(60295))
p_dialog.update(50, config.get_localized_string(60296) + '\n' + config.get_localized_string(60295))
results, info_load = otvdb_global.get_list_results()
logger.debug("results: %s" % results)
if not item.contentSeason:
p_dialog.update(100, config.get_localized_string(60296), config.get_localized_string(60297) % len(results))
p_dialog.update(100, config.get_localized_string(60296) + '\n' + config.get_localized_string(60297) % len(results))
p_dialog.close()
if len(results) > 1:
@@ -335,7 +339,7 @@ class Tvdb(object):
self.list_results = []
self.lang = ""
self.search_name = kwargs['search'] = \
re.sub('\[\\\?(B|I|COLOR)\s?[^\]]*\]', '', kwargs.get('search', ''))
re.sub(r'\[\\\?(B|I|COLOR)\s?[^\]]*\]', '', kwargs.get('search', ''))
self.list_episodes = {}
self.episodes = {}
@@ -390,9 +394,11 @@ class Tvdb(object):
url = HOST + "/login"
params = {"apikey": apikey}
if PY3: params = jsontools.dump(params).encode()
else: params = jsontools.dump(params)
try:
req = urllib.request.Request(url, data=jsontools.dump(params), headers=DEFAULT_HEADERS)
req = urllib.request.Request(url, data=params, headers=DEFAULT_HEADERS)
response = urllib.request.urlopen(req)
html = response.read()
response.close()
@@ -743,6 +749,7 @@ class Tvdb(object):
req = urllib.request.Request(url, headers=DEFAULT_HEADERS)
response = urllib.request.urlopen(req)
html = response.read()
logger.info(html)
response.close()
except Exception as ex:
@@ -836,7 +843,7 @@ class Tvdb(object):
except Exception as ex:
# if isinstance(ex, urllib).HTTPError:
logger.debug("code %s " % ex.code)
logger.debug("code %s " % ex)
message = "An exception of type %s occured. Arguments:\n%s" % (type(ex).__name__, repr(ex.args))
logger.error("error: %s" % message)
@@ -1021,102 +1028,46 @@ class Tvdb(object):
if not origen:
origen = self.result
# todo revisar
# if 'credits' in origen.keys():
# dic_origen_credits = origen['credits']
# origen['credits_cast'] = dic_origen_credits.get('cast', [])
# origen['credits_crew'] = dic_origen_credits.get('crew', [])
# del origen['credits']
items = list(origen.items())
for k, v in items:
if not v:
continue
if k == 'overview':
ret_infoLabels['plot'] = v
elif k == 'runtime':
ret_infoLabels['duration'] = int(v) * 60
elif k == 'firstAired':
ret_infoLabels['year'] = int(v[:4])
ret_infoLabels['premiered'] = v.split("-")[2] + "/" + v.split("-")[1] + "/" + v.split("-")[0]
# todo revisar
# elif k == 'original_title' or k == 'original_name':
# ret_infoLabels['originaltitle'] = v
elif k == 'siteRating':
ret_infoLabels['rating'] = float(v)
elif k == 'siteRatingCount':
ret_infoLabels['votes'] = v
elif k == 'status':
# se traduce los estados de una serie
ret_infoLabels['status'] = v
# I am not in favor of putting the chain as a studio but it is how the scraper does it in a generic way
elif k == 'network':
ret_infoLabels['studio'] = v
elif k == 'image_poster':
# obtenemos la primera imagen de la lista
ret_infoLabels['thumbnail'] = HOST_IMAGE + v[0]['fileName']
elif k == 'image_fanart':
# obtenemos la primera imagen de la lista
ret_infoLabels['fanart'] = HOST_IMAGE + v[0]['fileName']
# # no disponemos de la imagen de fondo
# elif k == 'banner':
# ret_infoLabels['fanart'] = HOST_IMAGE + v
elif k == 'id':
ret_infoLabels['tvdb_id'] = v
elif k == 'imdbId':
ret_infoLabels['imdb_id'] = v
# no se muestra
# ret_infoLabels['code'] = v
elif k in "rating":
# we translate the age rating (content rating system)
ret_infoLabels['mpaa'] = v
elif k in "genre":
ret_infoLabels['title'] = origen['seriesName']
ret_infoLabels['tvdb_id'] = origen['id']
thumbs = requests.get(HOST + '/series/' + str(origen['id']) + '/images/query?keyType=poster').json()
if 'data' in thumbs:
ret_infoLabels['thumbnail'] = HOST_IMAGE + thumbs['data'][0]['fileName']
elif 'poster' in origen and origen['poster']:
ret_infoLabels['thumbnail'] = origen['poster']
fanarts = requests.get(HOST + '/series/' + str(origen['id']) + '/images/query?keyType=fanart').json()
if 'data' in fanarts:
ret_infoLabels['fanart'] = HOST_IMAGE + fanarts['data'][0]['fileName']
elif 'fanart' in origen and origen['fanart']:
ret_infoLabels['thumbnail'] = origen['fanart']
if 'overview' in origen and origen['overview']:
ret_infoLabels['plot'] = origen['overview']
if 'duration' in origen and origen['duration']:
ret_infoLabels['duration'] = int(origen['duration']) * 60
if 'firstAired' in origen and origen['firstAired']:
ret_infoLabels['year'] = int(origen['firstAired'][:4])
ret_infoLabels['premiered'] = origen['firstAired'].split("-")[2] + "/" + origen['firstAired'].split("-")[1] + "/" + origen['firstAired'].split("-")[0]
if 'siteRating' in origen and origen['siteRating']:
ret_infoLabels['rating'] = float(origen['siteRating'])
if 'siteRatingCount' in origen and origen['siteRatingCount']:
ret_infoLabels['votes'] = origen['siteRatingCount']
if 'status' in origen and origen['status']:
ret_infoLabels['status'] = origen['status']
if 'network' in origen and origen['network']:
ret_infoLabels['studio'] = origen['network']
if 'imdbId' in origen and origen['rating']:
ret_infoLabels['imdb_id'] = origen['imdbId']
if 'rating' in origen and origen['rating']:
ret_infoLabels['mpaa'] = origen['rating']
if 'genre' in origen and origen['genre']:
for genre in origen['genre']:
genre_list = ""
for index, i in enumerate(v):
if index > 0:
genre_list += ", "
# traducimos los generos
genre_list += i
ret_infoLabels['genre'] = genre_list
elif k == 'seriesName': # or k == 'name' or k == 'title':
# if len(origen.get('aliases', [])) > 0:
# ret_infoLabels['title'] = v + " " + origen.get('aliases', [''])[0]
# else:
# ret_infoLabels['title'] = v
# logger.info("el titulo es %s " % ret_infoLabels['title'])
ret_infoLabels['title'] = v
elif k == 'cast':
dic_aux = dict((name, character) for (name, character) in l_castandrole)
l_castandrole.extend([(p['name'], p['role']) for p in v if p['name'] not in list(dic_aux.keys())])
else:
logger.debug("Attributes not added: %s=%s" % (k, v))
pass
# Sort the lists and convert them to str if necessary
if l_castandrole:
genre_list += genre + ', '
ret_infoLabels['genre'] = genre_list.rstrip(', ')
if 'cast' in origen and origen['cast']:
dic_aux = dict((name, character) for (name, character) in l_castandrole)
l_castandrole.extend([(p['name'], p['role']) for p in origen['cast'] if p['name'] not in list(dic_aux.keys())])
ret_infoLabels['castandrole'] = l_castandrole
logger.debug("ret_infoLabels %s" % ret_infoLabels)
return ret_infoLabels
+10 -10
View File
@@ -205,7 +205,7 @@ def save_movie(item, silent=False):
logger.error(traceback.format_exc())
if filetools.write(json_path, item.tojson()):
if not silent: p_dialog.update(100, config.get_localized_string(60062), item.contentTitle)
if not silent: p_dialog.update(100, item.contentTitle)
item_nfo.library_urls[item.channel] = item.url
if filetools.write(nfo_path, head_nfo + item_nfo.tojson()):
@@ -221,7 +221,7 @@ def save_movie(item, silent=False):
# If we get to this point it is because something has gone wrong
logger.error("Could not save %s in the video library" % item.contentTitle)
if not silent:
p_dialog.update(100, config.get_localized_string(60063), item.contentTitle)
p_dialog.update(100, item.contentTitle)
p_dialog.close()
return 0, 0, -1, path
@@ -254,7 +254,7 @@ def add_renumber_options(item, head_nfo, path):
return ret
def check_renumber_options(item):
from specials.autorenumber import load, write
from platformcode.autorenumber import load, write
for key in item.channel_prefs:
if 'TVSHOW_AUTORENUMBER' in item.channel_prefs[key]:
item.channel = key
@@ -645,10 +645,10 @@ def save_episodes(path, episodelist, serie, silent=False, overwrite=True):
# Silent is to show no progress (for service)
if not silent:
# progress dialog
p_dialog = platformtools.dialog_progress(config.get_localized_string(20000), config.get_localized_string(60064))
p_dialog.update(0, config.get_localized_string(60065))
p_dialog = platformtools.dialog_progress(config.get_localized_string(60064) ,'')
# p_dialog.update(0, config.get_localized_string(60065))
channel_alt = serie.channels # We prepare to add the emergency urls
channel_alt = serie.channel # We prepare to add the emergency urls
emergency_urls_stat = config.get_setting("emergency_urls", channel_alt) # Does the channel want emergency urls?
emergency_urls_succ = False
try: channel = __import__('specials.%s' % channel_alt, fromlist=["specials.%s" % channel_alt])
@@ -673,7 +673,7 @@ def save_episodes(path, episodelist, serie, silent=False, overwrite=True):
json_path = filetools.join(path, ("%s [%s].json" % (season_episode, e.channel)).lower()) # Path of the episode .json
if emergency_urls_stat == 1 and not e.emergency_urls and e.contentType == 'episode': # Do we keep emergency urls?
if not silent:
p_dialog.update(0, 'Caching links and .torren filest...', e.title) # progress dialog
p_dialog.update(0, 'Caching links and .torren filest...\n' + e.title) # progress dialog
if json_path in ficheros: # If there is the .json we get the urls from there
if overwrite: # but only if .json are overwritten
json_epi = Item().fromjson(filetools.read(json_path)) #We read the .json
@@ -690,7 +690,7 @@ def save_episodes(path, episodelist, serie, silent=False, overwrite=True):
emergency_urls_succ = True # ... is a success and we are going to mark the .nfo
elif emergency_urls_stat == 3 and e.contentType == 'episode': # Do we update emergency urls?
if not silent:
p_dialog.update(0, 'Caching links and .torrent files...', e.title) # progress dialog
p_dialog.update(0, 'Caching links and .torrent files...\n' + e.title) # progress dialog
e = emergency_urls(e, channel, json_path, headers=headers) # we generate the urls
if e.emergency_urls: # If we already have urls...
emergency_urls_succ = True # ... is a success and we are going to mark the .nfo
@@ -722,7 +722,7 @@ def save_episodes(path, episodelist, serie, silent=False, overwrite=True):
t = 0
for i, e in enumerate(scraper.sort_episode_list(new_episodelist)):
if not silent:
p_dialog.update(int(math.ceil((i + 1) * t)), config.get_localized_string(60064), e.title)
p_dialog.update(int(math.ceil((i + 1) * t)), e.title)
high_sea = e.contentSeason
high_epi = e.contentEpisodeNumber
@@ -1073,7 +1073,7 @@ def add_tvshow(item, channel=None):
# Get the episode list
itemlist = getattr(channel, item.action)(item)
if itemlist and not scrapertools.find_single_match(itemlist[0].title, r'(\d+x\d+)'):
from specials.autorenumber import select_type, renumber, check
from platformcode.autorenumber import select_type, renumber, check
if not check(item):
action = item.action
select_type(item)