Merge pull request #402 from lopezvg/master

Videolibrary: reacondocionado de PlayCounts
This commit is contained in:
Alfa
2018-08-15 12:43:53 -05:00
committed by GitHub
10 changed files with 171 additions and 29 deletions

View File

@@ -274,8 +274,6 @@ def findvideos(item):
item.title = re.sub('\s\[\d+,?\d*?\s\w[b|B]s\]', '', item.title) #Quitamos size de título, si lo traía
item.title = '%s [%s]' % (item.title, size) #Agregamos size al final del título
item.quality = re.sub('\s\[\d+,?\d*?\s\w[b|B]s\]', '', item.quality) #Quitamos size de calidad, si lo traía
item.quality = '%s [%s]' % (item.quality, size) #Agregamos size al final de calidad
item.quality = item.quality.replace("G", "G ").replace("M", "M ") #Se evita la palabra reservada en Unify
patron_t = '<div class="enlace_descarga".*?<a href="(.*?\.torrent)"'
link_torrent = scrapertools.find_single_match(data, patron_t)
@@ -301,6 +299,10 @@ def findvideos(item):
#Llamamos al método para crear el título general del vídeo, con toda la información obtenida de TMDB
item, itemlist = generictools.post_tmdb_findvideos(item, itemlist)
if size:
item.quality = '%s [%s]' % (item.quality, size) #Agregamos size al final de calidad
item.quality = item.quality.replace("G", "G ").replace("M", "M ") #Se evita la palabra reservada en Unify
#Generamos una copia de Item para trabajar sobre ella
item_local = item.clone()

View File

@@ -460,10 +460,18 @@ def findvideos(item):
item_local.quality = quality + tiempo
if "temporada" in temp_epi.lower():
item_local.quality = '%s [Temporada]' % item_local.quality
#Añadimos la duración, que estará en item.quility
if scrapertools.find_single_match(item.quality, '(\[\d+:\d+)'): #si ya tiene la duración, la ponemos
item_local.quality = '%s [%s h]' % (item_local.quality, scrapertools.find_single_match(item.quality, '(\d+:\d+)'))
#if size and item_local.contentType != "episode":
if size:
size = size.replace(".", ",").replace("B,", " B").replace("b,", " b")
item_local.quality = '%s [%s]' % (item_local.quality, size)
if item_local.action == 'show_result': #Viene de una búsqueda global
channel = item_local.channel.capitalize()
if item_local.from_channel:
channel = item_local.from_channel.capitalize()
item_local.quality = '[COLOR yellow][%s][/COLOR] %s' % (channel, item_local.quality)
#Salvamos la url del .torrent
if scrapedurl:

View File

@@ -605,8 +605,10 @@ def listado(item):
if item_local.contentType == "movie":
year = scrapertools.find_single_match(scrapedurl, r'(\d{4})')
if year >= "1900" and year <= "2040" and year != "2020":
title_subs += [year]
item_local.infoLabels['year'] = '-'
item_local.infoLabels['year'] = year
#title_subs += [year]
else:
item_local.infoLabels['year'] = '-'
#Guarda la variable temporal que almacena la info adicional del título a ser restaurada después de TMDB
item_local.title_subs = title_subs
@@ -1074,8 +1076,10 @@ def listado_busqueda(item):
year = ""
year = str(year)
if year >= "1900" and year <= "2040" and year != "2020":
title_subs += [year]
item_local.infoLabels['year'] = '-'
item_local.infoLabels['year'] = year
#title_subs += [year]
else:
item_local.infoLabels['year'] = '-'
#Guarda la variable temporal que almacena la info adicional del título a ser restaurada después de TMDB
item_local.title_subs = title_subs

View File

@@ -44,7 +44,9 @@
"00:00",
"04:00",
"08:00",
"12:00"
"12:00",
"16:00",
"20:00"
]
},
{
@@ -303,6 +305,12 @@
"default": true,
"enabled": "eq(-1,TheTvDB.com)",
"visible": true
},
{
"id": "verify_playcount",
"type": "bool",
"label": "Verificación de los contadores de vídeos vistos/no vistos (desmarcar para verificar)",
"default": false
}
]
}

View File

@@ -546,6 +546,75 @@ def update_tvshow(item):
p_dialog.close()
def verify_playcount_series(item, path):
logger.info()
"""
Este método revisa y repara el PlayCount de una serie que se haya desincronizado de la lista real de episodios en su carpeta. Las entradas de episodios, temporadas o serie que falten, son creado con la marca de "no visto". Posteriormente se envia a verificar los contadores de Temporadas y Serie
En el retorno envía de estado de True si se actualizado o False si no, normalmente por error. Con este estado, el caller puede actualizar el estado de la opción "verify_playcount" en "videolibrary.py". La intención de este método es la de dar una pasada que repare todos los errores y luego desactivarse. Se puede volver a activar en el menú de Videoteca de Alfa.
"""
#logger.debug("item:\n" + item.tostring('\n'))
#Si no ha hecho nunca la verificación, lo forzamos
estado = config.get_setting("verify_playcount", "videolibrary")
if not estado or estado == False:
estado = True #Si no ha hecho nunca la verificación, lo forzamos
else:
estado = False
if item.contentType == 'movie': #Esto es solo para Series
return (item, False)
if filetools.exists(path):
nfo_path = filetools.join(path, "tvshow.nfo")
head_nfo, it = videolibrarytools.read_nfo(nfo_path) #Obtenemos el .nfo de la Serie
if not hasattr(it, 'library_playcounts') or not it.library_playcounts: #Si el .nfo no tiene library_playcounts se lo creamos
logger.error('** No tiene PlayCount')
it.library_playcounts = {}
# Obtenemos los archivos de los episodios
raiz, carpetas_series, ficheros = filetools.walk(path).next()
# Crear un item en la lista para cada strm encontrado
estado_update = False
for i in ficheros:
if i.endswith('.strm'):
season_episode = scrapertools.get_season_and_episode(i)
if not season_episode:
# El fichero no incluye el numero de temporada y episodio
continue
season, episode = season_episode.split("x")
if season_episode not in it.library_playcounts: #No está incluido el episodio
it.library_playcounts.update({season_episode: 0}) #actualizamos el playCount del .nfo
estado_update = True #Marcamos que hemos actualizado algo
if 'season %s' % season not in it.library_playcounts: #No está incluida la Temporada
it.library_playcounts.update({'season %s' % season: 0}) #actualizamos el playCount del .nfo
estado_update = True #Marcamos que hemos actualizado algo
if it.contentSerieName not in it.library_playcounts: #No está incluida la Serie
it.library_playcounts.update({item.contentSerieName: 0}) #actualizamos el playCount del .nfo
estado_update = True #Marcamos que hemos actualizado algo
if estado_update:
logger.error('** Estado de actualización: ' + str(estado) + ' / PlayCount: ' + str(it.library_playcounts))
estado = estado_update
# se comprueba que si todos los episodios de una temporada están marcados, se marque tb la temporada
for key, value in it.library_playcounts.iteritems():
if key.startswith("season"):
season = scrapertools.find_single_match(key, 'season (\d+)') #Obtenemos en núm. de Temporada
it = check_season_playcount(it, season)
# Guardamos los cambios en item.nfo
if filetools.write(nfo_path, head_nfo + it.tojson()):
return (it, estado)
return (item, False)
def mark_content_as_watched2(item):
logger.info()
# logger.debug("item:\n" + item.tostring('\n'))

View File

@@ -215,6 +215,8 @@ def save_tvshow(item, episodelist):
@return: el número de episodios sobreescritos
@rtype fallidos: int
@return: el número de episodios fallidos o -1 si ha fallado toda la serie
@rtype path: str
@return: directorio serie
"""
logger.info()
# logger.debug(item.tostring('\n'))
@@ -223,7 +225,7 @@ def save_tvshow(item, episodelist):
# Si llegados a este punto no tenemos titulo o code, salimos
if not (item.contentSerieName or item.infoLabels['code']) or not item.channel:
logger.debug("NO ENCONTRADO contentSerieName NI code")
return 0, 0, -1 # Salimos sin guardar
return 0, 0, -1, path # Salimos sin guardar
scraper_return = scraper.find_and_set_infoLabels(item)
# Llegados a este punto podemos tener:
@@ -234,7 +236,7 @@ def save_tvshow(item, episodelist):
# TODO de momento si no hay resultado no añadimos nada,
# aunq podriamos abrir un cuadro para introducir el identificador/nombre a mano
logger.debug("NO ENCONTRADO EN SCRAPER O NO TIENE code")
return 0, 0, -1
return 0, 0, -1, path
_id = item.infoLabels['code'][0]
@@ -311,7 +313,7 @@ def save_tvshow(item, episodelist):
if not episodelist:
# La lista de episodios esta vacia
return 0, 0, 0
return 0, 0, 0, path
# Guardar los episodios
'''import time
@@ -619,6 +621,7 @@ def add_tvshow(item, channel=None):
# Obtiene el listado de episodios
itemlist = getattr(channel, item.action)(item)
insertados, sobreescritos, fallidos, path = save_tvshow(item, itemlist)
if not insertados and not sobreescritos and not fallidos:

View File

@@ -297,13 +297,26 @@ def post_tmdb_listado(item, itemlist):
rating = ''
except:
pass
# Si TMDB no ha encontrado el vídeo limpiamos el año
if item_local.infoLabels['year'] == "-":
item_local.infoLabels['year'] = ''
item_local.infoLabels['aired'] = ''
# Si TMDB no ha encontrado nada y hemos usado el año de la web, lo intentamos sin año
if not item_local.infoLabels['tmdb_id']:
if item_local.infoLabels['year']: #lo intentamos de nuevo solo si había año, puede que erroneo
year = item_local.infoLabels['year'] #salvamos el año por si no tiene éxito la nueva búsqueda
item_local.infoLabels['year'] = "-" #reseteo el año
try:
tmdb.set_infoLabels(item_local, True) #pasamos otra vez por TMDB
except:
pass
if not item_local.infoLabels['tmdb_id']: #ha tenido éxito?
item_local.infoLabels['year'] = year #no, restauramos el año y lo dejamos ya
# Para Episodios, tomo el año de exposición y no el de inicio de la serie
elif item_local.infoLabels['aired']:
if item_local.infoLabels['aired']:
item_local.infoLabels['year'] = scrapertools.find_single_match(str(item_local.infoLabels['aired']), r'\/(\d{4})')
# Preparamos el título para series, con los núm. de temporadas, si las hay
@@ -873,7 +886,7 @@ def post_tmdb_findvideos(item, itemlist):
En Itemlist devuelve un Item con el pseudotítulo. Ahí el canal irá agregando el resto.
"""
#logger.debug(item)
logger.debug(item)
#Creción de título general del vídeo a visualizar en Findvideos
itemlist = []
@@ -965,8 +978,8 @@ def post_tmdb_findvideos(item, itemlist):
tiempo_final = tiempo_final / 60 #Lo transformo a minutos
horas = tiempo_final / 60 #Lo transformo a horas
resto = tiempo_final - (horas * 60) #guardo el resto de minutos de la hora
if not scrapertools.find_single_match(item.quality, '(\[\d+:\d+\])'): #si ya tiene la duración, pasamos
item.quality += ' [%s:%s]' % (str(horas).zfill(2), str(resto).zfill(2)) #Lo agrego a Calidad del Servidor
if not scrapertools.find_single_match(item.quality, '(\[\d+:\d+)'): #si ya tiene la duración, pasamos
item.quality += ' [COLOR white][%s:%s h]' % (str(horas).zfill(2), str(resto).zfill(2)) #Lo agrego a Calidad del Servidor
except:
pass
@@ -1019,6 +1032,14 @@ def post_tmdb_findvideos(item, itemlist):
#Pintamos el pseudo-título con toda la información disponible del vídeo
itemlist.append(item.clone(action="", server = "", title=title_gen)) #Título con todos los datos del vídeo
if item.action == 'show_result': #Viene de una búsqueda global
channel = item.channel.capitalize()
if item.from_channel == channel_py or item.channel == channel_py:
channel = item.category
elif item.from_channel:
channel = item.from_channel.capitalize()
item.quality = '[COLOR yellow][%s][/COLOR] %s' % (channel, item.quality)
#agregamos la opción de Añadir a Videoteca para péliculas (no series)
if item.contentType == 'movie' and item.contentChannel != "videolibrary":
#Permitimos la actualización de los títulos, bien para uso inmediato, o para añadir a la videoteca
@@ -1159,11 +1180,13 @@ def fail_over_newpct1(item, patron, patron2=None, timeout=None):
#Cargamos en .json del canal para ver las listas de valores en settings
fail_over = channeltools.get_channel_json(channel_py)
for settings in fail_over['settings']: #Se recorren todos los settings
if settings['id'] == "clonenewpct1_channels_list": #Encontramos en setting
if settings['id'] == "clonenewpct1_channels_list": #Encontramos en setting
fail_over = settings['default'] #Carga lista de clones
break
fail_over_list = ast.literal_eval(fail_over)
if item.from_channel: #Desde search puede venir con el nombre de canal equivocado
item.channel = item.from_channel
#Recorremos el Array identificando el canal que falla
for active, channel, channel_host, contentType, action_excluded in fail_over_list:
if item.channel == channel_py:
@@ -1183,6 +1206,7 @@ def fail_over_newpct1(item, patron, patron2=None, timeout=None):
break
if not channel_failed:
logger.error('Patrón: ' + str(patron) + ' / fail_over_list: ' + str(fail_over_list))
logger.error(item)
return (item, data) #Algo no ha funcionado, no podemos hacer nada

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -50,17 +50,17 @@ def update(path, p_dialog, i, t, serie, overwrite):
try:
if int(overwrite) == 3:
# Sobrescribir todos los archivos (tvshow.nfo, 1x01.nfo, 1x01 [canal].json, 1x01.strm, etc...)
insertados, sobreescritos, fallidos = videolibrarytools.save_tvshow(serie, itemlist)
serie= videolibrary.check_season_playcount(serie, serie.contentSeason)
if filetools.write(path + '/tvshow.nfo', head_nfo + it.tojson()):
serie.infoLabels['playcount'] = serie.playcount
insertados, sobreescritos, fallidos, notusedpath = videolibrarytools.save_tvshow(serie, itemlist)
#serie= videolibrary.check_season_playcount(serie, serie.contentSeason)
#if filetools.write(path + '/tvshow.nfo', head_nfo + it.tojson()):
# serie.infoLabels['playcount'] = serie.playcount
else:
insertados, sobreescritos, fallidos = videolibrarytools.save_episodes(path, itemlist, serie,
silent=True,
overwrite=overwrite)
it = videolibrary.check_season_playcount(it, it.contentSeason)
if filetools.write(path + '/tvshow.nfo', head_nfo + it.tojson()):
serie.infoLabels['playcount'] = serie.playcount
#it = videolibrary.check_season_playcount(it, it.contentSeason)
#if filetools.write(path + '/tvshow.nfo', head_nfo + it.tojson()):
# serie.infoLabels['playcount'] = serie.playcount
insertados_total += insertados
except Exception, ex:
@@ -96,7 +96,8 @@ def check_for_update(overwrite=True):
serie_actualizada = False
update_when_finished = False
hoy = datetime.date.today()
estado_verify_playcount_series = False
try:
if config.get_setting("update", "videolibrary") != 0 or overwrite:
config.set_setting("updatelibrary_last_check", hoy.strftime('%Y-%m-%d'), "videolibrary")
@@ -128,6 +129,19 @@ def check_for_update(overwrite=True):
logger.info("serie=" + serie.contentSerieName)
p_dialog.update(int(math.ceil((i + 1) * t)), heading, serie.contentSerieName)
#Verificamos el estado del serie.library_playcounts de la Serie por si está incompleto
try:
estado = False
#Si no hemos hecho la verificación o no tiene playcount, entramos
estado = config.get_setting("verify_playcount", "videolibrary")
if not estado or estado == False or not serie.library_playcounts: #Si no se ha pasado antes, lo hacemos ahora
serie, estado = videolibrary.verify_playcount_series(serie, path) #También se pasa si falta un PlayCount por completo
except:
pass
else:
if estado: #Si ha tenido éxito la actualización...
estado_verify_playcount_series = True #... se marca para cambiar la opción de la Videoteca
interval = int(serie.active) # Podria ser del tipo bool
@@ -188,10 +202,11 @@ def check_for_update(overwrite=True):
if not serie_actualizada:
update_next += datetime.timedelta(days=interval)
head_nfo, serie = videolibrarytools.read_nfo(tvshow_file) #Vuelve a leer el.nfo, que ha sido modificado
head_nfo, serie = videolibrarytools.read_nfo(tvshow_file) #Vuelve a leer el.nfo, que ha sido modificado
if interval != int(serie.active) or update_next.strftime('%Y-%m-%d') != serie.update_next:
if update_next > hoy:
serie.update_next = update_next.strftime('%Y-%m-%d')
serie.active = interval
serie.update_next = update_next.strftime('%Y-%m-%d')
serie.channel = "videolibrary"
serie.action = "get_seasons"
filetools.write(tvshow_file, head_nfo + serie.tojson())
@@ -205,6 +220,9 @@ def check_for_update(overwrite=True):
else:
update_when_finished = True
if estado_verify_playcount_series: #Si se ha cambiado algún playcount, ...
estado = config.set_setting("verify_playcount", True, "videolibrary") #... actualizamos la opción de Videolibrary
if config.get_setting("search_new_content", "videolibrary") == 1 and update_when_finished:
# Actualizamos la videoteca de Kodi: Buscar contenido en todas las series
if config.is_xbmc():
@@ -254,7 +272,8 @@ def start(thread=True):
def monitor_update():
update_setting = config.get_setting("update", "videolibrary")
if update_setting == 2 or update_setting == 3: # "Actualizar "Cada dia" o "Una vez al dia"
# "Actualizar "Una sola vez al dia" o "al inicar Kodi y al menos una vez al dia"
if update_setting == 2 or update_setting == 3:
hoy = datetime.date.today()
last_check = config.get_setting("updatelibrary_last_check", "videolibrary")
if last_check:
@@ -269,14 +288,15 @@ def monitor_update():
# (last_check, hoy, datetime.datetime.now().hour))
# logger.info("Atraso del inicio del dia: %i:00" % update_start)
if last_check < hoy and datetime.datetime.now().hour >= int(update_start):
logger.info("Inicio actualizacion programada: %s" % datetime.datetime.now())
if last_check <= hoy and datetime.datetime.now().hour == int(update_start):
logger.info("Inicio actualizacion programada para las %s h.: %s" % (update_start, datetime.datetime.now()))
check_for_update(overwrite=False)
if __name__ == "__main__":
# Se ejecuta en cada inicio
import xbmc
import time
# modo adulto:
# sistema actual 0: Nunca, 1:Siempre, 2:Solo hasta que se reinicie Kodi
@@ -289,6 +309,10 @@ if __name__ == "__main__":
if wait > 0:
xbmc.sleep(wait)
# Verificar quick-fixes al abrirse Kodi, y dejarlo corriendo como Thread
from platformcode import updater
updater.check_addon_init()
if not config.get_setting("update", "videolibrary") == 2:
check_for_update(overwrite=False)