- Nuova sezione Musica
- Download in Background
- Download dalla Videoteca e supporto file locali
- Backup e cancellazione della Videoteca
- Spostamento della Videoteca
- Migliorata integrazione con libreria di Kodi
- Gestione delle Viste Preferite
- Nuovo layout impostazioni
This commit is contained in:
marco
2020-04-15 22:58:06 +02:00
parent ecafd1b0df
commit 6de0f4fec4
213 changed files with 5294 additions and 2482 deletions

View File

@@ -18,6 +18,8 @@ PLUGIN_NAME = "kod"
__settings__ = xbmcaddon.Addon(id="plugin.video." + PLUGIN_NAME)
__language__ = __settings__.getLocalizedString
__version_fix = None
__dev_mode = None
channels_data = list()
@@ -36,19 +38,25 @@ def get_addon_version(with_fix=True):
def get_addon_version_fix():
if not dev_mode():
try:
sha = open(os.path.join(get_runtime_path(), 'last_commit.txt')).readline()
return sha[:7]
except:
return '??'
else:
return 'DEV'
global __version_fix
ret = __version_fix
if not ret:
if not dev_mode():
try:
sha = open(os.path.join(get_runtime_path(), 'last_commit.txt')).readline()
ret = sha[:7]
except:
ret = '??'
else:
ret = 'DEV'
return ret
def dev_mode():
r = os.path.isdir(get_runtime_path() + '/.git')
return r
global __dev_mode
if not __dev_mode:
__dev_mode = os.path.isdir(get_runtime_path() + '/.git')
return __dev_mode
def get_platform(full_version=False):
@@ -152,6 +160,7 @@ def enable_disable_autorun(is_enabled):
if is_enabled is False:
with open(path, append_write) as file:
file.write("import xbmc\nxbmc.executebuiltin('XBMC.RunAddon(plugin.video.kod)')")
set_setting('autostart', 'On')
else:
file = open(path, "r")
old_content = file.read()
@@ -159,6 +168,7 @@ def enable_disable_autorun(is_enabled):
file.close()
with open(path, "w") as file:
file.write(new_content)
set_setting('autostart', 'Off')
return True
def get_all_settings_addon():
@@ -170,7 +180,7 @@ def get_all_settings_addon():
infile.close()
ret = {}
matches = scrapertools.find_multiple_matches(data, '<setting id="([^"]*)" value="([^"]*)')
matches = scrapertools.find_multiple_matches(data, '<setting id=\"([^\"]+)\"[^>]*>([^<]*)</setting>')
for _id, value in matches:
ret[_id] = get_setting(_id)
@@ -217,19 +227,25 @@ def open_settings():
set_setting('adult_aux_new_password1', '')
set_setting('adult_aux_new_password2', '')
from specials import videolibrary
from platformcode import xbmc_videolibrary
if settings_pre.get('downloadpath', None) != settings_post.get('downloadpath', None):
xbmc_videolibrary.update_sources(settings_post.get('downloadpath', None), settings_pre.get('downloadpath', None))
# si se ha cambiado la ruta de la videoteca llamamos a comprobar directorios para que lo cree y pregunte
# automaticamente si configurar la videoteca
if settings_pre.get("videolibrarypath", None) != settings_post.get("videolibrarypath", None) or \
settings_pre.get("folder_movies", None) != settings_post.get("folder_movies", None) or \
settings_pre.get("folder_tvshows", None) != settings_post.get("folder_tvshows", None):
verify_directories_created()
settings_pre.get("folder_movies", None) != settings_post.get("folder_movies", None) or \
settings_pre.get("folder_tvshows", None) != settings_post.get("folder_tvshows", None):
videolibrary.move_videolibrary(settings_pre.get("videolibrarypath", None), settings_post.get("videolibrarypath", None),
settings_pre.get("folder_movies", None), settings_post.get("folder_movies", None),
settings_pre.get("folder_tvshows", None), settings_post.get("folder_tvshows", None))
else:
# si se ha puesto que se quiere autoconfigurar y se había creado el directorio de la videoteca
if not settings_pre.get("videolibrary_kodi", None) and settings_post.get("videolibrary_kodi", None) \
and settings_post.get("videolibrary_kodi_flag", None) == 1:
from platformcode import xbmc_videolibrary
xbmc_videolibrary.ask_set_content(2, silent=True)
# si se ha puesto que se quiere autoconfigurar y se había creado el directorio de la videoteca
if not settings_pre.get("videolibrary_kodi", None) and settings_post.get("videolibrary_kodi", None):
xbmc_videolibrary.ask_set_content(silent=True)
elif settings_pre.get("videolibrary_kodi", None) and not settings_post.get("videolibrary_kodi", None):
xbmc_videolibrary.clean(get_setting('videolibrarypath'))
def get_setting(name, channel="", server="", default=None):
@@ -378,8 +394,10 @@ def get_localized_string(code):
def get_localized_category(categ):
categories = {'movie': get_localized_string(30122), 'tvshow': get_localized_string(30123),
'anime': get_localized_string(30124), 'documentary': get_localized_string(30125),
'vos': get_localized_string(30136), 'sub-ita': get_localized_string(70566), 'adult': get_localized_string(30126),
'direct': get_localized_string(30137), 'torrent': get_localized_string(70015), 'live': get_localized_string(30138)}
'vos': get_localized_string(30136), 'sub-ita': get_localized_string(70566),
'adult': get_localized_string(30126), 'direct': get_localized_string(30137),
'torrent': get_localized_string(70015), 'live': get_localized_string(30138),
'music': get_localized_string(30139) }
return categories[categ] if categ in categories else categ
@@ -463,8 +481,8 @@ def verify_directories_created():
logger.debug("Creating %s: %s" % (path, saved_path))
filetools.mkdir(saved_path)
config_paths = [["folder_movies", "CINE"],
["folder_tvshows", "SERIES"]]
config_paths = [["folder_movies", "Film"],
["folder_tvshows", "Serie TV"]]
for path, default in config_paths:
saved_path = get_setting(path)
@@ -480,6 +498,10 @@ def verify_directories_created():
# si se crea el directorio
filetools.mkdir(content_path)
from platformcode import xbmc_videolibrary
xbmc_videolibrary.update_sources(get_setting("videolibrarypath"))
xbmc_videolibrary.update_sources(get_setting("downloadpath"))
try:
from core import scrapertools
# Buscamos el archivo addon.xml del skin activo

View File

@@ -28,36 +28,36 @@ def init():
"""
Todo el código añadido al add-on se borra con cada actualización. Esta función permite restaurarlo automáticamente con cada actualización. Esto permite al usuario tener su propio código, bajo su responsabilidad, y restaurarlo al add-on cada vez que se actualiza.
El mecanismo funciona copiando el contenido de la carpeta-arbol "./userdata/addon_data/plugin.video.kod/custom_code/..." sobre
las carpetas de código del add-on. No verifica el contenido, solo vuelca(reemplaza) el contenido de "custom_code".
El usuario almacenará en las subcarpetas de "custom_code" su código actualizado y listo para ser copiado en cualquier momento.
Si no se desea que copie algo, simplemente se borra de "custom_code" y ya no se copiará en la próxima actualización.
Los pasos que sigue esta función, son los siguientes:
1.- La función se llama desde videolibrary_service.py, desde la función inicial:
1.- La función se llama desde service.py, desde la función inicial:
# Copia Custom code a las carpetas de Alfa desde la zona de Userdata
from platformcode import custom_code
custom_code.init()
2.- En el inicio de Kodi, comprueba si existe la carpeta "custom_code" en "./userdata/addon_data/plugin.video.kod/".
Si no existe, la crea y sale sin más, dando al ususario la posibilidad de copiar sobre esa estructura su código,
2.- En el inicio de Kodi, comprueba si existe la carpeta "custom_code" en "./userdata/addon_data/plugin.video.kod/".
Si no existe, la crea y sale sin más, dando al ususario la posibilidad de copiar sobre esa estructura su código,
y que la función la vuelque sobre el add-on en el próximo inicio de Kodi.
3.- En el siguiente inicio de Kodi, comprueba si existe el custom_code.json en la carpeta root del add-on.
Si no existe, lo crea con el número de versión del add-on vacío, para permitir que se copien los archivos en esta pasada.
4.- Verifica que el número de versión del add-on es diferente de el de custom_code.json. Si es la misma versión,
4.- Verifica que el número de versión del add-on es diferente de el de custom_code.json. Si es la misma versión,
se sale porque ya se realizo la copia anteriormente.
Si la versión es distinta, se realiza el volcado de todos los archivos de la carpeta-árbol "custom_code" sobre el add-on.
Si la carpeta de destino no existe, dará un error y se cancelará la copia. Se considera que no tienen sentido nuevas carpetas.
5.- Si la copia ha terminado con éxito, se actualiza el custom_code.json con el número de versión del add-on,
para que en inicios sucesivos de Kodi no se realicen las copias, hasta que el add-on cambie de versión.
En el número de versión del add-on no se considera el número de fix.
Tiempos: Copiando 7 archivos de prueba, el proceso ha tardado una décima de segundo.
"""
@@ -65,47 +65,47 @@ def init():
#Borra el .zip de instalación de Alfa de la carpeta Packages, por si está corrupto, y que así se pueda descargar de nuevo
version = 'plugin.video.kod-%s.zip' % config.get_addon_version(with_fix=False)
filetools.remove(filetools.join(xbmc.translatePath('special://home'), 'addons', 'packages', version), True)
#Verifica si Kodi tiene algún achivo de Base de Datos de Vídeo de versiones anteriores, entonces los borra
verify_Kodi_video_DB()
#LIBTORRENT: se descarga el binario de Libtorrent cada vez que se actualiza Alfa
try:
threading.Thread(target=update_libtorrent).start() # Creamos un Thread independiente, hasta el fin de Kodi
time.sleep(2) # Dejamos terminar la inicialización...
except: # Si hay problemas de threading, nos vamos
logger.error(traceback.format_exc())
#QUASAR: Preguntamos si se hacen modificaciones a Quasar
if not filetools.exists(filetools.join(config.get_data_path(), "quasar.json")) \
and not config.get_setting('addon_quasar_update', default=False):
question_update_external_addon("quasar")
#QUASAR: Hacemos las modificaciones a Quasar, si está permitido, y si está instalado
if config.get_setting('addon_quasar_update', default=False) or \
(filetools.exists(filetools.join(config.get_data_path(), \
"quasar.json")) and not xbmc.getCondVisibility('System.HasAddon("plugin.video.quasar")')):
if not update_external_addon("quasar"):
platformtools.dialog_notification("Actualización Quasar", "Ha fallado. Consulte el log")
# #QUASAR: Preguntamos si se hacen modificaciones a Quasar
# if not filetools.exists(filetools.join(config.get_data_path(), "quasar.json")) \
# and not config.get_setting('addon_quasar_update', default=False):
# question_update_external_addon("quasar")
# #QUASAR: Hacemos las modificaciones a Quasar, si está permitido, y si está instalado
# if config.get_setting('addon_quasar_update', default=False) or \
# (filetools.exists(filetools.join(config.get_data_path(), \
# "quasar.json")) and not xbmc.getCondVisibility('System.HasAddon("plugin.video.quasar")')):
# if not update_external_addon("quasar"):
# platformtools.dialog_notification("Actualización Quasar", "Ha fallado. Consulte el log")
#Existe carpeta "custom_code" ? Si no existe se crea y se sale
custom_code_dir = filetools.join(config.get_data_path(), 'custom_code')
if not filetools.exists(custom_code_dir):
create_folder_structure(custom_code_dir)
return
else:
#Existe "custom_code.json" ? Si no existe se crea
custom_code_json_path = config.get_runtime_path()
custom_code_json = filetools.join(custom_code_json_path, 'custom_code.json')
if not filetools.exists(custom_code_json):
create_json(custom_code_json_path)
#Se verifica si la versión del .json y del add-on son iguales. Si es así se sale. Si no se copia "custom_code" al add-on
verify_copy_folders(custom_code_dir, custom_code_json_path)
except:
logger.error(traceback.format_exc())
def create_folder_structure(custom_code_dir):
logger.info()
@@ -130,18 +130,18 @@ def create_json(custom_code_json_path, json_name=json_data_file_name):
if filetools.exists(json_data_file):
filetools.remove(json_data_file)
result = filetools.write(json_data_file, jsontools.dump({"addon_version": ""}))
return
def verify_copy_folders(custom_code_dir, custom_code_json_path):
logger.info()
#verificamos si es una nueva versión de Alfa instalada o era la existente. Si es la existente, nos vamos sin hacer nada
json_data_file = filetools.join(custom_code_json_path, json_data_file_name)
json_data = jsontools.load(filetools.read(json_data_file))
current_version = config.get_addon_version(with_fix=False)
if not json_data or not 'addon_version' in json_data:
if not json_data or not 'addon_version' in json_data:
create_json(custom_code_json_path)
json_data = jsontools.load(filetools.read(json_data_file))
try:
@@ -149,7 +149,7 @@ def verify_copy_folders(custom_code_dir, custom_code_json_path):
return
except:
logger.error(traceback.format_exc(1))
#Ahora copiamos los archivos desde el área de Userdata, Custom_code, sobre las carpetas del add-on
for root, folders, files in filetools.walk(custom_code_dir):
for file in files:
@@ -157,46 +157,46 @@ def verify_copy_folders(custom_code_dir, custom_code_json_path):
output_file = input_file.replace(custom_code_dir, custom_code_json_path)
if not filetools.copy(input_file, output_file, silent=True):
return
#Guardamaos el json con la versión actual de Alfa, para no volver a hacer la copia hasta la nueva versión
json_data['addon_version'] = current_version
filetools.write(json_data_file, jsontools.dump(json_data))
return
def question_update_external_addon(addon_name):
logger.info(addon_name)
#Verificamos que el addon está instalado
stat = False
if xbmc.getCondVisibility('System.HasAddon("plugin.video.%s")' % addon_name):
#Si es la primera vez que se pregunta por la actualización del addon externo, recogemos la respuesta,
#Si es la primera vez que se pregunta por la actualización del addon externo, recogemos la respuesta,
# guardaos un .json en userdat/alfa para no volver a preguntar otra vez, y se actualiza el setting en Alfa.
stat = platformtools.dialog_yesno('Actualización de %s' % addon_name.capitalize(), '¿Quiere que actualicemos Quasar para que sea compatible con las últimas versiones de Kodi? (recomendado: SÍ)', '', 'Si actualiza Quasar, reinicie Kodi en un par de minutos')
#Con la respuesta actualizamos la variable en Alfa settings.xml. Se puede cambiar en Ajustes de Alfa, Otros
if stat:
config.set_setting('addon_quasar_update', True)
else:
config.set_setting('addon_quasar_update', False)
# if stat:
# config.set_setting('addon_quasar_update', True)
# else:
# config.set_setting('addon_quasar_update', False)
#Creamos un .json en userdata para no volver a preguntar otra vez
create_json(config.get_data_path(), "%s.json" % addon_name)
return stat
def update_external_addon(addon_name):
logger.info(addon_name)
try:
#Verificamos que el addon está instalado
if xbmc.getCondVisibility('System.HasAddon("plugin.video.%s")' % addon_name):
#Path de actualizaciones de Alfa
alfa_addon_updates_mig = filetools.join(config.get_runtime_path(), "lib")
alfa_addon_updates = filetools.join(alfa_addon_updates_mig, addon_name)
#Path de destino en addon externo
__settings__ = xbmcaddon.Addon(id="plugin.video." + addon_name)
if addon_name.lower() in ['quasar', 'elementum']:
@@ -206,7 +206,7 @@ def update_external_addon(addon_name):
else:
addon_path_mig = ''
addon_path = ''
#Hay modificaciones en Alfa? Las copiamos al addon, incuidas las carpetas de migración a PY3
if filetools.exists(alfa_addon_updates) and filetools.exists(addon_path):
for root, folders, files in filetools.walk(alfa_addon_updates_mig):
@@ -222,7 +222,7 @@ def update_external_addon(addon_name):
if not filetools.copy(input_file, output_file, silent=True):
logger.error('Error en la copia de MIGRACIÓN: Input: %s o Output: %s' % (input_file, output_file))
return False
for root, folders, files in filetools.walk(alfa_addon_updates):
for file in files:
input_file = filetools.join(root, file)
@@ -241,13 +241,13 @@ def update_external_addon(addon_name):
return True
except:
logger.error(traceback.format_exc())
return False
def update_libtorrent():
logger.info()
if not config.get_setting("mct_buffer", server="torrent", default=""):
default = config.get_setting("torrent_client", server="torrent", default=0)
config.set_setting("torrent_client", default, server="torrent")
@@ -261,10 +261,10 @@ def update_libtorrent():
config.set_setting("bt_download_path", config.get_setting("downloadpath"), server="torrent")
config.set_setting("mct_download_limit", "", server="torrent")
config.set_setting("magnet2torrent", False, server="torrent")
if not filetools.exists(filetools.join(config.get_runtime_path(), "custom_code.json")) or not \
config.get_setting("unrar_path", server="torrent", default=""):
path = filetools.join(config.get_runtime_path(), 'lib', 'rarfiles')
creationflags = ''
sufix = ''
@@ -293,7 +293,7 @@ def update_libtorrent():
filetools.mkdir(unrar)
unrar = filetools.join(unrar, 'unrar')
filetools.copy(unrar_org, unrar, silent=True)
command = ['chmod', '777', '%s' % unrar]
p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output_cmd, error_cmd = p.communicate()
@@ -322,14 +322,14 @@ def update_libtorrent():
xbmc.log('######## UnRAR ERROR in module %s: %s' % (device, unrar), xbmc.LOGNOTICE)
logger.error(traceback.format_exc(1))
unrar = ''
if unrar: config.set_setting("unrar_path", unrar, server="torrent")
if filetools.exists(filetools.join(config.get_runtime_path(), "custom_code.json")) and \
config.get_setting("libtorrent_path", server="torrent", default="") :
return
try:
from lib.python_libtorrent.python_libtorrent import get_libtorrent
except Exception as e:
@@ -339,18 +339,18 @@ def update_libtorrent():
config.set_setting("libtorrent_path", "", server="torrent")
if not config.get_setting("libtorrent_error", server="torrent", default=''):
config.set_setting("libtorrent_error", str(e), server="torrent")
return
def verify_Kodi_video_DB():
logger.info()
import random
platform = {}
path = ''
db_files = []
try:
path = filetools.join(xbmc.translatePath("special://masterprofile/"), "Database")
if filetools.exists(path):
@@ -365,16 +365,16 @@ def verify_Kodi_video_DB():
randnum = str(random.randrange(1, 999999))
filetools.rename(filetools.join(path, file), 'OLD_' + randnum +'_' + file)
logger.error('BD obsoleta: ' + file)
else:
logger.error('Video_DB: ' + str(platform['video_db']) + ' para versión Kodi ' + str(platform['num_version']) + ' NO EXISTE. Analizar carpeta: ' + str(db_files))
else:
logger.error('Estructura de get_platform(full_version=True) incorrecta')
else:
logger.error('Path a Userdata/Database (' + path + ') no encontrado')
except:
logger.error('Platform: ' + str(platform) + ' / Path: ' + str(path) + ' / Files: ' + str(db_files))
logger.error(traceback.format_exc())
return

View File

@@ -51,10 +51,10 @@ def download_and_play(url, file_name, download_path):
while not cancelled and download_thread.isAlive():
dialog.update(download_thread.get_progress(), config.get_localized_string(60313),
"Velocidad: " + str(int(old_div(download_thread.get_speed(), 1024))) + " KB/s " + str(
download_thread.get_actual_size()) + "MB de " + str(
config.get_localized_string(60314) + str(int(old_div(download_thread.get_speed(), 1024))) + " KB/s " + str(
download_thread.get_actual_size()) + config.get_localized_string(60316) + str(
download_thread.get_total_size()) + "MB",
"Tiempo restante: " + str(downloadtools.sec_to_hms(download_thread.get_remaining_time())))
config.get_localized_string(60202) % (str(downloadtools.sec_to_hms(download_thread.get_remaining_time()))))
xbmc.sleep(1000)
if dialog.iscanceled():
@@ -296,7 +296,7 @@ class DownloadThread(threading.Thread):
logger.info("Detectado fichero force_stop, se interrumpe la descarga")
f.close()
xbmc.executebuiltin((u'XBMC.Notification("Cancelado", "Descarga en segundo plano cancelada", 300)'))
xbmc.executebuiltin("XBMC.Notification(%s,%s,300)" % (config.get_localized_string(60319),config.get_localized_string(60320)))
return

View File

