diff --git a/plugin.video.alfa/channels/elitetorrent.py b/plugin.video.alfa/channels/elitetorrent.py index fccba66c..c4b74f07 100644 --- a/plugin.video.alfa/channels/elitetorrent.py +++ b/plugin.video.alfa/channels/elitetorrent.py @@ -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 = '
= "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 diff --git a/plugin.video.alfa/channels/videolibrary.json b/plugin.video.alfa/channels/videolibrary.json index a68b173f..4afa81bd 100755 --- a/plugin.video.alfa/channels/videolibrary.json +++ b/plugin.video.alfa/channels/videolibrary.json @@ -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 } ] } \ No newline at end of file diff --git a/plugin.video.alfa/channels/videolibrary.py b/plugin.video.alfa/channels/videolibrary.py index c2927894..bd3a0998 100644 --- a/plugin.video.alfa/channels/videolibrary.py +++ b/plugin.video.alfa/channels/videolibrary.py @@ -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')) diff --git a/plugin.video.alfa/core/videolibrarytools.py b/plugin.video.alfa/core/videolibrarytools.py index ac3dc120..f38242da 100644 --- a/plugin.video.alfa/core/videolibrarytools.py +++ b/plugin.video.alfa/core/videolibrarytools.py @@ -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: diff --git a/plugin.video.alfa/lib/generictools.py b/plugin.video.alfa/lib/generictools.py index 8f1c130e..639d374d 100644 --- a/plugin.video.alfa/lib/generictools.py +++ b/plugin.video.alfa/lib/generictools.py @@ -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 diff --git a/plugin.video.alfa/resources/media/channels/fanart/estrenosgo.png b/plugin.video.alfa/resources/media/channels/fanart/estrenosgo.png new file mode 100644 index 00000000..35f8cca8 Binary files /dev/null and b/plugin.video.alfa/resources/media/channels/fanart/estrenosgo.png differ diff --git a/plugin.video.alfa/resources/media/channels/thumb/estrenosgo.png b/plugin.video.alfa/resources/media/channels/thumb/estrenosgo.png new file mode 100644 index 00000000..f0b3478c Binary files /dev/null and b/plugin.video.alfa/resources/media/channels/thumb/estrenosgo.png differ diff --git a/plugin.video.alfa/videolibrary_service.py b/plugin.video.alfa/videolibrary_service.py index ecbde844..0452fa02 100644 --- a/plugin.video.alfa/videolibrary_service.py +++ b/plugin.video.alfa/videolibrary_service.py @@ -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)