Files
addon/platformcode/xbmc_videolibrary.py
2020-02-24 22:43:31 +01:00

955 lines
39 KiB
Python

# -*- coding: utf-8 -*-
# ------------------------------------------------------------
# XBMC Library Tools
# ------------------------------------------------------------
from future import standard_library
standard_library.install_aliases()
#from builtins import str
import sys
PY3 = False
if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int
import os
import threading
import time
import re
import xbmc
from core import filetools
from core import jsontools
from platformcode import config, logger
from platformcode import platformtools
from core import scrapertools
def mark_auto_as_watched(item):
def mark_as_watched_subThread(item):
logger.info()
# logger.debug("item:\n" + item.tostring('\n'))
condicion = config.get_setting("watched_setting", "videolibrary")
time_limit = time.time() + 30
while not platformtools.is_playing() and time.time() < time_limit:
time.sleep(1)
sync_with_trakt = False
while platformtools.is_playing():
tiempo_actual = xbmc.Player().getTime()
totaltime = xbmc.Player().getTotalTime()
mark_time = 0
if condicion == 0: # '5 minutos'
mark_time = 300
elif condicion == 1: # '30%'
mark_time = totaltime * 0.3
elif condicion == 2: # '50%'
mark_time = totaltime * 0.5
elif condicion == 3: # '80%'
mark_time = totaltime * 0.8
elif condicion == 4: # '0 seg'
mark_time = -1
# logger.debug(str(tiempo_actual))
# logger.debug(str(mark_time))
if tiempo_actual > mark_time:
logger.debug("marcado")
item.playcount = 1
sync_with_trakt = True
from specials import videolibrary
videolibrary.mark_content_as_watched2(item)
break
time.sleep(30)
# Sincronizacion silenciosa con Trakt
if sync_with_trakt:
if config.get_setting("sync_trakt_watched", "videolibrary"):
sync_trakt_kodi()
# logger.debug("Fin del hilo")
# Si esta configurado para marcar como visto
if config.get_setting("mark_as_watched", "videolibrary"):
threading.Thread(target=mark_as_watched_subThread, args=[item]).start()
def sync_trakt_addon(path_folder):
"""
Actualiza los valores de episodios vistos si
"""
logger.info()
# si existe el addon hacemos la busqueda
if xbmc.getCondVisibility('System.HasAddon("script.trakt")'):
# importamos dependencias
paths = ["special://home/addons/script.module.dateutil/lib/", "special://home/addons/script.module.six/lib/",
"special://home/addons/script.module.arrow/lib/", "special://home/addons/script.module.trakt/lib/",
"special://home/addons/script.trakt/"]
for path in paths:
sys.path.append(xbmc.translatePath(path))
# se obtiene las series vistas
try:
from resources.lib.traktapi import traktAPI
traktapi = traktAPI()
except:
return
shows = traktapi.getShowsWatched({})
shows = list(shows.items())
# obtenemos el id de la serie para comparar
_id = re.findall("\[(.*?)\]", path_folder, flags=re.DOTALL)[0]
logger.debug("el id es %s" % _id)
if "tt" in _id:
type_id = "imdb"
elif "tvdb_" in _id:
_id = _id.strip("tvdb_")
type_id = "tvdb"
elif "tmdb_" in _id:
type_id = "tmdb"
_id = _id.strip("tmdb_")
else:
logger.error("No hay _id de la serie")
return
# obtenemos los valores de la serie
from core import videolibrarytools
tvshow_file = filetools.join(path_folder, "tvshow.nfo")
head_nfo, serie = videolibrarytools.read_nfo(tvshow_file)
# buscamos en las series de trakt
for show in shows:
show_aux = show[1].to_dict()
try:
_id_trakt = show_aux['ids'].get(type_id, None)
# logger.debug("ID ES %s" % _id_trakt)
if _id_trakt:
if _id == _id_trakt:
logger.debug("ENCONTRADO!! %s" % show_aux)
# creamos el diccionario de trakt para la serie encontrada con el valor que tiene "visto"
dict_trakt_show = {}
for idx_season, season in enumerate(show_aux['seasons']):
for idx_episode, episode in enumerate(show_aux['seasons'][idx_season]['episodes']):
sea_epi = "%sx%s" % (show_aux['seasons'][idx_season]['number'],
str(show_aux['seasons'][idx_season]['episodes'][idx_episode][
'number']).zfill(2))
dict_trakt_show[sea_epi] = show_aux['seasons'][idx_season]['episodes'][idx_episode][
'watched']
logger.debug("dict_trakt_show %s " % dict_trakt_show)
# obtenemos las keys que son episodios
regex_epi = re.compile('\d+x\d+')
keys_episodes = [key for key in serie.library_playcounts if regex_epi.match(key)]
# obtenemos las keys que son temporadas
keys_seasons = [key for key in serie.library_playcounts if 'season ' in key]
# obtenemos los numeros de las keys temporadas
seasons = [key.strip('season ') for key in keys_seasons]
# marcamos los episodios vistos
for k in keys_episodes:
serie.library_playcounts[k] = dict_trakt_show.get(k, 0)
for season in seasons:
episodios_temporada = 0
episodios_vistos_temporada = 0
# obtenemos las keys de los episodios de una determinada temporada
keys_season_episodes = [key for key in keys_episodes if key.startswith("%sx" % season)]
for k in keys_season_episodes:
episodios_temporada += 1
if serie.library_playcounts[k] > 0:
episodios_vistos_temporada += 1
# se comprueba que si todos los episodios están vistos, se marque la temporada como vista
if episodios_temporada == episodios_vistos_temporada:
serie.library_playcounts.update({"season %s" % season: 1})
temporada = 0
temporada_vista = 0
for k in keys_seasons:
temporada += 1
if serie.library_playcounts[k] > 0:
temporada_vista += 1
# se comprueba que si todas las temporadas están vistas, se marque la serie como vista
if temporada == temporada_vista:
serie.library_playcounts.update({serie.title: 1})
logger.debug("los valores nuevos %s " % serie.library_playcounts)
filetools.write(tvshow_file, head_nfo + serie.tojson())
break
else:
continue
else:
logger.error("no se ha podido obtener el id, trakt tiene: %s" % show_aux['ids'])
except:
import traceback
logger.error(traceback.format_exc())
def sync_trakt_kodi(silent=True):
# Para que la sincronizacion no sea silenciosa vale con silent=False
if xbmc.getCondVisibility('System.HasAddon("script.trakt")'):
notificacion = True
if (not config.get_setting("sync_trakt_notification", "videolibrary") and
platformtools.is_playing()):
notificacion = False
xbmc.executebuiltin('RunScript(script.trakt,action=sync,silent=%s)' % silent)
logger.info("Sincronizacion con Trakt iniciada")
if notificacion:
platformtools.dialog_notification(config.get_localized_string(20000),
config.get_localized_string(60045),
icon=0,
time=2000)
def mark_content_as_watched_on_kodi(item, value=1):
"""
marca el contenido como visto o no visto en la libreria de Kodi
@type item: item
@param item: elemento a marcar
@type value: int
@param value: >0 para visto, 0 para no visto
"""
logger.info()
# logger.debug("item:\n" + item.tostring('\n'))
payload_f = ''
if item.contentType == "movie":
movieid = 0
payload = {"jsonrpc": "2.0", "method": "VideoLibrary.GetMovies",
"params": {"properties": ["title", "playcount", "originaltitle", "file"]},
"id": 1}
data = get_data(payload)
if 'result' in data and "movies" in data['result']:
if item.strm_path: #Si Item es de un episodio
filename = filetools.basename(item.strm_path)
head, tail = filetools.split(filetools.split(item.strm_path)[0])
else: #Si Item es de la Serie
filename = filetools.basename(item.path)
head, tail = filetools.split(filetools.split(item.path)[0])
path = filetools.join(tail, filename)
for d in data['result']['movies']:
if d['file'].replace("/", "\\").endswith(path.replace("/", "\\")):
# logger.debug("marco la pelicula como vista")
movieid = d['movieid']
break
if movieid != 0:
payload_f = {"jsonrpc": "2.0", "method": "VideoLibrary.SetMovieDetails", "params": {
"movieid": movieid, "playcount": value}, "id": 1}
else: # item.contentType != 'movie'
episodeid = 0
payload = {"jsonrpc": "2.0", "method": "VideoLibrary.GetEpisodes",
"params": {"properties": ["title", "playcount", "showtitle", "file", "tvshowid"]},
"id": 1}
data = get_data(payload)
if 'result' in data and "episodes" in data['result']:
if item.strm_path: #Si Item es de un episodio
filename = filetools.basename(item.strm_path)
head, tail = filetools.split(filetools.split(item.strm_path)[0])
else: #Si Item es de la Serie
filename = filetools.basename(item.path)
head, tail = filetools.split(filetools.split(item.path)[0])
path = filetools.join(tail, filename)
for d in data['result']['episodes']:
if d['file'].replace("/", "\\").endswith(path.replace("/", "\\")):
# logger.debug("marco el episodio como visto")
episodeid = d['episodeid']
break
if episodeid != 0:
payload_f = {"jsonrpc": "2.0", "method": "VideoLibrary.SetEpisodeDetails", "params": {
"episodeid": episodeid, "playcount": value}, "id": 1}
if payload_f:
# Marcar como visto
data = get_data(payload_f)
# logger.debug(str(data))
if data['result'] != 'OK':
logger.error("ERROR al poner el contenido como visto")
def mark_season_as_watched_on_kodi(item, value=1):
"""
marca toda la temporada como vista o no vista en la libreria de Kodi
@type item: item
@param item: elemento a marcar
@type value: int
@param value: >0 para visto, 0 para no visto
"""
logger.info()
# logger.debug("item:\n" + item.tostring('\n'))
# Solo podemos marcar la temporada como vista en la BBDD de Kodi si la BBDD es local,
# en caso de compartir BBDD esta funcionalidad no funcionara
if config.get_setting("db_mode", "videolibrary"):
return
if value == 0:
value = 'Null'
request_season = ''
if item.contentSeason > -1:
request_season = ' and c12= %s' % item.contentSeason
tvshows_path = filetools.join(config.get_videolibrary_path(), config.get_setting("folder_tvshows"))
item_path1 = "%" + item.path.replace("\\\\", "\\").replace(tvshows_path, "")
if item_path1[:-1] != "\\":
item_path1 += "\\"
item_path2 = item_path1.replace("\\", "/")
sql = 'update files set playCount= %s where idFile in ' \
'(select idfile from episode_view where (strPath like "%s" or strPath like "%s")%s)' % \
(value, item_path1, item_path2, request_season)
execute_sql_kodi(sql)
def mark_content_as_watched_on_alfa(path):
from specials import videolibrary
from core import videolibrarytools
"""
marca toda la serie o película como vista o no vista en la Videoteca de Alfa basado en su estado en la Videoteca de Kodi
@type str: path
@param path: carpeta de contenido a marcar
"""
logger.info()
#logger.debug("path: " + path)
FOLDER_MOVIES = config.get_setting("folder_movies")
FOLDER_TVSHOWS = config.get_setting("folder_tvshows")
VIDEOLIBRARY_PATH = config.get_videolibrary_config_path()
if not VIDEOLIBRARY_PATH:
return
# Solo podemos marcar el contenido como vista en la BBDD de Kodi si la BBDD es local,
# en caso de compartir BBDD esta funcionalidad no funcionara
#if config.get_setting("db_mode", "videolibrary"):
# return
path2 = ''
if "special://" in VIDEOLIBRARY_PATH:
if FOLDER_TVSHOWS in path:
path2 = re. sub(r'.*?%s' % FOLDER_TVSHOWS, VIDEOLIBRARY_PATH + "/" + FOLDER_TVSHOWS, path).replace("\\", "/")
if FOLDER_MOVIES in path:
path2 = re. sub(r'.*?%s' % FOLDER_MOVIES, VIDEOLIBRARY_PATH + "/" + FOLDER_MOVIES, path).replace("\\", "/")
if "\\" in path:
path = path.replace("/", "\\")
head_nfo, item = videolibrarytools.read_nfo(path) #Leo el .nfo del contenido
if not item:
logger.error('.NFO no encontrado: ' + path)
return
if FOLDER_TVSHOWS in path: #Compruebo si es CINE o SERIE
contentType = "episode_view" #Marco la tabla de BBDD de Kodi Video
nfo_name = "tvshow.nfo" #Construyo el nombre del .nfo
path1 = path.replace("\\\\", "\\").replace(nfo_name, '') #para la SQL solo necesito la carpeta
if not path2:
path2 = path1.replace("\\", "/") #Formato no Windows
else:
path2 = path2.replace(nfo_name, '')
else:
contentType = "movie_view" #Marco la tabla de BBDD de Kodi Video
path1 = path.replace("\\\\", "\\") #Formato Windows
if not path2:
path2 = path1.replace("\\", "/") #Formato no Windows
nfo_name = scrapertools.find_single_match(path2, '\]\/(.*?)$') #Construyo el nombre del .nfo
path1 = path1.replace(nfo_name, '') #para la SQL solo necesito la carpeta
path2 = path2.replace(nfo_name, '') #para la SQL solo necesito la carpeta
path2 = filetools.remove_smb_credential(path2) #Si el archivo está en un servidor SMB, quitamos las credenciales
#Ejecutmos la sentencia SQL
sql = 'select strFileName, playCount from %s where (strPath like "%s" or strPath like "%s")' % (contentType, path1, path2)
nun_records = 0
records = None
nun_records, records = execute_sql_kodi(sql) #ejecución de la SQL
if nun_records == 0: #hay error?
logger.error("Error en la SQL: " + sql + ": 0 registros")
return #salimos: o no está catalogado en Kodi, o hay un error en la SQL
for title, playCount in records: #Ahora recorremos todos los registros obtenidos
if contentType == "episode_view":
title_plain = title.replace('.strm', '') #Si es Serie, quitamos el sufijo .strm
else:
title_plain = scrapertools.find_single_match(item.strm_path, '.(.*?\s\[.*?\])') #si es peli, quitamos el título
if playCount is None or playCount == 0: #todavía no se ha visto, lo ponemos a 0
playCount_final = 0
elif playCount >= 1:
playCount_final = 1
elif not PY3 and isinstance(title_plain, (str, unicode)):
title_plain = title_plain.decode("utf-8").encode("utf-8") #Hacemos esto porque si no genera esto: u'title_plain'
elif PY3 and isinstance(var, bytes):
title_plain = title_plain.decode('utf-8')
item.library_playcounts.update({title_plain: playCount_final}) #actualizamos el playCount del .nfo
if item.infoLabels['mediatype'] == "tvshow": #Actualizamos los playCounts de temporadas y Serie
for season in item.library_playcounts:
if "season" in season: #buscamos las etiquetas "season" dentro de playCounts
season_num = int(scrapertools.find_single_match(season, 'season (\d+)')) #salvamos el núm, de Temporada
item = videolibrary.check_season_playcount(item, season_num) #llamamos al método que actualiza Temps. y Series
filetools.write(path, head_nfo + item.tojson())
#logger.debug(item)
def get_data(payload):
"""
obtiene la información de la llamada JSON-RPC con la información pasada en payload
@type payload: dict
@param payload: data
:return:
"""
import urllib.request, urllib.error
logger.info("payload: %s" % payload)
# Required header for XBMC JSON-RPC calls, otherwise you'll get a 415 HTTP response code - Unsupported media type
headers = {'content-type': 'application/json'}
if config.get_setting("db_mode", "videolibrary"):
try:
try:
xbmc_port = config.get_setting("xbmc_puerto", "videolibrary")
except:
xbmc_port = 0
xbmc_json_rpc_url = "http://" + config.get_setting("xbmc_host", "videolibrary") + ":" + str(
xbmc_port) + "/jsonrpc"
req = urllib.request.Request(xbmc_json_rpc_url, data=jsontools.dump(payload), headers=headers)
f = urllib.request.urlopen(req)
response = f.read()
f.close()
logger.info("get_data: response %s" % response)
data = jsontools.load(response)
except Exception as ex:
template = "An exception of type %s occured. Arguments:\n%r"
message = template % (type(ex).__name__, ex.args)
logger.error("error en xbmc_json_rpc_url: %s" % message)
data = ["error"]
else:
try:
data = jsontools.load(xbmc.executeJSONRPC(jsontools.dump(payload)))
except Exception as ex:
template = "An exception of type %s occured. Arguments:\n%r"
message = template % (type(ex).__name__, ex.args)
logger.error("error en xbmc.executeJSONRPC: %s" % message)
data = ["error"]
logger.info("data: %s" % data)
return data
def update(folder_content=config.get_setting("folder_tvshows"), folder=""):
"""
Actualiza la libreria dependiendo del tipo de contenido y la ruta que se le pase.
@type folder_content: str
@param folder_content: tipo de contenido para actualizar, series o peliculas
@type folder: str
@param folder: nombre de la carpeta a escanear.
"""
logger.info(folder)
payload = {
"jsonrpc": "2.0",
"method": "VideoLibrary.Scan",
"id": 1
}
if folder:
folder = str(folder)
videolibrarypath = config.get_videolibrary_config_path()
if folder.endswith('/') or folder.endswith('\\'):
folder = folder[:-1]
update_path = None
if videolibrarypath.startswith("special:"):
if videolibrarypath.endswith('/'):
videolibrarypath = videolibrarypath[:-1]
update_path = videolibrarypath + "/" + folder_content + "/" + folder + "/"
else:
#update_path = filetools.join(videolibrarypath, folder_content, folder) + "/" # Problemas de encode en "folder"
update_path = filetools.join(videolibrarypath, folder_content, ' ').rstrip()
if not scrapertools.find_single_match(update_path, '(^\w+:\/\/)'):
payload["params"] = {"directory": update_path}
while xbmc.getCondVisibility('Library.IsScanningVideo()'):
xbmc.sleep(500)
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
def search_library_path():
sql = 'SELECT strPath FROM path WHERE strPath LIKE "special://%/plugin.video.kod/library/" AND idParentPath ISNULL'
nun_records, records = execute_sql_kodi(sql)
if nun_records >= 1:
logger.debug(records[0][0])
return records[0][0]
return None
def set_content(content_type, silent=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
"""
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:
seleccion = 0 # tmdb
else:
seleccion = platformtools.dialog_select(config.get_localized_string(70094), scraper)
# Instalar The Movie Database
if seleccion == -1 or seleccion == 0:
if not xbmc.getCondVisibility('System.HasAddon(metadata.themoviedb.org)'):
if not silent:
# Preguntar si queremos instalar metadata.themoviedb.org
install = platformtools.dialog_yesno(config.get_localized_string(60046))
else:
install = True
if install:
try:
# Instalar metadata.themoviedb.org
xbmc.executebuiltin('xbmc.installaddon(metadata.themoviedb.org)', True)
logger.info("Instalado el Scraper de películas de TheMovieDB")
except:
pass
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)
# Instalar Universal Movie Scraper
elif seleccion == 1:
if continuar and not xbmc.getCondVisibility('System.HasAddon(metadata.universal)'):
continuar = False
if not silent:
# Preguntar si queremos instalar metadata.universal
install = platformtools.dialog_yesno(config.get_localized_string(70095))
else:
install = True
if install:
try:
xbmc.executebuiltin('xbmc.installaddon(metadata.universal)', True)
if xbmc.getCondVisibility('System.HasAddon(metadata.universal)'):
continuar = True
except:
pass
continuar = (install and continuar)
if not continuar:
msg_text = config.get_localized_string(70097)
if continuar:
xbmc.executebuiltin('xbmc.addon.opensettings(metadata.universal)', True)
else: # SERIES
scraper = [config.get_localized_string(70098), config.get_localized_string(70093)]
if forced:
seleccion = 0 # tvdb
else:
seleccion = platformtools.dialog_select(config.get_localized_string(70107), scraper)
# Instalar The TVDB
if seleccion == -1 or seleccion == 0:
if not xbmc.getCondVisibility('System.HasAddon(metadata.tvdb.com)'):
if not silent:
# Preguntar si queremos instalar metadata.tvdb.com
install = platformtools.dialog_yesno(config.get_localized_string(60048))
else:
install = True
if install:
try:
# Instalar metadata.tvdb.com
xbmc.executebuiltin('xbmc.installaddon(metadata.tvdb.com)', True)
logger.info("Instalado el Scraper de series de The TVDB")
except:
pass
continuar = (install and xbmc.getCondVisibility('System.HasAddon(metadata.tvdb.com)'))
if not continuar:
msg_text = config.get_localized_string(70099)
if continuar:
xbmc.executebuiltin('xbmc.addon.opensettings(metadata.tvdb.com)', True)
# Instalar The Movie Database
elif seleccion == 1:
if continuar and not xbmc.getCondVisibility('System.HasAddon(metadata.tvshows.themoviedb.org)'):
continuar = False
if not silent:
# Preguntar si queremos instalar metadata.tvshows.themoviedb.org
install = platformtools.dialog_yesno(config.get_localized_string(70100))
else:
install = True
if install:
try:
# Instalar metadata.tvshows.themoviedb.org
xbmc.executebuiltin('xbmc.installaddon(metadata.tvshows.themoviedb.org)', True)
if xbmc.getCondVisibility('System.HasAddon(metadata.tvshows.themoviedb.org)'):
continuar = True
except:
pass
continuar = (install and continuar)
if not continuar:
msg_text = config.get_localized_string(60047)
if continuar:
xbmc.executebuiltin('xbmc.addon.opensettings(metadata.tvshows.themoviedb.org)', True)
idPath = 0
idParentPath = 0
if continuar:
continuar = False
# Buscamos el idPath
sql = 'SELECT MAX(idPath) FROM path'
nun_records, records = execute_sql_kodi(sql)
if nun_records == 1:
idPath = records[0][0] + 1
sql_videolibrarypath = videolibrarypath
if sql_videolibrarypath.startswith("special://"):
sql_videolibrarypath = sql_videolibrarypath.replace('/profile/', '/%/').replace('/home/userdata/', '/%/')
sep = '/'
elif scrapertools.find_single_match(sql_videolibrarypath, '(^\w+:\/\/)'):
sep = '/'
else:
sep = os.sep
if not sql_videolibrarypath.endswith(sep):
sql_videolibrarypath += sep
# Buscamos el idParentPath
sql = 'SELECT idPath, strPath FROM path where strPath LIKE "%s"' % sql_videolibrarypath
nun_records, records = execute_sql_kodi(sql)
if nun_records == 1:
idParentPath = records[0][0]
videolibrarypath = records[0][1][:-1]
continuar = True
else:
# No existe videolibrarypath en la BD: la insertamos
sql_videolibrarypath = videolibrarypath
if not sql_videolibrarypath.endswith(sep):
sql_videolibrarypath += sep
sql = 'INSERT INTO path (idPath, strPath, scanRecursive, useFolderNames, noUpdate, exclude) VALUES ' \
'(%s, "%s", 0, 0, 0, 0)' % (idPath, sql_videolibrarypath)
nun_records, records = execute_sql_kodi(sql)
if nun_records == 1:
continuar = True
idParentPath = idPath
idPath += 1
else:
msg_text = config.get_localized_string(70101)
if continuar:
continuar = False
# Fijamos strContent, strScraper, scanRecursive y strSettings
if content_type == 'movie':
strContent = 'movies'
scanRecursive = 2147483647
if seleccion == -1 or seleccion == 0:
strScraper = 'metadata.themoviedb.org'
path_settings = xbmc.translatePath("special://profile/addon_data/metadata.themoviedb.org/settings.xml")
elif seleccion == 1:
strScraper = 'metadata.universal'
path_settings = xbmc.translatePath("special://profile/addon_data/metadata.universal/settings.xml")
settings_data = filetools.read(path_settings)
strSettings = ' '.join(settings_data.split()).replace("> <", "><")
strSettings = strSettings.replace("\"","\'")
strActualizar = "¿Desea configurar este Scraper en español como opción por defecto para películas?"
if not videolibrarypath.endswith(sep):
videolibrarypath += sep
strPath = videolibrarypath + config.get_setting("folder_movies") + sep
else:
strContent = 'tvshows'
scanRecursive = 0
if seleccion == -1 or seleccion == 0:
strScraper = 'metadata.tvdb.com'
path_settings = xbmc.translatePath("special://profile/addon_data/metadata.tvdb.com/settings.xml")
elif seleccion == 1:
strScraper = 'metadata.tvshows.themoviedb.org'
path_settings = xbmc.translatePath("special://profile/addon_data/metadata.tvshows.themoviedb.org/settings.xml")
settings_data = filetools.read(path_settings)
strSettings = ' '.join(settings_data.split()).replace("> <", "><")
strSettings = strSettings.replace("\"","\'")
strActualizar = "¿Desea configurar este Scraper en español como opción por defecto para series?"
if not videolibrarypath.endswith(sep):
videolibrarypath += sep
strPath = videolibrarypath + config.get_setting("folder_tvshows") + sep
logger.info("%s: %s" % (content_type, strPath))
# Comprobamos si ya existe strPath en la BD para evitar duplicados
sql = 'SELECT idPath FROM path where strPath="%s"' % strPath
nun_records, records = execute_sql_kodi(sql)
sql = ""
if nun_records == 0:
# Insertamos el scraper
sql = 'INSERT INTO path (idPath, strPath, strContent, strScraper, scanRecursive, useFolderNames, ' \
'strSettings, noUpdate, exclude, idParentPath) VALUES (%s, "%s", "%s", "%s", %s, 0, ' \
'"%s", 0, 0, %s)' % (
idPath, strPath, strContent, strScraper, scanRecursive, strSettings, idParentPath)
else:
if not silent:
# Preguntar si queremos configurar themoviedb.org como opcion por defecto
actualizar = platformtools.dialog_yesno(config.get_localized_string(70098), strActualizar)
else:
actualizar = True
if actualizar:
# Actualizamos el scraper
idPath = records[0][0]
sql = 'UPDATE path SET strContent="%s", strScraper="%s", scanRecursive=%s, strSettings="%s" ' \
'WHERE idPath=%s' % (strContent, strScraper, scanRecursive, strSettings, idPath)
if sql:
nun_records, records = execute_sql_kodi(sql)
if nun_records == 1:
continuar = True
if not continuar:
msg_text = config.get_localized_string(60055)
if not continuar:
heading = config.get_localized_string(70102) % content_type
elif content_type == 'SERIES' 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))
def execute_sql_kodi(sql):
"""
Ejecuta la consulta sql contra la base de datos de kodi
@param sql: Consulta sql valida
@type sql: str
@return: Numero de registros modificados o devueltos por la consulta
@rtype nun_records: int
@return: lista con el resultado de la consulta
@rtype records: list of tuples
"""
logger.info()
file_db = ""
nun_records = 0
records = None
# Buscamos el archivo de la BBDD de videos segun la version de kodi
video_db = config.get_platform(True)['video_db']
if video_db:
file_db = filetools.join(xbmc.translatePath("special://userdata/Database"), video_db)
# metodo alternativo para localizar la BBDD
if not file_db or not filetools.exists(file_db):
file_db = ""
for f in filetools.listdir(xbmc.translatePath("special://userdata/Database")):
path_f = filetools.join(xbmc.translatePath("special://userdata/Database"), f)
if filetools.isfile(path_f) and f.lower().startswith('myvideos') and f.lower().endswith('.db'):
file_db = path_f
break
if file_db:
logger.info("Archivo de BD: %s" % file_db)
conn = None
try:
import sqlite3
conn = sqlite3.connect(file_db)
cursor = conn.cursor()
logger.info("Ejecutando sql: %s" % sql)
cursor.execute(sql)
conn.commit()
records = cursor.fetchall()
if sql.lower().startswith("select"):
nun_records = len(records)
if nun_records == 1 and records[0][0] is None:
nun_records = 0
records = []
else:
nun_records = conn.total_changes
conn.close()
logger.info("Consulta ejecutada. Registros: %s" % nun_records)
except:
logger.error("Error al ejecutar la consulta sql")
if conn:
conn.close()
else:
logger.debug("Base de datos no encontrada")
return nun_records, records
def add_sources(path):
logger.info()
from xml.dom import minidom
SOURCES_PATH = xbmc.translatePath("special://userdata/sources.xml")
if os.path.exists(SOURCES_PATH):
xmldoc = minidom.parse(SOURCES_PATH)
else:
# Crear documento
xmldoc = minidom.Document()
nodo_sources = 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)
# 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)
def ask_set_content(flag, 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()
else:
# no hemos aceptado
config.set_setting("videolibrary_kodi", False)
else:
do_config()
config.set_setting("videolibrary_kodi_flag", flag)