Merge pull request #402 from lopezvg/master
Videolibrary: reacondocionado de PlayCounts
This commit is contained in:
@@ -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()
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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'))
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
BIN
plugin.video.alfa/resources/media/channels/fanart/estrenosgo.png
Normal file
BIN
plugin.video.alfa/resources/media/channels/fanart/estrenosgo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 41 KiB |
BIN
plugin.video.alfa/resources/media/channels/thumb/estrenosgo.png
Normal file
BIN
plugin.video.alfa/resources/media/channels/thumb/estrenosgo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user