@@ -17,13 +17,7 @@ else:
import os
import sys
import time
from core import channeltools
from core import scrapertools
from core import servertools
from core import videolibrarytools
from core import trakt_tools
from core.item import Item
from platformcode import config, logger
from platformcode import platformtools
@@ -47,14 +41,23 @@ def start():
from specials.checkhost import test_conn
import threading
threading.Thread(target=test_conn, args=(True, not config.get_setting('resolver_dns'), True, [], [], True)).start()
if not config.dev_mode():
from platformcode import updater
updater.showSavedChangelog()
def run(item=None):
logger.info()
if not item:
# Extract item from sys.argv
if sys.argv[2]:
item = Item().fromurl(sys.argv[2])
sp = sys.argv[2].split('&')
url = sp[0]
item = Item().fromurl(url)
if len(sp) > 1:
for e in sp[1:]:
key, val = e.split('=')
item.__setattr__(key, val)
# If no item, this is mainlist
else:
if config.get_setting("start_page"):
@@ -84,7 +87,7 @@ def run(item=None):
item = Item(channel="channelselector", action="getmainlist", viewmode="movie")
if not config.get_setting('show_once'):
from platformcode import xbmc_videolibrary
xbmc_videolibrary.ask_set_content(1, config.get_setting('videolibrary_kodi_force'))
xbmc_videolibrary.ask_set_content(silent=False)
config.set_setting('show_once', True)
logger.info(item.tostring())
@@ -162,6 +165,7 @@ def run(item=None):
else:
# Entry point for a channel is the "mainlist" action, so here we check parental control
if item.action == "mainlist":
from core import channeltools
#updater.checkforupdates() beta version checking for update, still disabled
# Parental control
@@ -207,6 +211,7 @@ def run(item=None):
if item.action == "play":
#define la info para trakt
try:
from core import trakt_tools
trakt_tools.set_trakt_info(item)
except:
pass
@@ -241,6 +246,7 @@ def run(item=None):
# Special action for findvideos, where the plugin looks for known urls
elif item.action == "findvideos":
from core import servertools
# First checks if channel has a "findvideos" function
if hasattr(channel, 'findvideos'):
@@ -263,10 +269,12 @@ def run(item=None):
# Special action for adding a movie to the library
elif item.action == "add_pelicula_to_library":
from core import videolibrarytools
videolibrarytools.add_movie(item)
# Special action for adding a serie to the library
elif item.action == "add_serie_to_library":
from core import videolibrarytools
videolibrarytools.add_tvshow(item, channel)
# Special action for downloading all episodes from a serie
@@ -279,6 +287,7 @@ def run(item=None):
# Special action for searching, first asks for the words then call the "search" function
elif item.action == "search":
logger.info("item.action=%s" % item.action.upper())
from core import channeltools
# last_search = ""
# last_search_active = config.get_setting("last_search", "search")
@@ -315,6 +324,7 @@ def run(item=None):
logger.info("Executing channel '%s' method" % item.action)
itemlist = getattr(channel, item.action)(item)
if config.get_setting('trakt_sync'):
from core import trakt_tools
token_auth = config.get_setting("token_trakt", "trakt")
if not token_auth:
trakt_tools.auth_trakt()
@@ -346,6 +356,8 @@ def run(item=None):
platformtools.dialog_ok(config.get_localized_string(20000), config.get_localized_string(30051) % e.code)
except WebErrorException as e:
import traceback
from core import scrapertools
logger.error(traceback.format_exc())
patron = 'File "' + os.path.join(config.get_runtime_path(), "channels", "").replace("\\", "\\\\") + '([^.]+)\.py"'
@@ -356,6 +368,8 @@ def run(item=None):
config.get_localized_string(60013) %(e))
except:
import traceback
from core import scrapertools
logger.error(traceback.format_exc())
patron = 'File "' + os.path.join(config.get_runtime_path(), "channels", "").replace("\\", "\\\\") + '([^.]+)\.py"'
@@ -467,6 +481,7 @@ def play_from_library(item):
@type item: item
@param item: elemento con información
"""
item.fromLibrary = True
logger.info()
# logger.debug("item: \n" + item.tostring('\n'))
@@ -503,7 +518,7 @@ def play_from_library(item):
item.show_server = True
from specials import videolibrary, autoplay
p_dialog = platformtools.dialog_progress_bg(config.get_localized_string(20000), config.get_localized_string(70004))
p_dialog = platformtools.dialog_progress_bg(config.get_localized_string(20000), config.get_localized_string(60683))
p_dialog.update(0, '')
itemlist = videolibrary.findvideos(item)

View File

@@ -45,8 +45,7 @@ except:
try:
DOWNLOAD_PATH = ''
DOWNLOAD_PATH = xbmc.translatePath(config.get_setting("mct_download_path", \
server="torrent", default=config.get_setting("downloadpath")))
DOWNLOAD_PATH = xbmc.translatePath(config.get_setting("mct_download_path", server="torrent", default=config.get_setting("torrent_downloadpath")))
except:
DOWNLOAD_PATH = config.get_setting("mct_download_path", server="torrent", default=config.get_setting("downloadpath"))
if not config.get_setting("mct_download_path", server="torrent") and DOWNLOAD_PATH:
@@ -573,7 +572,7 @@ def play(url, xlistitem={}, is_view=None, subtitle="", password="", item=None):
ok = xbmcgui.Dialog().yesno(msg_header, config.get_localized_string(30031), config.get_localized_string(30032))
else: ok = True
# -- NO ---------------------------------------------
if not ok:
if ok:
is_view=None
bkg_user = True
dp_cerrado = False
@@ -614,7 +613,7 @@ def play(url, xlistitem={}, is_view=None, subtitle="", password="", item=None):
dp.close()
# Preguntamos si el usuario quiere pasar a backgroung
dialog = xbmcgui.Dialog().yesno(msg_header, config.get_localized_string(30031), config.get_localized_string(30032))
if not dialog:
if dialog:
bkg_user = True
dp_cerrado = False
dp = xbmcgui.DialogProgressBG()

View File

@@ -47,10 +47,17 @@ class XBMCPlayer(xbmc.Player):
xbmc_player = XBMCPlayer()
def makeMessage(line1, line2, line3):
message = line1
if line2:
message += '\n' + line2
if line3:
message += '\n' + line3
return message
def dialog_ok(heading, line1, line2="", line3=""):
dialog = xbmcgui.Dialog()
return dialog.ok(heading, line1, line2, line3)
return dialog.ok(heading, makeMessage(line1, line2, line3))
def dialog_notification(heading, message, icon=0, time=5000, sound=True):
@@ -62,12 +69,19 @@ def dialog_notification(heading, message, icon=0, time=5000, sound=True):
dialog_ok(heading, message)
def dialog_yesno(heading, line1, line2="", line3="", nolabel="No", yeslabel="Si", autoclose=""):
def dialog_yesno(heading, line1, line2="", line3="", nolabel="No", yeslabel="Si", autoclose=0, customlabel=None):
# customlabel only on kodi 19
dialog = xbmcgui.Dialog()
if autoclose:
return dialog.yesno(heading, line1, line2, line3, nolabel, yeslabel, autoclose)
if config.get_platform() == 'kodi-matrix':
if autoclose:
return dialog.yesno(heading, makeMessage(line1, line2, line3), nolabel=nolabel, yeslabel=yeslabel, customlabel=customlabel, autoclose=autoclose)
else:
return dialog.yesno(heading, makeMessage(line1, line2, line3), nolabel=nolabel, yeslabel=yeslabel, customlabel=customlabel)
else:
return dialog.yesno(heading, line1, line2, line3, nolabel, yeslabel)
if autoclose:
return dialog.yesno(heading, makeMessage(line1, line2, line3), nolabel=nolabel, yeslabel=yeslabel, autoclose=autoclose)
else:
return dialog.yesno(heading, makeMessage(line1, line2, line3), nolabel=nolabel, yeslabel=yeslabel)
def dialog_select(heading, _list):
@@ -80,7 +94,7 @@ def dialog_multiselect(heading, _list, autoclose=0, preselect=[], useDetails=Fal
def dialog_progress(heading, line1, line2=" ", line3=" "):
dialog = xbmcgui.DialogProgress()
dialog.create(heading, line1, line2, line3)
dialog.create(heading, makeMessage(line1, line2, line3))
return dialog
@@ -112,6 +126,12 @@ def dialog_textviewer(heading, text): # disponible a partir de kodi 16
return xbmcgui.Dialog().textviewer(heading, text)
def dialog_browse(_type, heading, default=""):
dialog = xbmcgui.Dialog()
d = dialog.browse(_type, heading, 'files')
return d
def itemlist_refresh():
xbmc.executebuiltin("Container.Refresh")
@@ -124,6 +144,138 @@ def itemlist_update(item, replace=False):
def render_items(itemlist, parent_item):
"""
Function used to render itemlist on kodi
"""
logger.info('START render_items')
thumb_type = config.get_setting('video_thumbnail_type')
from specials import shortcuts
from core import httptools
_handle = int(sys.argv[1])
default_fanart = config.get_fanart()
def_context_commands = shortcuts.context()
# for adding extendedinfo to contextual menu, if it's used
has_extendedinfo = xbmc.getCondVisibility('System.HasAddon(script.extendedinfo)')
# for adding superfavourites to contextual menu, if it's used
sf_file_path = xbmc.translatePath("special://home/addons/plugin.program.super.favourites/LaunchSFMenu.py")
check_sf = os.path.exists(sf_file_path)
superfavourites = check_sf and xbmc.getCondVisibility('System.HasAddon("plugin.program.super.favourites")')
# if it's not a list, do nothing
if not isinstance(itemlist, list):
return
# if there's no item, add "no elements" item
if not len(itemlist):
itemlist.append(Item(title=config.get_localized_string(60347), thumbnail=get_thumb('nofolder.png')))
for item in itemlist:
item_url = item.tourl()
if item.category == "":
item.category = parent_item.category
if not item.title:
item.title = ''
# Si no hay action o es findvideos/play, folder=False porque no se va a devolver ningún listado
if item.action in ['play', '']:
item.folder = False
if item.fanart == "":
item.fanart = parent_item.fanart
if item.action == 'play' and thumb_type == 1 and not item.forcethumb:
item.thumbnail = "https://github.com/kodiondemand/media/raw/master/resources/servers/" + item.server.lower() + '.png'
# if cloudflare, cookies are needed to display images taken from site
# before checking domain (time consuming), checking if tmdb failed (so, images scraped from website are used)
if item.action in ['findvideos'] and not item.infoLabels['tmdb_id'] and item.channel in httptools.channelsCF:
item.thumbnail = httptools.get_url_headers(item.thumbnail)
item.fanart = httptools.get_url_headers(item.fanart)
icon_image = "DefaultFolder.png" if item.folder else "DefaultVideo.png"
listitem = xbmcgui.ListItem(item.title)
listitem.setArt({'icon': icon_image, 'thumb': item.thumbnail, 'poster': item.thumbnail,
'fanart': item.fanart if item.fanart else default_fanart})
if config.get_setting("player_mode") == 1 and item.action == "play":
listitem.setProperty('IsPlayable', 'true')
set_infolabels(listitem, item)
# context menu
if parent_item.channel != 'special':
context_commands = def_context_commands + set_context_commands(item, item_url, parent_item, has_extendedinfo=has_extendedinfo,
superfavourites=superfavourites)
else:
context_commands = def_context_commands
listitem.addContextMenuItems(context_commands)
xbmcplugin.addDirectoryItem(_handle, '%s?%s' % (sys.argv[0], item_url), listitem, item.folder)
if parent_item.list_type == '':
breadcrumb = parent_item.category.capitalize()
else:
if 'similar' in parent_item.list_type:
if parent_item.contentTitle != '':
breadcrumb = config.get_localized_string(70693) + parent_item.contentTitle
else:
breadcrumb = config.get_localized_string(70693) + parent_item.contentSerieName
else:
breadcrumb = config.get_localized_string(70693)
xbmcplugin.setPluginCategory(handle=_handle, category=breadcrumb)
set_view_mode(item, parent_item)
xbmcplugin.endOfDirectory(_handle)
logger.info('END render_items')
def set_view_mode(item, parent_item):
def mode(content, Type):
mode = int(config.get_setting('view_mode_%s' % content).split(',')[-1])
if mode > 0:
xbmcplugin.setContent(handle=int(sys.argv[1]), content=Type)
xbmc.executebuiltin('Container.SetViewMode(%s)' % mode)
logger.info('TYPE: ' + Type)
else:
xbmcplugin.setContent(handle=int(sys.argv[1]), content='')
xbmc.executebuiltin('Container.SetViewMode(%s)' % 55)
logger.info('TYPE: ' + 'None')
def reset_view_mode():
for mode in ['addon','channel','movie','tvshow','season','episode','server']:
config.set_setting('skin_name', xbmc.getSkinDir())
config.set_setting('view_mode_%s' % mode, config.get_localized_string(70003) + ' , 0')
if xbmc.getSkinDir() != config.get_setting('skin_name') or not config.get_setting('skin_name'):
reset_view_mode()
xbmcplugin.setContent(handle=int(sys.argv[1]), content='')
xbmc.executebuiltin('Container.SetViewMode(%s)' % 55)
elif (item.contentType in ['movie'] and parent_item.action in ['peliculas']) \
or (item.channel in ['videolibrary'] and parent_item.action in ['list_movies']):
mode('movie', 'movies')
elif (item.contentType in ['tvshow'] and parent_item.action in ['peliculas']) \
or (item.channel in ['videolibrary'] and parent_item.action in ['list_tvshows']):
mode('tvshow', 'tvshow')
elif parent_item.action in ['get_seasons']:
mode('season', 'tvshow')
elif parent_item.action in ['episodios', 'get_episodes']:
mode('episode', 'tvshow')
elif parent_item.action == 'findvideos':
mode('server', 'addons')
elif parent_item.action == 'mainlist':
mode('channel', 'addons')
else:
mode('addon', 'addons')
def render_items_old(itemlist, parent_item):
"""
Función encargada de mostrar el itemlist en kodi, se pasa como parametros el itemlist y el item del que procede
@type itemlist: list
@@ -147,7 +299,7 @@ def render_items(itemlist, parent_item):
# Si no hay ningun item, mostramos un aviso
if not len(itemlist):
itemlist.append(Item(title=config.get_localized_string(60347)))
itemlist.append(Item(title=config.get_localized_string(60347), thumbnail=get_thumb('nofolder.png')))
genre = False
if 'nero' in parent_item.title:
@@ -155,33 +307,41 @@ def render_items(itemlist, parent_item):
anime = False
if 'anime' in channeltools.get_channel_parameters(parent_item.channel)['categories']:
anime = True
try:
force_unify = channeltools.get_channel_parameters(parent_item.channel)['force_unify']
except:
force_unify = False
# try:
# force_unify = channeltools.get_channel_parameters(parent_item.channel)['force_unify']
# except:
force_unify = False
unify_enabled = config.get_setting('unify')
try:
if channeltools.get_channel_parameters(parent_item.channel)['adult']:
unify_enabled = False
except:
pass
unify_enabled = False
has_extendedinfo = xbmc.getCondVisibility('System.HasAddon(script.extendedinfo)')
# Añadir SuperFavourites al menu contextual (1.0.53 o superior necesario)
sf_file_path = xbmc.translatePath("special://home/addons/plugin.program.super.favourites/LaunchSFMenu.py")
check_sf = os.path.exists(sf_file_path)
superfavourites = check_sf and xbmc.getCondVisibility('System.HasAddon("plugin.program.super.favourites")')
# try:
# if channeltools.get_channel_parameters(parent_item.channel)['adult']:
# unify_enabled = False
# except:
# pass
# logger.debug('unify_enabled: %s' % unify_enabled)
# Recorremos el itemlist
for item in itemlist:
# logger.debug(item)
# Si el item no contiene categoria, le ponemos la del item padre
item_url = item.tourl()
if item.category == "":
item.category = parent_item.category
# Si title no existe, lo iniciamos como str, para evitar errones "NoType"
if not item.title:
item.title = ''
# Si no hay action o es findvideos/play, folder=False porque no se va a devolver ningún listado
if item.action in ['play', '']:
item.folder = False
item.folder = False
# Si el item no contiene fanart, le ponemos el del item padre
if item.fanart == "":
@@ -199,9 +359,9 @@ def render_items(itemlist, parent_item):
item.thumbnail = get_thumb("next.png")
elif 'add' in item.action:
if 'pelicula' in item.action:
item.thumbnail = get_thumb("videolibrary_movie.png")
item.thumbnail = get_thumb("add_to_videolibrary.png")
elif 'serie' in item.action:
item.thumbnail = get_thumb("videolibrary_tvshow.png")
item.thumbnail = get_thumb("add_to_videolibrary.png")
if (unify_enabled or force_unify) and parent_item.channel not in ['kodfavourites']:
# Formatear titulo con unify
@@ -257,14 +417,14 @@ def render_items(itemlist, parent_item):
# Añadimos los infoLabels
set_infolabels(listitem, item)
# No arrastrar plot si no es una peli/serie/temporada/episodio
if item.plot and item.contentType not in ['movie', 'tvshow', 'season', 'episode']:
item.__dict__['infoLabels'].pop('plot')
# Montamos el menu contextual
if parent_item.channel != 'special':
context_commands = set_context_commands(item, parent_item)
context_commands = set_context_commands(item, item_url, parent_item, has_extendedinfo=has_extendedinfo, superfavourites=superfavourites)
else:
context_commands = []
# Añadimos el menu contextual
@@ -278,7 +438,7 @@ def render_items(itemlist, parent_item):
if not item.totalItems:
item.totalItems = 0
xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url='%s?%s' % (sys.argv[0], item.tourl()),
xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url='%s?%s' % (sys.argv[0], item_url),
listitem=listitem, isFolder=item.folder,
totalItems=item.totalItems)
@@ -313,11 +473,11 @@ def render_items(itemlist, parent_item):
xbmcplugin.endOfDirectory(handle=int(sys.argv[1]), succeeded=True)
# Fijar la vista
if config.get_setting("forceview"):
viewmode_id = get_viewmode_id(parent_item)
xbmc.executebuiltin("Container.SetViewMode(%s)" % viewmode_id)
if parent_item.mode in ['silent', 'get_cached', 'set_cache', 'finish']:
xbmc.executebuiltin("Container.SetViewMode(500)")
# if config.get_setting("forceview"):
# viewmode_id = get_viewmode_id(parent_item)
# xbmc.executebuiltin("Container.SetViewMode(%s)" % viewmode_id)
# if parent_item.mode in ['silent', 'get_cached', 'set_cache', 'finish']:
# xbmc.executebuiltin("Container.SetViewMode(500)")
logger.info('END render_items')
@@ -397,37 +557,42 @@ def set_infolabels(listitem, item, player=False):
'top250': 'top250', 'tracknumber': 'tracknumber', 'trailer': 'trailer', 'thumbnail': 'None',
'tvdb_id': 'None', 'tvshowtitle': 'tvshowtitle', 'type': 'None', 'userrating': 'userrating',
'url_scraper': 'None', 'votes': 'votes', 'writer': 'writer', 'year': 'year'}
infoLabels_kodi = {}
if item.infoLabels:
if 'mediatype' not in item.infoLabels:
item.infoLabels['mediatype'] = item.contentType
try:
for label_tag, label_value in list(item.infoLabels.items()):
try:
# logger.debug(str(label_tag) + ': ' + str(infoLabels_dict[label_tag]))
if infoLabels_dict[label_tag] != 'None':
infoLabels_kodi.update({infoLabels_dict[label_tag]: item.infoLabels[label_tag]})
except:
continue
infoLabels_kodi = {infoLabels_dict[label_tag]: item.infoLabels[label_tag] for label_tag, label_value in list(item.infoLabels.items()) if infoLabels_dict[label_tag] != 'None'}
listitem.setInfo("video", infoLabels_kodi)
except:
listitem.setInfo("video", item.infoLabels)
logger.error(item.infoLabels)
logger.error(infoLabels_kodi)
if player and not item.contentTitle:
listitem.setInfo("video", {"Title": item.title})
elif not player:
listitem.setInfo("video", {"Title": item.title})
# if item.infoLabels:
# if 'mediatype' not in item.infoLabels:
# item.infoLabels['mediatype'] = item.contentType
#
# try:
# for label_tag, label_value in list(item.infoLabels.items()):
# try:
# # logger.debug(str(label_tag) + ': ' + str(infoLabels_dict[label_tag]))
# if infoLabels_dict[label_tag] != 'None':
# infoLabels_kodi.update({infoLabels_dict[label_tag]: item.infoLabels[label_tag]})
# except:
# continue
#
# listitem.setInfo("video", infoLabels_kodi)
#
# except:
# listitem.setInfo("video", item.infoLabels)
# logger.error(item.infoLabels)
# logger.error(infoLabels_kodi)
#
# if player and not item.contentTitle:
# listitem.setInfo("video", {"Title": item.title})
#
# elif not player:
# listitem.setInfo("video", {"Title": item.title})
def set_context_commands(item, parent_item):
def set_context_commands(item, item_url, parent_item, **kwargs):
"""
Función para generar los menus contextuales.
1. Partiendo de los datos de item.context
@@ -458,7 +623,7 @@ def set_context_commands(item, parent_item):
@type parent_item: item
"""
context_commands = []
num_version_xbmc = config.get_platform(True)['num_version']
# num_version_xbmc = config.get_platform(True)['num_version']
# Creamos un list con las diferentes opciones incluidas en item.context
if isinstance(item.context, str):
@@ -468,43 +633,6 @@ def set_context_commands(item, parent_item):
else:
context = []
# if config.get_setting("faster_item_serialization"):
# # logger.info("Reducing serialization!")
# itemBK = item
# item = Item()
# item.action = itemBK.action
# item.channel = itemBK.channel
# infoLabels = {}
# if itemBK.infoLabels["year"]: infoLabels["year"] = itemBK.infoLabels["year"]
# if itemBK.infoLabels["imdb_id"]: infoLabels["imdb_id"] = itemBK.infoLabels["imdb_id"]
# if itemBK.infoLabels["tmdb_id"]: infoLabels["tmdb_id"] = itemBK.infoLabels["tmdb_id"]
# if itemBK.infoLabels["tvdb_id"]: infoLabels["tvdb_id"] = itemBK.infoLabels["tvdb_id"]
# if itemBK.infoLabels["noscrap_id"]: infoLabels["noscrap_id"] = itemBK.infoLabels["noscrap_id"]
# if len(infoLabels) > 0: item.infoLabels = infoLabels
# if itemBK.thumbnail: item.thumbnail = itemBK.thumbnail
# if itemBK.extra: item.extra = itemBK.extra
# if itemBK.contentEpisodeNumber: item.contentEpisodeNumber = itemBK.contentEpisodeNumber
# if itemBK.contentEpisodeTitle: item.contentEpisodeTitle = itemBK.contentEpisodeTitle
# if itemBK.contentPlot: item.contentPlot = itemBK.contentPlot
# if itemBK.contentQuality: item.contentQuality = itemBK.contentQuality
# if itemBK.contentSeason: item.contentSeason = itemBK.contentSeason
# if itemBK.contentSerieName: item.contentSerieName = itemBK.contentSerieName
# if itemBK.contentThumbnail: item.contentThumbnail = itemBK.contentThumbnail
# if itemBK.contentTitle: item.contentTitle = itemBK.contentTitle
# if itemBK.contentType: item.contentType = itemBK.contentType
# if itemBK.duration: item.duration = itemBK.duration
# if itemBK.plot: item.plot = itemBK.plot
# if itemBK.quality: item.quality = itemBK.quality
# if itemBK.show: item.show = itemBK.show
# if itemBK.title: item.title = itemBK.title
# if itemBK.viewcontent: item.viewcontent = itemBK.viewcontent
# itemJson = item.tojson()
# logger.info("Elemento: {0} bytes".format(len(itemJson)))
# logger.info(itemJson)
# logger.info("--------------------------------------------------------------")
# Opciones segun item.context
for command in context:
# Predefinidos
@@ -535,15 +663,14 @@ def set_context_commands(item, parent_item):
# No añadir más opciones predefinidas si se está dentro de Alfavoritos
if parent_item.channel == 'kodfavorites':
return context_commands
# Opciones segun criterios, solo si el item no es un tag (etiqueta), ni es "Añadir a la videoteca", etc...
# Opciones segun criterios, solo si el item no es un tag (etiqueta), ni es "Añadir a la videoteca", etc...
if item.action and item.action not in ["add_pelicula_to_library", "add_serie_to_library", "buscartrailer", "actualizar_titulos"]:
# Mostrar informacion: si el item tiene plot suponemos q es una serie, temporada, capitulo o pelicula
if item.infoLabels['plot'] and (num_version_xbmc < 17.0 or item.contentType == 'season'):
context_commands.append((config.get_localized_string(60348), "XBMC.Action(Info)"))
# if item.infoLabels['plot'] and (num_version_xbmc < 17.0 or item.contentType == 'season'):
# context_commands.append((config.get_localized_string(60348), "XBMC.Action(Info)"))
# ExtendedInfo: Si está instalado el addon y se cumplen una serie de condiciones
if xbmc.getCondVisibility('System.HasAddon(script.extendedinfo)') \
if kwargs.get('has_extendedinfo') \
and config.get_setting("extended_info") == True:
if item.contentType == "episode" and item.contentEpisodeNumber and item.contentSeason \
and (item.infoLabels['tmdb_id'] or item.contentSerieName):
@@ -575,43 +702,39 @@ def set_context_commands(item, parent_item):
context_commands.append(("ExtendedInfo",
"XBMC.RunScript(script.extendedinfo,info=extendedinfo,%s)" % param))
# InfoPlus
# InfoPlus
if config.get_setting("infoplus"):
#if item.infoLabels['tmdb_id'] or item.infoLabels['imdb_id'] or item.infoLabels['tvdb_id'] or \
# (item.contentTitle and item.infoLabels["year"]) or item.contentSerieName:
if item.infoLabels['tmdb_id'] or item.infoLabels['imdb_id'] or item.infoLabels['tvdb_id']:
context_commands.append(("InfoPlus", "XBMC.RunPlugin(%s?%s)" % (sys.argv[0], item.clone(
channel="infoplus", action="start", from_channel=item.channel).tourl())))
context_commands.append(("InfoPlus", "XBMC.RunPlugin(%s?%s&%s)" % (sys.argv[0], item_url,
'channel=infoplus&action=start&from_channel=' + item.channel)))
# Ir al Menu Principal (channel.mainlist)
if parent_item.channel not in ["news", "channelselector"] and item.action != "mainlist" \
if parent_item.channel not in ["news", "channelselector", "downloads"] and item.action != "mainlist" \
and parent_item.action != "mainlist":
context_commands.insert(0, (config.get_localized_string(60349), "XBMC.Container.Refresh (%s?%s)" %
(sys.argv[0], Item(channel=item.channel, action="mainlist").tourl())))
(sys.argv[0], Item(channel=item.channel, action="mainlist").tourl())))
context_commands.insert(1, (config.get_localized_string(70739),
"XBMC.Container.Update (%s?%s)" % (sys.argv[0], Item(action="open_browser",
url=item.url).tourl())))
# Añadir a Favoritos
if num_version_xbmc < 17.0 and \
((item.channel not in ["favorites", "videolibrary", "help", ""]
or item.action in ["update_videolibrary"]) and parent_item.channel != "favorites"):
context_commands.append((config.get_localized_string(30155), "XBMC.RunPlugin(%s?%s)" %
(sys.argv[0], item.clone(channel="favorites", action="addFavourite",
from_channel=item.channel,
from_action=item.action).tourl())))
# if num_version_xbmc < 17.0 and \
# ((item.channel not in ["favorites", "videolibrary", "help", ""]
# or item.action in ["update_videolibrary"]) and parent_item.channel != "favorites"):
# context_commands.append((config.get_localized_string(30155), "XBMC.RunPlugin(%s?%s&%s)" %
# (sys.argv[0], item_url, 'channel=favorites&action=addFavourite&from_channel=' + item.channel + '&from_action=' + item.action)))
# Añadir a Alfavoritos (Mis enlaces)
if item.channel not in ["favorites", "videolibrary", "help", ""] and parent_item.channel != "favorites":
context_commands.append(
(config.get_localized_string(70557), "XBMC.RunPlugin(%s?%s)" %
(sys.argv[0], item.clone(channel="kodfavourites", action="addFavourite",
from_channel=item.channel,
from_action=item.action).tourl())))
# Buscar en otros canales
if item.contentType in ['movie', 'tvshow'] and item.channel != 'search' and item.action not in ['play']:
(config.get_localized_string(70557), "XBMC.RunPlugin(%s?%s&%s)" %
(sys.argv[0], item_url, urllib.urlencode({'channel': "kodfavourites", 'action': "addFavourite",
'from_channel': item.channel,
'from_action': item.action}))))
# Buscar en otros canales
if item.contentType in ['movie', 'tvshow'] and item.channel != 'search' and item.action not in ['play'] and parent_item.action != 'mainlist':
# Buscar en otros canales
if item.contentSerieName != '':
@@ -625,20 +748,17 @@ def set_context_commands(item, parent_item):
mediatype = item.contentType
context_commands.append((config.get_localized_string(60350),
"XBMC.Container.Update (%s?%s)" % (sys.argv[0],
item.clone(channel='search',
action="from_context",
from_channel=item.channel,
contextual=True,
text=item.wanted).tourl())))
"XBMC.Container.Update (%s?%s&%s)" % (sys.argv[0],
item_url, urllib.urlencode({'channel': 'search',
'action': "from_context",
'from_channel': item.channel,
'contextual': True,
'text': item.wanted}))))
context_commands.append(
(config.get_localized_string(70561), "XBMC.Container.Update (%s?%s)" % (
sys.argv[0], item.clone(channel='search', action='from_context', search_type='list', page='1',
list_type='%s/%s/similar' % (
mediatype, item.infoLabels['tmdb_id'])).tourl())))
# Definir como Pagina de inicio
(config.get_localized_string(70561), "XBMC.Container.Update (%s?%s&%s)" % (
sys.argv[0], item_url, 'channel=search&action=from_context&search_type=list&page=1&list_type=%s/%s/similar' % (mediatype, item.infoLabels['tmdb_id']))))
# Definir como Pagina de inicio
if config.get_setting('start_page'):
if item.action not in ['episodios', 'seasons', 'findvideos', 'play']:
context_commands.insert(0, (config.get_localized_string(60351),
@@ -651,46 +771,34 @@ def set_context_commands(item, parent_item):
or (item.channel != "videolibrary" and config.get_localized_string(70585) in str(item.context) and config.get_localized_string(70714) in str(item.context)):
# Añadir Serie a la videoteca
if item.action in ["episodios", "get_episodios", "get_seasons"] and item.contentSerieName:
context_commands.append((config.get_localized_string(60352), "XBMC.RunPlugin(%s?%s)" %
(sys.argv[0], item.clone(action="add_serie_to_library",
from_action=item.action).tourl())))
context_commands.append((config.get_localized_string(60352), "XBMC.RunPlugin(%s?%s&%s)" %
(sys.argv[0], item_url, 'action=add_serie_to_library&from_action=' + item.action)))
# Añadir Pelicula a videoteca
elif item.action in ["detail", "findvideos"] and item.contentType == 'movie' and item.contentTitle:
context_commands.append((config.get_localized_string(60353), "XBMC.RunPlugin(%s?%s)" %
(sys.argv[0], item.clone(action="add_pelicula_to_library",
from_action=item.action).tourl())))
if item.channel not in ["downloads", "videolibrary"] and item.server != 'torrent':
context_commands.append((config.get_localized_string(60353), "XBMC.RunPlugin(%s?%s&%s)" %
(sys.argv[0], item_url, 'action=add_pelicula_to_library&from_action=' + item.action)))
if item.channel not in ["downloads"] and item.server != 'torrent' and parent_item.action != 'mainlist' and config.get_setting('downloadenabled'):
# Descargar pelicula
if item.contentType == "movie":
context_commands.append((config.get_localized_string(60354), "XBMC.RunPlugin(%s?%s)" %
(sys.argv[0], item.clone(channel="downloads", action="save_download",
from_channel=item.channel, from_action=item.action)
.tourl())))
context_commands.append((config.get_localized_string(60354), "XBMC.RunPlugin(%s?%s&%s)" %
(sys.argv[0], item_url, 'channel=downloads&action=save_download&from_channel=' + item.channel + '&from_action=' + item.action)))
elif item.contentSerieName:
# Descargar serie
if item.contentType == "tvshow":
context_commands.append((config.get_localized_string(60355), "XBMC.RunPlugin(%s?%s)" %
(sys.argv[0], item.clone(channel="downloads", action="save_download",
from_channel=item.channel,
from_action=item.action).tourl())))
context_commands.append((config.get_localized_string(60357), "XBMC.RunPlugin(%s?%s)" %
(sys.argv[0], item.clone(channel="downloads", action="save_download", download="seson",
from_channel=item.channel,
from_action=item.action).tourl())))
context_commands.append((config.get_localized_string(60355), "XBMC.RunPlugin(%s?%s&%s)" %
(sys.argv[0], item_url, 'channel=downloads&action=save_download&from_channel=' + item.channel + '&from_action=' + item.action)))
context_commands.append((config.get_localized_string(60357), "XBMC.RunPlugin(%s?%s&%s)" %
(sys.argv[0], item_url, 'channel=downloads&action=save_download&download=season&from_channel=' + item.channel + '&from_action=' + item.action)))
# Descargar episodio
elif item.contentType == "episode":
context_commands.append((config.get_localized_string(60356), "XBMC.RunPlugin(%s?%s)" %
(sys.argv[0], item.clone(channel="downloads", action="save_download",
from_channel=item.channel,
from_action=item.action).tourl())))
context_commands.append((config.get_localized_string(60356), "XBMC.RunPlugin(%s?%s&%s)" %
(sys.argv[0], item_url, 'channel=downloads&action=save_download&from_channel=' + item.channel + '&from_action=' + item.action)))
# Descargar temporada
elif item.contentType == "season":
context_commands.append((config.get_localized_string(60357), "XBMC.RunPlugin(%s?%s)" %
(sys.argv[0], item.clone(channel="downloads", action="save_download",
from_channel=item.channel,
from_action=item.action).tourl())))
context_commands.append((config.get_localized_string(60357), "XBMC.RunPlugin(%s?%s&%s)" %
(sys.argv[0], item_url, 'channel=downloads&action=save_download&download=season&from_channel=' + item.channel + '&from_action=' + item.action)))
# # Abrir configuración
# if parent_item.channel not in ["setting", "news", "search"] and item.action == "play":
@@ -698,20 +806,17 @@ def set_context_commands(item, parent_item):
# (sys.argv[0], Item(channel="setting", action="mainlist").tourl())))
# Buscar Trailer
if item.action == "findvideos" or "buscar_trailer" in context:
if item.action in ["findvideos", 'episodios', 'check'] or "buscar_trailer" in context:
context_commands.append(
(config.get_localized_string(60359), "XBMC.RunPlugin(%s?%s)" % (sys.argv[0], item.clone(
channel="trailertools", action="buscartrailer", contextual=True).tourl())))
(config.get_localized_string(60359), "XBMC.RunPlugin(%s?%s)" % (sys.argv[0], urllib.urlencode({
'channel': "trailertools", 'action': "buscartrailer", 'search_title': item.fulltitle if item.fulltitle else item.contentTitle, 'contextual': True}))))
# Añadir SuperFavourites al menu contextual (1.0.53 o superior necesario)
sf_file_path = xbmc.translatePath("special://home/addons/plugin.program.super.favourites/LaunchSFMenu.py")
check_sf = os.path.exists(sf_file_path)
if check_sf and xbmc.getCondVisibility('System.HasAddon("plugin.program.super.favourites")'):
context_commands.append((config.get_localized_string(60361),
if kwargs.get('superfavourites'):
context_commands.append((config.get_localized_string(60361),
"XBMC.RunScript(special://home/addons/plugin.program.super.favourites/LaunchSFMenu.py)"))
# context_commands = sorted(context_commands, key=lambda comand: comand[0])
# Menu Rapido
# context_commands.insert(0, (config.get_localized_string(60360),
# "XBMC.Container.Update (%s?%s)" % (sys.argv[0], Item(channel='side_menu',
@@ -993,7 +1098,7 @@ def get_dialogo_opciones(item, default_action, strm, autoplay):
# Si puedes ver el vídeo, presenta las opciones
if puedes:
for video_url in video_urls:
opciones.append(config.get_localized_string(30151) + " " + video_url[0])
opciones.append(config.get_localized_string(60221) + " " + video_url[0])
if item.server == "local":
opciones.append(config.get_localized_string(30164))
@@ -1071,14 +1176,7 @@ def set_opcion(item, seleccion, opciones, video_urls):
# "Descargar"
elif opciones[seleccion] == config.get_localized_string(30153):
from specials import downloads
import xbmcaddon
import xbmcgui
__addon__ = xbmcaddon.Addon()
__addonname__ = __addon__.getAddonInfo('name')
line1 = config.get_localized_string(70690)
line2 = config.get_localized_string(70691)
line3 = config.get_localized_string(70692)
xbmcgui.Dialog().ok(__addonname__, line1, line2, line3)
downloads.show_disclaimer()
if item.contentType == "list" or item.contentType == "tvshow":
item.contentType = "video"
@@ -1169,7 +1267,7 @@ def set_player(item, xlistitem, mediaurl, view, strm):
logger.info("player_mode=%s" % config.get_setting("player_mode"))
logger.info("mediaurl=" + mediaurl)
if config.get_setting("player_mode") == 3 or "megacrypter.com" in mediaurl:
from . import download_and_play
from platformcode import download_and_play
download_and_play.download_and_play(mediaurl, "download_and_play.tmp", config.get_setting("downloadpath"))
return
@@ -1218,8 +1316,7 @@ def torrent_client_installed(show_tuple=False):
# Plugins externos se encuentra en servers/torrent.json nodo clients
from core import filetools
from core import jsontools
torrent_clients = jsontools.get_node_from_file("torrent.json", "clients", filetools.join(config.get_runtime_path(),
"servers"))
torrent_clients = jsontools.get_node_from_file("torrent.json", "clients", filetools.join(config.get_runtime_path(),"servers"))
torrent_options = []
for client in torrent_clients:
if xbmc.getCondVisibility('System.HasAddon("%s")' % client["id"]):
@@ -1240,6 +1337,16 @@ def play_torrent(item, xlistitem, mediaurl):
from lib import generictools
from servers import torrent
# Si Libtorrent ha dado error de inicialización, no se pueden usar los clientes internos
UNRAR = config.get_setting("unrar_path", server="torrent", default="")
LIBTORRENT = config.get_setting("libtorrent_path", server="torrent", default='')
size_rar = 2
rar_files = []
if item.password:
size_rar = 3
# Opciones disponibles para Reproducir torrents
torrent_options = list()
torrent_options.append([config.get_localized_string(30033)])
@@ -1249,6 +1356,12 @@ def play_torrent(item, xlistitem, mediaurl):
torrent_client = config.get_setting("torrent_client", server="torrent")
# Si es Libtorrent y no está soportado, se ofrecen alternativas, si las hay...
if not LIBTORRENT and len(torrent_options) < 3:
from specials import quasar_download
if dialog_yesno(config.get_localized_string(70784), config.get_localized_string(70782)):
quasar_download.download()
if torrent_client and torrent_client - 1 <= len(torrent_options):
if torrent_client == 0:
seleccion = dialog_select(config.get_localized_string(70193), [opcion[0] for opcion in torrent_options])
@@ -1260,15 +1373,6 @@ def play_torrent(item, xlistitem, mediaurl):
else:
seleccion = 0
# Si Libtorrent ha dado error de inicialización, no se pueden usar los clientes internos
UNRAR = config.get_setting("unrar_path", server="torrent", default="")
LIBTORRENT = config.get_setting("libtorrent_path", server="torrent", default='')
size_rar = 2
rar_files = []
if item.password:
size_rar = 3
# Si es Libtorrent y no está soportado, se ofrecen alternativas, si las hay...
if seleccion < 2 and not LIBTORRENT:
dialog_ok(config.get_localized_string(30033), config.get_localized_string(70774), \
config.get_localized_string(70775) % config.get_setting("libtorrent_error", server="torrent", default=''), \
@@ -1362,38 +1466,24 @@ def play_torrent(item, xlistitem, mediaurl):
item.url = item.torrent_alt
# Si es un archivo .torrent local, actualizamos el path relativo a path absoluto
if (item.url.startswith("\\") or item.url.startswith("/")) and not \
url_stat and videolibrary_path: # .torrent alternativo local
if (item.url.startswith("\\") or item.url.startswith("/")) and not url_stat and videolibrary_path: # .torrent alternativo local
movies = config.get_setting("folder_movies")
series = config.get_setting("folder_tvshows")
if item.contentType == 'movie':
folder = movies # películas
else:
folder = series # o series
item.url = filetools.join(config.get_videolibrary_path(), folder,
item.url) # dirección del .torrent local en la Videoteca
if filetools.copy(item.url, torrents_path,
silent=True): # se copia a la carpeta generíca para evitar problemas de encode
item.url = filetools.join(config.get_videolibrary_path(), folder, item.url) # dirección del .torrent local en la Videoteca
if filetools.copy(item.url, torrents_path, silent=True): # se copia a la carpeta generíca para evitar problemas de encode
item.url = torrents_path
if "torrentin" in torrent_options[seleccion][0]: # Si es Torrentin, hay que añadir un prefijo
item.url = 'file://' + item.url
size, rar_files = generictools.get_torrent_size('', file_list=True, local_torr=torrents_path,
short_pad=True)
size, rar_files = generictools.get_torrent_size('', file_list=True, local_torr=torrents_path,short_pad=True)
mediaurl = item.url
if seleccion >= 0:
# Si tiene .torrent válido o magnet, lo registramos
if size or item.url.startswith('magnet'):
try:
import threading
if not PY3: from lib import alfaresolver
else: from lib import alfaresolver_py3 as alfaresolver
threading.Thread(target=alfaresolver.frequency_count, args=(item, )).start()
except:
logger.error(traceback.format_exc(1))
# Reproductor propio BT (libtorrent)
if seleccion == 0:
torrent.bt_client(mediaurl, xlistitem, rar_files, subtitle=item.subtitle, password=password, item=item)
@@ -1407,8 +1497,7 @@ def play_torrent(item, xlistitem, mediaurl):
else:
mediaurl = urllib.quote_plus(item.url)
# Llamada con más parámetros para completar el título
if ("quasar" in torrent_options[seleccion][1] or "elementum" in torrent_options[seleccion][1]) \
and item.infoLabels['tmdb_id']:
if ("quasar" in torrent_options[seleccion][1] or "elementum" in torrent_options[seleccion][1]) and item.infoLabels['tmdb_id']:
if item.contentType == 'episode' and "elementum" not in torrent_options[seleccion][1]:
mediaurl += "&episode=%s&library=&season=%s&show=%s&tmdb=%s&type=episode" % (
item.infoLabels['episode'], item.infoLabels['season'], item.infoLabels['tmdb_id'],
@@ -1422,14 +1511,10 @@ def play_torrent(item, xlistitem, mediaurl):
# y después lo extraemos, incluso con RAR's anidados y con contraseña
torr_client = torrent_options[seleccion][0].replace('Plugin externo: ', '')
if 'RAR-' in size and torr_client in ['quasar', 'elementum'] and UNRAR:
rar_file, save_path_videos, folder_torr = torrent.wait_for_download(rar_files,
torr_client) # Esperamos mientras se descarga el RAR
rar_file, save_path_videos, folder_torr = torrent.wait_for_download(item, mediaurl, rar_files, torr_client) # Esperamos mientras se descarga el RAR
if rar_file and save_path_videos: # Si se ha descargado el RAR...
dp = dialog_progress_bg('KoD %s' % torr_client)
video_file, rar, video_path, erase_file_path = torrent.extract_files(rar_file, \
save_path_videos, password, dp,
item,
torr_client) # ... extraemos el vídeo del RAR
video_file, rar, video_path, erase_file_path = torrent.extract_files(rar_file, save_path_videos, password, dp, item, torr_client) # ... extraemos el vídeo del RAR
dp.close()
# Reproducimos el vídeo extraido, si no hay nada en reproducción
@@ -1457,8 +1542,7 @@ def play_torrent(item, xlistitem, mediaurl):
try:
torr_data, deamon_url, index = torrent.get_tclient_data(folder_torr, torr_client)
if torr_data and deamon_url:
data = httptools.downloadpage('%sdelete/%s' % (deamon_url, index), timeout=5,
alfa_s=True).data
data = httptools.downloadpage('%sdelete/%s' % (deamon_url, index), timeout=5, alfa_s=True).data
time.sleep(1)
if filetools.isdir(erase_file_path):
filetools.rmdirtree(erase_file_path)
@@ -1466,8 +1550,7 @@ def play_torrent(item, xlistitem, mediaurl):
filetools.remove(erase_file_path)
except:
logger.error(traceback.format_exc(1))
elementum_dl = config.get_setting("elementum_dl", server="torrent",
default='') # Si salvamos el cambio de Elementum
elementum_dl = config.get_setting("elementum_dl", server="torrent", default='') # Si salvamos el cambio de Elementum
if elementum_dl:
config.set_setting("elementum_dl", "", server="torrent") # lo reseteamos en Alfa
xbmcaddon.Addon(id="plugin.video.%s" % torrent_options[seleccion][0].replace('Plugin externo: ', '')) \

View File

@@ -5,7 +5,7 @@ import shutil
from lib.six import BytesIO
from core import filetools
from platformcode import logger, platformtools
from platformcode import config, logger, platformtools
import json
import xbmc
import re
@@ -19,6 +19,7 @@ import sys
PY3 = False
if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int
addon = xbmcaddon.Addon('plugin.video.kod')
addonname = addon.getAddonInfo('name')
_hdr_pat = re.compile("^@@ -(\d+),?(\d+)? \+(\d+),?(\d+)? @@.*")
@@ -43,13 +44,13 @@ def loadCommits(page=1):
except:
xbmc.sleep(1000)
else:
platformtools.dialog_notification('Kodi on Demand', 'impossibile controllare gli aggiornamenti')
platformtools.dialog_notification(addonname, config.get_localized_string(70675))
ret = None
return ret
# ret -> aggiornato, necessita reload videolibrary_service
# ret -> aggiornato, necessita reload service
def check(background=False):
if not addon.getSetting('addon_update_enabled'):
return False, False
@@ -109,7 +110,7 @@ def check(background=False):
logger.info(file["filename"])
if 'resources/language' in file["filename"]:
poFilesChanged = True
if 'videolibrary_service.py' in file["filename"]:
if 'service.py' in file["filename"]:
serviceChanged = True
if file['status'] == 'modified' or file['status'] == 'added':
if 'patch' in file:

View File

@@ -20,6 +20,7 @@ from core import jsontools
from platformcode import config, logger
from platformcode import platformtools
from core import scrapertools
from xml.dom import minidom
def mark_auto_as_watched(item):
@@ -511,22 +512,7 @@ def update(folder_content=config.get_setting("folder_tvshows"), folder=""):
data = get_data(payload)
def clean(mostrar_dialogo=False):
"""
limpia la libreria de elementos que no existen
@param mostrar_dialogo: muestra el cuadro de progreso mientras se limpia la videoteca
@type mostrar_dialogo: bool
"""
logger.info()
payload = {"jsonrpc": "2.0", "method": "VideoLibrary.Clean", "id": 1,
"params": {"showdialogs": mostrar_dialogo}}
data = get_data(payload)
if data.get('result', False) == 'OK':
return True
return False
xbmc.executebuiltin('XBMC.ReloadSkin()')
def search_library_path():
@@ -538,26 +524,26 @@ def search_library_path():
return None
def set_content(content_type, silent=False):
def set_content(content_type, silent=False, custom=False):
"""
Procedimiento para auto-configurar la videoteca de kodi con los valores por defecto
@type content_type: str ('movie' o 'tvshow')
@param content_type: tipo de contenido para configurar, series o peliculas
"""
logger.info()
continuar = True
msg_text = ""
videolibrarypath = config.get_setting("videolibrarypath")
forced = config.get_setting('videolibrary_kodi_force')
if content_type == 'movie':
scraper = [config.get_localized_string(70093), config.get_localized_string(70096)]
if forced:
if not custom:
seleccion = 0 # tmdb
else:
seleccion = platformtools.dialog_select(config.get_localized_string(70094), scraper)
# Instalar The Movie Database
# Instalar The Movie Database
if seleccion == -1 or seleccion == 0:
if not xbmc.getCondVisibility('System.HasAddon(metadata.themoviedb.org)'):
if not silent:
@@ -577,9 +563,8 @@ def set_content(content_type, silent=False):
continuar = (install and xbmc.getCondVisibility('System.HasAddon(metadata.themoviedb.org)'))
if not continuar:
msg_text = config.get_localized_string(60047)
if continuar:
xbmc.executebuiltin('xbmc.addon.opensettings(metadata.themoviedb.org)', True)
xbmc.executebuiltin('Addon.OpenSettings(metadata.themoviedb.org)', True)
# Instalar Universal Movie Scraper
elif seleccion == 1:
@@ -603,11 +588,11 @@ def set_content(content_type, silent=False):
if not continuar:
msg_text = config.get_localized_string(70097)
if continuar:
xbmc.executebuiltin('xbmc.addon.opensettings(metadata.universal)', True)
xbmc.executebuiltin('Addon.OpenSettings(metadata.universal)', True)
else: # SERIES
scraper = [config.get_localized_string(70098), config.get_localized_string(70093)]
if forced:
if not custom:
seleccion = 0 # tvdb
else:
seleccion = platformtools.dialog_select(config.get_localized_string(70107), scraper)
@@ -631,9 +616,9 @@ def set_content(content_type, silent=False):
continuar = (install and xbmc.getCondVisibility('System.HasAddon(metadata.tvdb.com)'))
if not continuar:
msg_text = config.get_localized_string(70099)
msg_text = config.get_localized_string(60049)
if continuar:
xbmc.executebuiltin('xbmc.addon.opensettings(metadata.tvdb.com)', True)
xbmc.executebuiltin('Addon.OpenSettings(metadata.tvdb.com)', True)
# Instalar The Movie Database
elif seleccion == 1:
@@ -641,7 +626,7 @@ def set_content(content_type, silent=False):
continuar = False
if not silent:
# Preguntar si queremos instalar metadata.tvshows.themoviedb.org
install = platformtools.dialog_yesno(config.get_localized_string(70100))
install = platformtools.dialog_yesno(config.get_localized_string(60050))
else:
install = True
@@ -656,9 +641,9 @@ def set_content(content_type, silent=False):
continuar = (install and continuar)
if not continuar:
msg_text = config.get_localized_string(60047)
msg_text = config.get_localized_string(60051)
if continuar:
xbmc.executebuiltin('xbmc.addon.opensettings(metadata.tvshows.themoviedb.org)', True)
xbmc.executebuiltin('Addon.OpenSettings(metadata.tvshows.themoviedb.org)', True)
idPath = 0
idParentPath = 0
@@ -719,6 +704,9 @@ def set_content(content_type, silent=False):
elif seleccion == 1:
strScraper = 'metadata.universal'
path_settings = xbmc.translatePath("special://profile/addon_data/metadata.universal/settings.xml")
if not os.path.exists(path_settings):
logger.info("%s: %s" % (content_type, path_settings + " doesn't exist"))
return continuar
settings_data = filetools.read(path_settings)
strSettings = ' '.join(settings_data.split()).replace("> <", "><")
strSettings = strSettings.replace("\"","\'")
@@ -735,6 +723,9 @@ def set_content(content_type, silent=False):
elif seleccion == 1:
strScraper = 'metadata.tvshows.themoviedb.org'
path_settings = xbmc.translatePath("special://profile/addon_data/metadata.tvshows.themoviedb.org/settings.xml")
if not os.path.exists(path_settings):
logger.info("%s: %s" % (content_type, path_settings + " doesn't exist"))
return continuar
settings_data = filetools.read(path_settings)
strSettings = ' '.join(settings_data.split()).replace("> <", "><")
strSettings = strSettings.replace("\"","\'")
@@ -777,16 +768,258 @@ def set_content(content_type, silent=False):
if not continuar:
heading = config.get_localized_string(70102) % content_type
elif content_type == 'SERIES' and not xbmc.getCondVisibility(
elif content_type == 'tvshow' and not xbmc.getCondVisibility(
'System.HasAddon(metadata.tvshows.themoviedb.org)'):
heading = config.get_localized_string(70103) % content_type
msg_text = config.get_localized_string(60058)
else:
heading = config.get_localized_string(70103) % content_type
msg_text = config.get_localized_string(70104)
platformtools.dialog_notification(heading, msg_text, icon=1, time=3000)
logger.info("%s: %s" % (heading, msg_text))
return continuar
def update_db(old_path, new_path, old_movies_folder, new_movies_folder, old_tvshows_folder, new_tvshows_folder, progress):
def path_replace(path, old, new):
if new.startswith("special://") or '://' in new: sep = '/'
else: sep = os.sep
path = path.replace(old,new)
if sep == '/': path = path.replace('\\','/')
else: path = path.replace('/','\\')
return path
logger.info()
sql_old_path = old_path
if sql_old_path.startswith("special://"):
sql_old_path = sql_old_path.replace('/profile/', '/%/').replace('/home/userdata/', '/%/')
sep = '/'
elif '://' in sql_old_path:
sep = '/'
else: sep = os.sep
if not sql_old_path.endswith(sep):
sql_old_path += sep
# search MAIN path in the DB
sql = 'SELECT idPath, strPath FROM path where strPath LIKE "%s"' % sql_old_path
nun_records, records = execute_sql_kodi(sql)
# change main path
if records:
idPath = records[0][0]
strPath = path_replace(records[0][1], old_path, new_path)
sql = 'UPDATE path SET strPath="%s" WHERE idPath=%s' % (strPath, idPath)
nun_records, records = execute_sql_kodi(sql)
p = 80
progress.update(p, config.get_localized_string(20000), config.get_localized_string(80013))
for OldFolder, NewFolder in [[old_movies_folder, new_movies_folder], [old_tvshows_folder, new_tvshows_folder]]:
sql_old_folder = sql_old_path + OldFolder
if not sql_old_folder.endswith(sep): sql_old_folder += sep
# Search Main Sub Folder
sql = 'SELECT idPath, strPath FROM path where strPath LIKE "%s"' % sql_old_folder
nun_records, records = execute_sql_kodi(sql)
# Change Main Sub Folder
if records:
for record in records:
idPath = record[0]
strPath = path_replace(record[1], filetools.join(old_path, OldFolder), filetools.join(new_path, NewFolder))
sql = 'UPDATE path SET strPath="%s" WHERE idPath=%s' % (strPath, idPath)
nun_records, records = execute_sql_kodi(sql)
# Search if Sub Folder exixt in all paths
sql_old_folder += '%'
sql = 'SELECT idPath, strPath FROM path where strPath LIKE "%s"' % sql_old_folder
nun_records, records = execute_sql_kodi(sql)
#Change Sub Folder in all paths
if records:
for record in records:
idPath = record[0]
strPath = path_replace(record[1], filetools.join(old_path, OldFolder), filetools.join(new_path, NewFolder))
sql = 'UPDATE path SET strPath="%s" WHERE idPath=%s' % (strPath, idPath)
nun_records, records = execute_sql_kodi(sql)
if OldFolder == old_movies_folder:
# if is Movie Folder
# search and modify in "movie"
sql = 'SELECT idMovie, c22 FROM movie where c22 LIKE "%s"' % sql_old_folder
nun_records, records = execute_sql_kodi(sql)
if records:
for record in records:
idMovie = record[0]
strPath = path_replace(record[1], filetools.join(old_path, OldFolder), filetools.join(new_path, NewFolder))
sql = 'UPDATE movie SET c22="%s" WHERE idMovie=%s' % (strPath, idMovie)
nun_records, records = execute_sql_kodi(sql)
else:
# if is TV Show Folder
# search and modify in "episode"
sql = 'SELECT idEpisode, c18 FROM episode where c18 LIKE "%s"' % sql_old_folder
nun_records, records = execute_sql_kodi(sql)
if records:
for record in records:
idEpisode = record[0]
strPath = path_replace(record[1], filetools.join(old_path, OldFolder), filetools.join(new_path, NewFolder))
sql = 'UPDATE episode SET c18="%s" WHERE idEpisode=%s' % (strPath, idEpisode)
nun_records, records = execute_sql_kodi(sql)
p += 5
progress.update(p, config.get_localized_string(20000), config.get_localized_string(80013))
progress.update(100)
xbmc.sleep(1000)
progress.close()
xbmc.executebuiltin('XBMC.ReloadSkin()')
def clean(path=''):
def sql_format(path):
if path.startswith("special://"):
path = path.replace('/profile/', '/%/').replace('/home/userdata/', '/%/')
sep = '/'
elif '://' in path:
sep = '/'
else: sep = os.sep
if sep == '/': path = path.replace('\\','/')
else: path = path.replace('/','\\')
return path, sep
logger.info()
idParentPath = 0
sql_path = ''
sql_movies_path = ''
sql_tvshows_path = ''
sql_episodes_path = ''
path, sep = sql_format(path)
movies_folder = config.get_setting("folder_movies")
tvshows_folder = config.get_setting("folder_tvshows")
# delete episode/movie (downloads.py move_to_libray)
if path.endswith(".strm"):
if movies_folder in path:
sql_movies_path = path
else:
sql_episodes_path = path
# delete movie
elif movies_folder in path:
if not path.endswith(sep): path += sep
sql_movies_path = path + '%'
# delete tvshow
elif tvshows_folder in path:
if not path.endswith(sep): path += sep
sql_tvshows_path = path + '%'
sql_episodes_path = sql_tvshows_path
# delete video library
else:
if not path.endswith(sep): path += sep
sql_path = path
sql_movies_path = sql_path + movies_folder
if not sql_movies_path.endswith(sep): sql_movies_path += sep
sql_movies_path += '%'
sql_tvshows_path = sql_path + tvshows_folder
if not sql_tvshows_path.endswith(sep): sql_tvshows_path += sep
sql_tvshows_path += '%'
sql_episodes_path = sql_tvshows_path
progress = platformtools.dialog_progress_bg(config.get_localized_string(20000), config.get_localized_string(80025))
progress.update(0)
if sql_path:
# search video library path in the DB
sql = 'SELECT idPath FROM path where strPath LIKE "%s"' % sql_path
nun_records, records = execute_sql_kodi(sql)
# delete video library path
if records:
idPath = records[0][0]
idParentPath = idPath
if not config.get_setting("videolibrary_kodi"):
sql = 'DELETE from path WHERE idPath=%s' % idPath
nun_records, records = execute_sql_kodi(sql)
progress.update(10)
if sql_movies_path:
# search movies in the DB
sql = 'SELECT idMovie FROM movie where c22 LIKE "%s"' % sql_movies_path
nun_records, records = execute_sql_kodi(sql)
# delete movies
if records:
for record in records:
idMovie = record[0]
sql = 'DELETE from movie WHERE idMovie=%s' % idMovie
nun_records, records = execute_sql_kodi(sql)
progress.update(28)
if sql_movies_path:
# search movies path and folders in the DB
sql = 'SELECT idPath, idParentPath FROM path where strPath LIKE "%s"' % sql_movies_path
nun_records, records = execute_sql_kodi(sql)
# delete movies path and folders
if records:
for record in records:
if record[1] == idParentPath and config.get_setting("videolibrary_kodi"):
continue
idPath = record[0]
sql = 'DELETE from path WHERE idPath=%s' % idPath
nun_records, records = execute_sql_kodi(sql)
progress.update(46)
if sql_tvshows_path:
# search TV shows in the DB
sql = 'SELECT idShow FROM tvshow_view where strPath LIKE "%s"' % sql_tvshows_path
nun_records, records = execute_sql_kodi(sql)
# delete TV shows
if records:
for record in records:
idShow = record[0]
sql = 'DELETE from tvshow WHERE idShow=%s' % idShow
nun_records, records = execute_sql_kodi(sql)
progress.update(64)
if sql_episodes_path:
# search episodes in the DB
sql = 'SELECT idEpisode FROM episode where c18 LIKE "%s"' % sql_episodes_path
nun_records, records = execute_sql_kodi(sql)
# delete episodes
if records:
for record in records:
idEpisode = record[0]
sql = 'DELETE from episode WHERE idEpisode=%s' % idEpisode
nun_records, records = execute_sql_kodi(sql)
progress.update(82)
if sql_tvshows_path:
# search TV shows path and folders in the DB
sql = 'SELECT idPath, idParentPath FROM path where strPath LIKE "%s"' % sql_tvshows_path
nun_records, records = execute_sql_kodi(sql)
# delete tvshows path and folders
if records:
for record in records:
if record[1] == idParentPath and config.get_setting("videolibrary_kodi"):
continue
idPath = record[0]
sql = 'DELETE from path WHERE idPath=%s' % idPath
nun_records, records = execute_sql_kodi(sql)
progress.update(100)
xbmc.sleep(1000)
progress.close()
xbmc.executebuiltin('XBMC.ReloadSkin()')
def execute_sql_kodi(sql):
@@ -854,101 +1087,175 @@ def execute_sql_kodi(sql):
return nun_records, records
def add_sources(path):
def check_sources(new_movies_path='', new_tvshows_path=''):
def format_path(path):
if path.startswith("special://") or '://' in path: sep = '/'
else: sep = os.sep
if not path.endswith(sep): path += sep
return path
logger.info()
from xml.dom import minidom
new_movies_path = format_path(new_movies_path)
new_tvshows_path = format_path(new_tvshows_path)
SOURCES_PATH = xbmc.translatePath("special://userdata/sources.xml")
if os.path.exists(SOURCES_PATH):
if filetools.isfile(SOURCES_PATH):
xmldoc = minidom.parse(SOURCES_PATH)
video_node = xmldoc.childNodes[0].getElementsByTagName("video")[0]
paths_node = video_node.getElementsByTagName("path")
list_path = [p.firstChild.data for p in paths_node]
return new_movies_path in list_path, new_tvshows_path in list_path
else:
# Crear documento
xmldoc = minidom.Document()
nodo_sources = xmldoc.createElement("sources")
source_nodes = xmldoc.createElement("sources")
for type in ['programs', 'video', 'music', 'picture', 'files']:
nodo_type = xmldoc.createElement(type)
element_default = xmldoc.createElement("default")
element_default.setAttribute("pathversion", "1")
nodo_type.appendChild(element_default)
nodo_sources.appendChild(nodo_type)
xmldoc.appendChild(nodo_sources)
source_nodes.appendChild(nodo_type)
xmldoc.appendChild(source_nodes)
# Buscamos el nodo video
nodo_video = xmldoc.childNodes[0].getElementsByTagName("video")[0]
# Buscamos el path dentro de los nodos_path incluidos en el nodo_video
nodos_paths = nodo_video.getElementsByTagName("path")
list_path = [p.firstChild.data for p in nodos_paths]
logger.debug(list_path)
if path in list_path:
logger.debug("La ruta %s ya esta en sources.xml" % path)
return
logger.debug("La ruta %s NO esta en sources.xml" % path)
# Si llegamos aqui es por q el path no esta en sources.xml, asi q lo incluimos
nodo_source = xmldoc.createElement("source")
# Nodo <name>
nodo_name = xmldoc.createElement("name")
sep = os.sep
if path.startswith("special://") or scrapertools.find_single_match(path, '(^\w+:\/\/)'):
sep = "/"
name = path
if path.endswith(sep):
name = path[:-1]
nodo_name.appendChild(xmldoc.createTextNode(name.rsplit(sep)[-1]))
nodo_source.appendChild(nodo_name)
# Nodo <path>
nodo_path = xmldoc.createElement("path")
nodo_path.setAttribute("pathversion", "1")
nodo_path.appendChild(xmldoc.createTextNode(path))
nodo_source.appendChild(nodo_path)
# Nodo <allowsharing>
nodo_allowsharing = xmldoc.createElement("allowsharing")
nodo_allowsharing.appendChild(xmldoc.createTextNode('true'))
nodo_source.appendChild(nodo_allowsharing)
# Añadimos <source> a <video>
nodo_video.appendChild(nodo_source)
# Guardamos los cambios
if not PY3:
filetools.write(SOURCES_PATH,
'\n'.join([x for x in xmldoc.toprettyxml().encode("utf-8").splitlines() if x.strip()]))
else:
filetools.write(SOURCES_PATH,
b'\n'.join([x for x in xmldoc.toprettyxml().encode("utf-8").splitlines() if x.strip()]),
vfs=False)
return False, False
def ask_set_content(flag, silent=False):
def update_sources(new='', old=''):
logger.info()
if new == old: return
SOURCES_PATH = xbmc.translatePath("special://userdata/sources.xml")
if filetools.isfile(SOURCES_PATH):
xmldoc = minidom.parse(SOURCES_PATH)
else:
xmldoc = minidom.Document()
source_nodes = xmldoc.createElement("sources")
for type in ['programs', 'video', 'music', 'picture', 'files']:
nodo_type = xmldoc.createElement(type)
element_default = xmldoc.createElement("default")
element_default.setAttribute("pathversion", "1")
nodo_type.appendChild(element_default)
source_nodes.appendChild(nodo_type)
xmldoc.appendChild(source_nodes)
# collect nodes
# nodes = xmldoc.getElementsByTagName("video")
video_node = xmldoc.childNodes[0].getElementsByTagName("video")[0]
paths_node = video_node.getElementsByTagName("path")
if old:
# delete old path
for node in paths_node:
if node.firstChild.data == old:
parent = node.parentNode
remove = parent.parentNode
remove.removeChild(parent)
# write changes
if sys.version_info[0] >= 3: #PY3
filetools.write(SOURCES_PATH, '\n'.join([x for x in xmldoc.toprettyxml().splitlines() if x.strip()]))
else:
filetools.write(SOURCES_PATH, '\n'.join([x for x in xmldoc.toprettyxml().splitlines() if x.strip()]), vfs=False)
logger.debug("The path %s has been removed from sources.xml" % old)
if new:
# create new path
list_path = [p.firstChild.data for p in paths_node]
if new in list_path:
logger.info("The path %s already exists in sources.xml" % new)
return
logger.info("The path %s does not exist in sources.xml" % new)
# if the path does not exist we create one
source_node = xmldoc.createElement("source")
# <name> Node
name_node = xmldoc.createElement("name")
sep = os.sep
if new.startswith("special://") or scrapertools.find_single_match(new, r'(^\w+:\/\/)'):
sep = "/"
name = new
if new.endswith(sep):
name = new[:-1]
name_node.appendChild(xmldoc.createTextNode(name.rsplit(sep)[-1]))
source_node.appendChild(name_node)
# <path> Node
path_node = xmldoc.createElement("path")
path_node.setAttribute("pathversion", "1")
path_node.appendChild(xmldoc.createTextNode(new))
source_node.appendChild(path_node)
# <allowsharing> Node
allowsharing_node = xmldoc.createElement("allowsharing")
allowsharing_node.appendChild(xmldoc.createTextNode('true'))
source_node.appendChild(allowsharing_node)
# Añadimos <source> a <video>
video_node.appendChild(source_node)
# write changes
if sys.version_info[0] >= 3: #PY3
filetools.write(SOURCES_PATH, '\n'.join([x for x in xmldoc.toprettyxml().splitlines() if x.strip()]))
else:
filetools.write(SOURCES_PATH, '\n'.join([x for x in xmldoc.toprettyxml().splitlines() if x.strip()]), vfs=False)
logger.debug("The path %s has been added to sources.xml" % new)
def ask_set_content(silent=False):
logger.info()
logger.debug("videolibrary_kodi_flag %s" % config.get_setting("videolibrary_kodi_flag"))
logger.debug("videolibrary_kodi %s" % config.get_setting("videolibrary_kodi"))
def do_config():
logger.debug("hemos aceptado")
config.set_setting("videolibrary_kodi", True)
set_content("movie", silent=True)
set_content("tvshow", silent=True)
add_sources(config.get_setting("videolibrarypath"))
add_sources(config.get_setting("downloadpath"))
if not silent:
heading = config.get_localized_string(59971)
linea1 = config.get_localized_string(70105)
linea2 = config.get_localized_string(70106)
if platformtools.dialog_yesno(heading, linea1, linea2):
do_config()
def do_config(custom=False):
if set_content("movie", True, custom) and set_content("tvshow", True, custom):
platformtools.dialog_ok(config.get_localized_string(80026), config.get_localized_string(70104))
config.set_setting("videolibrary_kodi", True)
update()
else:
# no hemos aceptado
platformtools.dialog_ok(config.get_localized_string(80026), config.get_localized_string(80024))
config.set_setting("videolibrary_kodi", False)
else:
do_config()
# configuration during installation
if not silent:
# ask to configure Kodi video library
if platformtools.dialog_yesno(config.get_localized_string(20000), config.get_localized_string(80015)):
# ask for custom or default settings
if not platformtools.dialog_yesno(config.get_localized_string(80026), config.get_localized_string(80016), "", "", config.get_localized_string(80017), config.get_localized_string(80018)):
# input path and folders
path = platformtools.dialog_browse(3, config.get_localized_string(80019), config.get_setting("videolibrarypath"))
movies_folder = platformtools.dialog_input(config.get_setting("folder_movies"), config.get_localized_string(80020))
tvshows_folder = platformtools.dialog_input(config.get_setting("folder_tvshows"), config.get_localized_string(80021))
config.set_setting("videolibrary_kodi_flag", flag)
if path != "" and movies_folder != "" and tvshows_folder != "":
movies_path, tvshows_path = check_sources(filetools.join(path, movies_folder), filetools.join(path, tvshows_folder))
# configure later
if movies_path or tvshows_path:
platformtools.dialog_ok(config.get_localized_string(80026), config.get_localized_string(80029))
# set path and folders
else:
update_sources(path, config.get_setting("videolibrarypath"))
config.set_setting("videolibrarypath", path)
config.set_setting("folder_movies", movies_folder)
config.set_setting("folder_tvshows", tvshows_folder)
config.verify_directories_created()
do_config(True)
# default path and folders
else:
platformtools.dialog_ok(config.get_localized_string(80026), config.get_localized_string(80030))
do_config(True)
# default settings
else:
platformtools.dialog_ok(config.get_localized_string(80026), config.get_localized_string(80027))
do_config(False)
# configure later
else:
platformtools.dialog_ok(config.get_localized_string(20000), config.get_localized_string(80022))
# configuration from the settings menu
else:
platformtools.dialog_ok(config.get_localized_string(80026), config.get_localized_string(80023))
do_config(True)