- Aggiunti i canali Mediaset Play e La 7.
- Riscritto Animeunity.
- Le stagioni concluse vengono ora escluse dall'aggiornamento della videoteca.
- Ora è possibile aggiornare gli episodi di Kod dal menu contestuale della Libreria di Kod (se non gestite da Kod verranno cercate)
- Fix Adesso in Onda su ATV
- Fix Vari
This commit is contained in:
marco
2020-07-19 16:05:27 +02:00
parent c93ba1b736
commit 0e1eb946b2
60 changed files with 1736 additions and 794 deletions
+4 -2
View File
@@ -216,12 +216,14 @@ def downloadbest(video_urls, title, continuar=False):
return -2
def downloadfile(url, nombrefichero, headers=None, silent=False, continuar=False, resumir=True):
def downloadfile(url, nombrefichero, headers=None, silent=False, continuar=False, resumir=True, header=''):
logger.info("url= " + url)
logger.info("filename= " + nombrefichero)
if headers is None:
headers = []
if not header:
header = "plugin"
progreso = None
@@ -269,7 +271,7 @@ def downloadfile(url, nombrefichero, headers=None, silent=False, continuar=False
# Create the progress dialog
if not silent:
progreso = platformtools.dialog_progress("plugin", "Downloading...", url, nombrefichero)
progreso = platformtools.dialog_progress(header, "Downloading...", url, nombrefichero)
# If the platform does not return a valid dialog box, it assumes silent mode
if progreso is None:
+21 -9
View File
@@ -6,6 +6,8 @@
from __future__ import division
# from builtins import str
import io
from future.builtins import range
from past.utils import old_div
import sys
@@ -43,6 +45,11 @@ if os.name == "nt":
else:
fs_encoding = "utf8"
# per android è necessario, su kodi 18, usare FileIO
# https://forum.kodi.tv/showthread.php?tid=330124
# per xbox invece, è necessario usare open perchè _io è rotto :(
# https://github.com/jellyfin/jellyfin-kodi/issues/115#issuecomment-538811017
fileIo = platformtools.xbmc.getCondVisibility('system.platform.linux') and platformtools.xbmc.getCondVisibility('system.platform.android')
def validate_path(path):
@@ -142,19 +149,20 @@ def read(path, linea_inicio=0, total_lineas=None, whence=0, silent=False, vfs=Tr
total_lineas = None
if xbmc_vfs and vfs:
if not exists(path): return False
f = xbmcvfs.File(path, "rb")
f = xbmcvfs.File(path, "r")
data = f.read()
if total_lineas == None:
total_lineas = 9999999999
if linea_inicio > 0:
if not isinstance(whence, int):
try:
whence = int(whence)
except:
return False
f.seek(linea_inicio, whence)
logger.debug('POSITION of beginning of reading,, tell(): %s' % f.seek(0, 1))
if total_lineas == None:
total_lineas = 0
data = f.read(total_lineas)
return "".join(data)
data = '\n'.join(data.split('\n')[linea_inicio:total_lineas])
return data
elif path.lower().startswith("smb://"):
f = samba.smb_open(path, "rb")
else:
@@ -179,7 +187,7 @@ def read(path, linea_inicio=0, total_lineas=None, whence=0, silent=False, vfs=Tr
return unicode(b"".join(data))
def write(path, data, mode="wb", silent=False, vfs=True):
def write(path, data, mode="w", silent=False, vfs=True):
"""
Save the data to a file
@param path: file path to save
@@ -233,7 +241,11 @@ def file_open(path, mode="r", silent=False, vfs=True):
elif path.lower().startswith("smb://"):
return samba.smb_open(path, mode)
else:
return open(path, mode)
if fileIo:
return io.FileIO(path, mode)
else:
# return io.open(path, mode, decode='utf-8')
return open(path, mode)
except:
logger.error("ERROR when opening file: %s, %s" % (path, mode))
if not silent:
+13 -12
View File
@@ -56,7 +56,7 @@ HTTPTOOLS_DEFAULT_RANDOM_HEADERS = False
# with open(CF_LIST_PATH, "rb") as CF_File:
# CF_LIST = CF_File.read().splitlines()
FORCE_CLOUDSCRAPER_LIST = []
FORCE_CLOUDSCRAPER_LIST = ['akvideo.stream']
def get_user_agent():
# Returns the global user agent to be used when necessary for the url.
@@ -256,7 +256,7 @@ def downloadpage(url, **opt):
Parameter Type Description
-------------------------------------------------- -------------------------------------------------- ------------
HTTPResponse.sucess: bool True: Request successful | False: Error when making the request
HTTPResponse.success: bool True: Request successful | False: Error when making the request
HTTPResponse.code: int Server response code or error code if an error occurs
HTTPResponse.error: str Description of the error in case of an error
HTTPResponse.headers: dict Dictionary with server response headers
@@ -270,7 +270,7 @@ def downloadpage(url, **opt):
# global CF_LIST
CF = False
if domain in FORCE_CLOUDSCRAPER_LIST:
if domain in FORCE_CLOUDSCRAPER_LIST or opt.get('cf', False):
from lib import cloudscraper
session = cloudscraper.create_scraper()
CF = True
@@ -278,10 +278,10 @@ def downloadpage(url, **opt):
from lib import requests
session = requests.session()
# if domain in CF_LIST or opt.get('CF', False):
if opt.get('CF', False):
url = 'https://web.archive.org/save/' + url
CF = True
# if domain in CF_LIST or opt.get('CF', False):
if opt.get('CF', False):
url = 'https://web.archive.org/save/' + url
CF = True
if config.get_setting('resolver_dns') and not opt.get('use_requests', False):
from specials import resolverdns
@@ -380,9 +380,10 @@ def downloadpage(url, **opt):
req = requests.Response()
if not opt.get('ignore_response_code', False) and not proxy_data.get('stat', ''):
response['data'] = ''
response['sucess'] = False
response['success'] = False
info_dict.append(('Success', 'False'))
response['code'] = str(e)
import traceback
response['code'] = traceback.format_exc()
info_dict.append(('Response code', str(e)))
info_dict.append(('Finished in', time.time() - inicio))
if not opt.get('alfa_s', False):
@@ -393,7 +394,7 @@ def downloadpage(url, **opt):
else:
response['data'] = ''
response['sucess'] = False
response['success'] = False
response['code'] = ''
return type('HTTPResponse', (), response)
@@ -476,10 +477,10 @@ def fill_fields_post(info_dict, req, response, req_headers, inicio):
if response['code'] == 200:
info_dict.append(('Success', 'True'))
response['sucess'] = True
response['success'] = True
else:
info_dict.append(('Success', 'False'))
response['sucess'] = False
response['success'] = False
info_dict.append(('Response data length', len(response['data'])))
+7 -5
View File
@@ -352,7 +352,7 @@ def scrapeBlock(item, args, block, patron, headers, action, pagination, debug, t
quality=quality,
url=scraped["url"],
infoLabels=infolabels,
thumbnail=item.thumbnail if function == 'episodios' or not scraped["thumb"] else scraped["thumb"],
thumbnail=item.thumbnail if not scraped["thumb"] else scraped["thumb"],
args=item.args,
contentSerieName= title if 'movie' not in [contentType] and function != 'episodios' else item.contentSerieName,
contentTitle= title if 'movie' in [contentType] and function == 'peliculas' else item.contentTitle,
@@ -429,6 +429,7 @@ def scrape(func):
typeContentDict = args['typeContentDict'] if 'typeContentDict' in args else {}
debug = args['debug'] if 'debug' in args else False
debugBlock = args['debugBlock'] if 'debugBlock' in args else False
disabletmdb = args['disabletmdb'] if 'disabletmdb' in args else False
if 'pagination' in args and inspect.stack()[1][3] not in ['add_tvshow', 'get_episodes', 'update', 'find_episodes']: pagination = args['pagination'] if args['pagination'] else 20
else: pagination = ''
lang = args['deflang'] if 'deflang' in args else ''
@@ -506,7 +507,7 @@ def scrape(func):
page=pag + 1,
thumbnail=thumb()))
if action != 'play' and function != 'episodios' and 'patronMenu' not in args and item.contentType in ['movie', 'tvshow', 'episode']:
if action != 'play' and function != 'episodios' and 'patronMenu' not in args and item.contentType in ['movie', 'tvshow', 'episode'] and not disabletmdb:
tmdb.set_infoLabels_itemlist(itemlist, seekTmdb=True)
if anime:
@@ -1095,6 +1096,7 @@ def videolibrary(itemlist, item, typography='', function_level=1, function=''):
contentSerieName=contentSerieName,
url=item.url,
action=action,
from_action=item.action,
extra=extra,
path=item.path,
thumbnail=get_thumb('add_to_videolibrary.png')
@@ -1334,9 +1336,9 @@ def addQualityTag(item, itemlist, data, patron):
else:
log('nessun tag qualità trovato')
def get_jwplayer_mediaurl(data, srvName):
def get_jwplayer_mediaurl(data, srvName, onlyHttp=False):
video_urls = []
block = scrapertools.find_single_match(data, r'sources: \[([^\]]+)\]')
block = scrapertools.find_single_match(data, r'sources:\s*\[([^\]]+)\]')
if 'file:' in block:
sources = scrapertools.find_multiple_matches(block, r'file:\s*"([^"]+)"(?:,label:\s*"([^"]+)")?')
elif 'src:' in block:
@@ -1346,7 +1348,7 @@ def get_jwplayer_mediaurl(data, srvName):
for url, quality in sources:
quality = 'auto' if not quality else quality
if url.split('.')[-1] != 'mpd':
video_urls.append(['.' + url.split('.')[-1] + ' [' + quality + '] [' + srvName + ']', url])
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
+95 -24
View File
@@ -435,7 +435,9 @@ def save_tvshow(item, episodelist, silent=False):
logger.debug("NOT FOUND contentSerieName or code")
return 0, 0, -1, path # Salimos sin guardar
contentTypeBackup = item.contentType # Fix errors in some channels
scraper_return = scraper.find_and_set_infoLabels(item)
item.contentType = contentTypeBackup # Fix errors in some channels
# At this point we can have:
# scraper_return = True: An item with infoLabels with the updated information of the series
# scraper_return = False: An item without movie information (it has been canceled in the window)
@@ -574,19 +576,63 @@ def save_episodes(path, episodelist, serie, silent=False, overwrite=True):
# process local episodes
local_episodes_path = ''
local_episodelist = []
update = False
nfo_path = filetools.join(path, "tvshow.nfo")
head_nfo, item_nfo = read_nfo(nfo_path)
if item_nfo.update_last:
local_episodes_path = item_nfo.local_episodes_path
elif config.get_setting("local_episodes", "videolibrary"):
done, local_episodes_path = config_local_episodes_path(path, serie.show)
done, local_episodes_path = config_local_episodes_path(path, serie)
if done < 0:
logger.info("An issue has occurred while configuring local episodes, going out without creating strm")
return 0, 0, done
item_nfo.local_episodes_path = local_episodes_path
filetools.write(nfo_path, head_nfo + item_nfo.tojson())
if local_episodes_path:
process_local_episodes(local_episodes_path, path)
from platformcode.xbmc_videolibrary import check_db, clean
# check if the local episodes are in the Kodi video library
if check_db(local_episodes_path):
local_episodelist += get_local_content(local_episodes_path)
clean_list = []
for f in filetools.listdir(path):
match = scrapertools.find_single_match(f, r'[S]?(\d+)(?:x|_|\.)?[E]?(\d+)')
if match:
ep = '%dx%02d' % (int(match[0]), int(match[1]))
if ep in local_episodelist:
del_file = filetools.join(path, f)
filetools.remove(del_file)
if f.endswith('strm'):
sep = '\\' if '\\' in path else '/'
clean_path = path[:-len(sep)] if path.endswith(sep) else path
clean_path = '%/' + clean_path.split(sep)[-1] + '/' + f
clean_list.append(clean_path)
clean_list.append(clean_path.replace('/','\\'))
if clean_list:
clean(clean_list)
update = True
if item_nfo.local_episodes_list:
difference = [x for x in item_nfo.local_episodes_list if (x not in local_episodelist)]
if len(difference) > 0:
clean_list = []
for f in difference:
sep = '\\' if '\\' in local_episodes_path else '/'
clean_path = local_episodes_path[:-len(sep)] if local_episodes_path.endswith(sep) else local_episodes_path
clean_path = '%/' + clean_path.split(sep)[-1] + '/%' + f.replace('x','%') + '%'
clean_list.append(clean_path)
clean_list.append(clean_path.replace('/','\\'))
clean(clean_list)
update = True
item_nfo.local_episodes_list = sorted(local_episodelist)
filetools.write(nfo_path, head_nfo + item_nfo.tojson())
# the local episodes are not in the Kodi video library
else:
process_local_episodes(local_episodes_path, path)
insertados = 0
sobreescritos = 0
@@ -667,12 +713,13 @@ def save_episodes(path, episodelist, serie, silent=False, overwrite=True):
logger.info("There is no episode list, we go out without creating strm")
return 0, 0, 0
local_episodelist += get_local_content(path)
# fix float because division is done poorly in python 2.x
try:
t = float(100) / len(new_episodelist)
except:
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)
@@ -694,6 +741,10 @@ def save_episodes(path, episodelist, serie, silent=False, overwrite=True):
nfo_path = filetools.join(path, "%s.nfo" % season_episode)
json_path = filetools.join(path, ("%s [%s].json" % (season_episode, e.channel)).lower())
if season_episode in local_episodelist:
logger.info('Skipped: Serie ' + serie.contentSerieName + ' ' + season_episode + ' available as local content')
continue
# check if the episode has been downloaded
if filetools.join(path, "%s [downloads].json" % season_episode) in ficheros:
logger.info('INFO: "%s" episode %s has been downloaded, skipping it' % (serie.contentSerieName, season_episode))
@@ -817,14 +868,17 @@ def save_episodes(path, episodelist, serie, silent=False, overwrite=True):
filetools.write(tvshow_path, head_nfo + tvshow_item.tojson())
except:
logger.error("Error updating tvshow.nfo")
logger.error("Unable to save %s emergency urls in the video library" % tvshow_item.contentSerieName)
logger.error("Unable to save %s emergency urls in the video library" % serie.contentSerieName)
logger.error(traceback.format_exc())
fallidos = -1
else:
# ... if it was correct we update the Kodi video library
if config.is_xbmc() and config.get_setting("videolibrary_kodi") and not silent:
from platformcode import xbmc_videolibrary
xbmc_videolibrary.update()
update = True
if update:
from platformcode import xbmc_videolibrary
xbmc_videolibrary.update()
if fallidos == len(episodelist):
fallidos = -1
@@ -833,23 +887,25 @@ def save_episodes(path, episodelist, serie, silent=False, overwrite=True):
return insertados, sobreescritos, fallidos
def config_local_episodes_path(path, title, silent=False):
logger.info()
local_episodes_path = ''
if not silent:
silent = platformtools.dialog_yesno(config.get_localized_string(30131), config.get_localized_string(80044) % title)
if silent:
if config.is_xbmc() and not config.get_setting("videolibrary_kodi"):
platformtools.dialog_ok(config.get_localized_string(30131), config.get_localized_string(80043))
local_episodes_path = platformtools.dialog_browse(0, config.get_localized_string(80046))
if local_episodes_path == '':
logger.info("User has canceled the dialog")
return -2, local_episodes_path
elif path in local_episodes_path:
platformtools.dialog_ok(config.get_localized_string(30131), config.get_localized_string(80045))
logger.info("Selected folder is the same of the TV show one")
return -2, local_episodes_path
def config_local_episodes_path(path, item, silent=False):
logger.info(item)
from platformcode.xbmc_videolibrary import search_local_path
local_episodes_path=search_local_path(item)
if not local_episodes_path:
title = item.contentSerieName if item.contentSerieName else item.show
if not silent:
silent = platformtools.dialog_yesno(config.get_localized_string(30131), config.get_localized_string(80044) % title)
if silent:
if config.is_xbmc() and not config.get_setting("videolibrary_kodi"):
platformtools.dialog_ok(config.get_localized_string(30131), config.get_localized_string(80043))
local_episodes_path = platformtools.dialog_browse(0, config.get_localized_string(80046))
if local_episodes_path == '':
logger.info("User has canceled the dialog")
return -2, local_episodes_path
elif path in local_episodes_path:
platformtools.dialog_ok(config.get_localized_string(30131), config.get_localized_string(80045))
logger.info("Selected folder is the same of the TV show one")
return -2, local_episodes_path
if local_episodes_path:
# import artwork
@@ -901,6 +957,21 @@ def process_local_episodes(local_episodes_path, path):
filetools.write(nfo_path, head_nfo + item_nfo.tojson())
def get_local_content(path):
logger.info()
local_episodelist = []
for root, folders, files in filetools.walk(path):
for file in files:
season_episode = scrapertools.get_season_and_episode(file)
if season_episode == "" or filetools.exists(filetools.join(path, "%s.strm" % season_episode)):
continue
local_episodelist.append(season_episode)
local_episodelist = sorted(set(local_episodelist))
return local_episodelist
def add_movie(item):
"""
Keep a movie at the movie library. The movie can be a link within a channel or a previously downloaded video.
@@ -969,7 +1040,7 @@ def add_tvshow(item, channel=None):
else:
# This mark is because the item has something else apart in the "extra" attribute
item.action = item.extra if item.extra else item.action
# item.action = item.extra if item.extra else item.action
if isinstance(item.extra, str) and "###" in item.extra:
item.action = item.extra.split("###")[0]
item.extra = item.extra.split("###")[1]
+3 -3
View File
@@ -23,7 +23,7 @@ class ziptools(object):
if not dir.endswith(':') and not filetools.exists(dir):
filetools.mkdir(dir)
zf = zipfile.ZipFile(file)
zf = zipfile.ZipFile(filetools.file_open(file, vfs=False))
if not folder_to_extract:
self._createstructure(file, dir)
num_files = len(zf.namelist())
@@ -93,7 +93,7 @@ class ziptools(object):
filetools.mkdir(curdir)
def _listdirs(self, file):
zf = zipfile.ZipFile(file)
zf = zipfile.ZipFile(filetools.file_open(file, vfs=False))
dirs = []
for name in zf.namelist():
if name.endswith('/'):
@@ -104,7 +104,7 @@ class ziptools(object):
def zip(self, dir, file):
import os
zf = zipfile.ZipFile(file, "w", zipfile.ZIP_DEFLATED)
zf = zipfile.ZipFile(filetools.file_open(file, "w", vfs=False), "w", zipfile.ZIP_DEFLATED)
abs_src = os.path.abspath(dir)
for dirname, subdirs, files in os.walk(dir):
for filename in files: