Files
addon/lib/generictools.py
marco 94eac40955 KoD 1.5
-Nuova Ricerca Globale\n-Nuova Rinumerazione\n-Messaggi di Errore più chiari\n-Fix var\n
2020-12-01 20:19:07 +01:00

1774 lines
99 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8 -*-
# ------------------------------------------------------------
# GenericTools
# ------------------------------------------------------------
# Reusable code of different parts of channels that can
# be called from other channels, and thus charify the format
# and result of each channel and reduce the cost of its maintenance
# ------------------------------------------------------------
import re, os, sys, datetime, time, traceback
try: import urlparse
except: import urllib.parse as urlparse
from channelselector import get_thumb
from core import httptools, scrapertools, servertools, channeltools, filetools, tmdb
from core.item import Item
from platformcode import config, logger, platformtools
from lib import jsunpack
channel_py = "newpct1"
intervenido_judicial = 'Domain intervened by the Judicial Authority'
intervenido_policia = 'Judicial_Policia_Nacional'
intervenido_guardia = 'Judicial_Guardia_Civil'
intervenido_sucuri = 'Access Denied - Sucuri Website Firewall'
def update_title(item):
logger.debug()
from core import scraper,support
"""
Utility to disambiguate Titles before adding them to the Video Library. Can be called from Videolibrarytools
or from Episodes on a Channel. If called from a channel, the call would be like this (included in post_tmdb_episodes (item, itemlist)):
# Allow the updating of titles, either for immediate use, or to add to the video library
item.from_action = item.action # Save action
item.from_title = item.title # Save Title
itemlist.append(item.clone(title="** [COLOR limegreen]Update Titles - video library preview[/COLOR] **", action="actualizar_titulos", extra="episodios", tmdb_stat=False))
The channel must add a method to be able to receive the call from Kodi / Alfa, and be able to call this method:
def actualizar_titulos(item):
logger.debug()
itemlist = []
from lib import generictools
from platformcode import launcher
item = generictools.update_title(item) # We call the method that updates the title with tmdb.find_and_set_infoLabels
# We return to the next action on the channel
return launcher.run(item)
To disambiguate titles, TMDB is caused to ask for the really desired title, deleting existing IDs
The user can select the title among those offered on the first screen
or you can cancel and enter a new title on the second screen
If you do it in "Enter another name", TMDB will automatically search for the new title
If you do this under "Complete Information", it changes to the new title, but does not search TMDB. We have to do it again
If the second screen is canceled, the variable "scraper_return" will be False. The user does not want to continue
"""
# logger.debug(item)
# We restore and delete intermediate labels (if called from the channel)
if item.from_action:
item.action = item.from_action
del item.from_action
if item.from_update:
if item.from_title_tmdb: # If the title of the content returned by TMDB was saved, it is restored.
item.title = item.from_title_tmdb
else:
item.add_videolibrary = True # We are Adding to the Video Library. Indicator to control the use of Channels
if item.add_videolibrary:
if item.season_colapse: del item.season_colapse
if item.from_num_season_colapse: del item.from_num_season_colapse
if item.from_title_season_colapse: del item.from_title_season_colapse
if item.contentType == "movie":
if item.from_title_tmdb: # If the title of the content returned by TMDB was saved, it is restored.
item.title = item.from_title_tmdb
del item.add_videolibrary
if item.channel_host: # We already delete the indicator so that it is not stored in the Video Library
del item.channel_host
if item.contentTitle:
item.contentTitle = re.sub(r' -%s-' % item.category, '', item.contentTitle)
item.title = re.sub(r' -%s-' % item.category, '', item.title)
if item.contentType == 'movie':
from_title_tmdb = item.contentTitle
else:
from_title_tmdb = item.contentSerieName
# We only execute this code if it has not been done before in the Channel. For example, if you have called from Episodes or Findvideos,
# The Add to Video Library will no longer be executed, although from the channel you can call as many times as you want,
# or until you find an unambiguous title
if item.tmdb_stat:
if item.from_title_tmdb: del item.from_title_tmdb
if item.from_title: del item.from_title
item.from_update = True
del item.from_update
if item.contentType == "movie":
if item.channel == channel_py: # If it is a NewPct1 movie, we put the name of the clone
item.channel = scrapertools.find_single_match(item.url, r'http.?\:\/\/(?:www.)?(\w+)\.\w+\/')
else:
new_item = item.clone() # We save the initial Item to restore it if the user cancels
if item.contentType == "movie":
if item.channel == channel_py: # If it is a NewPct1 movie, we put the name of the clone
item.channel = scrapertools.find_single_match(item.url, r'http.?\:\/\/(?:www.)?(\w+)\.\w+\/')
# We delete the IDs and the year to force TMDB to ask us
if item.infoLabels['tmdb_id'] or item.infoLabels['tmdb_id'] == None: item.infoLabels['tmdb_id'] = ''
if item.infoLabels['tvdb_id'] or item.infoLabels['tvdb_id'] == None: item.infoLabels['tvdb_id'] = ''
if item.infoLabels['imdb_id'] or item.infoLabels['imdb_id'] == None: item.infoLabels['imdb_id'] = ''
if item.infoLabels['season']: del item.infoLabels['season'] # It works wrong with num. seasonal. Then we restore it
item.infoLabels['year'] = '-'
if item.from_title:
if item.from_title_tmdb:
if scrapertools.find_single_match(item.from_title_tmdb, r'^(?:\[COLOR \w+\])?(.*?)(?:\[)'):
from_title_tmdb = scrapertools.find_single_match(item.from_title_tmdb, r'^(?:\[COLOR \w+\])?(.*?)(?:\[)').strip()
item.title = item.title.replace(from_title_tmdb, item.from_title)
item.infoLabels['title'] = item.from_title
if item.from_title_tmdb: del item.from_title_tmdb
if not item.from_update and item.from_title: del item.from_title
if item.contentSerieName: # We copy the title to serve as a reference in the "Complete Information" menu
item.infoLabels['originaltitle'] = item.contentSerieName
item.contentTitle = item.contentSerieName
else:
item.infoLabels['originaltitle'] = item.contentTitle
scraper_return = scraper.find_and_set_infoLabels(item)
if not scraper_return: # If the user has canceled, we restore the data to the initial situation and leave
return
# item = new_item.clone()
else:
# If the user has changed the data in "Complete Information" you must see the final title in TMDB
if not item.infoLabels['tmdb_id']:
if item.contentSerieName:
item.contentSerieName = item.contentTitle # New title is put
item.infoLabels['noscrap_id'] = '' # It resets, just in case
item.infoLabels['year'] = '-' # It resets, just in case
scraper_return = scraper.find_and_set_infoLabels(item) # Try again
# It seems the user has canceled again. We restore the data to the initial situation
if not scraper_return or not item.infoLabels['tmdb_id']:
item = new_item.clone()
else:
item.tmdb_stat = True # We mark Item as processed correctly by TMDB (pass 2)
else:
item.tmdb_stat = True # We mark Item as successfully processed by TMDB (pass 1)
# If the user has selected a different option or changed something, we adjust the titles
if item.contentType != 'movie' or item.from_update:
item.channel = new_item.channel # Restoring the name of the channel, in case we had changed it
if item.tmdb_stat == True:
if new_item.contentSerieName: # If it's serial ...
filter_languages = config.get_setting("filter_languages", item.channel)
if filter_languages and filter_languages >= 0:
item.title_from_channel = new_item.contentSerieName # I keep the initial title for Filtertools
item.contentSerieName = new_item.contentSerieName # I keep the initial title for Filtertools
else:
item.title = item.title.replace(new_item.contentSerieName, item.contentTitle).replace(from_title_tmdb, item.contentTitle)
item.contentSerieName = item.contentTitle
if new_item.contentSeason: item.contentSeason = new_item.contentSeason # We restore Season
if item.infoLabels['title']: del item.infoLabels['title'] # We delete movie title (it is series)
else: # If it's a movie ...
item.title = item.title.replace(new_item.contentTitle, item.contentTitle).replace(from_title_tmdb, item.contentTitle)
if new_item.infoLabels['year']: # We update the Year in the title
item.title = item.title.replace(str(new_item.infoLabels['year']), str(item.infoLabels['year']))
if new_item.infoLabels['rating']: # We update in Rating in the title
try:
rating_old = ''
if new_item.infoLabels['rating'] and new_item.infoLabels['rating'] != 0.0:
rating_old = float(new_item.infoLabels['rating'])
rating_old = round(rating_old, 1)
rating_new = ''
if item.infoLabels['rating'] and item.infoLabels['rating'] != 0.0:
rating_new = float(item.infoLabels['rating'])
rating_new = round(rating_new, 1)
item.title = item.title.replace("[" + str(rating_old) + "]", "[" + str(rating_new) + "]")
except:
logger.error(traceback.format_exc())
if item.wanted: # We update Wanted, if it exists
item.wanted = item.contentTitle
if new_item.contentSeason: # We restore the no. Season after TMDB
item.contentSeason = new_item.contentSeason
if item.from_update: # If the call is from the channel menu ...
item.from_update = True
del item.from_update
xlistitem = refresh_screen(item) # We refresh the screens with the new Item
# To avoid TMDB "memory effect", it is called with a dummy title to reset buffers
# if item.contentSerieName:
# new_item.infoLabels['tmdb_id'] = '289' # an unambiguous series
# else:
# new_item.infoLabels['tmdb_id'] = '111' # an unambiguous movie
# new_item.infoLabels['year'] = '-'
# if new_item.contentSeason:
# del new_item.infoLabels['season'] # It works wrong with num. seasonal
# support.dbg()
# scraper_return = scraper.find_and_set_infoLabels(new_item)
#logger.debug(item)
return item
def refresh_screen(item):
logger.debug()
"""
#### Kodi 18 compatibility ####
Refreshes the screen with the new Item after having established a dialog that has caused the change of Item
Create an xlistitem to trick Kodi with the xbmcplugin.setResolvedUrl function FALSE
Entry: item: The updated Item
Output: xlistitem The xlistitem created, in case it is of any later use
"""
try:
import xbmcplugin
import xbmcgui
xlistitem = xbmcgui.ListItem(path=item.url) # We create xlistitem for compatibility with Kodi 18
if config.get_platform(True)['num_version'] >= 16.0:
xlistitem.setArt({"thumb": item.contentThumbnail}) # We load the thumb
else:
xlistitem.setThumbnailImage(item.contentThumbnail)
xlistitem.setInfo("video", item.infoLabels) # We copy infoLabel
xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, xlistitem) # We prepare the environment to avoid Kod1 error 18
time.sleep(1) # We leave time for it to run
except:
logger.error(traceback.format_exc())
platformtools.itemlist_update(item) # we refresh the screen with the new Item
return xlistitem
def post_tmdb_listado(item, itemlist):
logger.debug()
itemlist_fo = []
"""
Last for makeup of the titles obtained from TMDB in List and List_Search.
InfoLabel takes all the data of interest and places them in different variables, mainly title
so that it is compatible with Unify, and if there are no Smart Titles, so that the format is the most
similar to Unify.
It also restores various saved data from the title before passing it through TMDB, as keeping them would not have found the title (title_subs)
The method call from Listing or Listing_Search, after passing Itemlist pot TMDB, is:
from lib import generictools
item, itemlist = generictools.post_tmdb_listado (item, itemlist)
"""
# logger.debug(item)
# We delete values if there has been a fail-over
channel_alt = ''
if item.channel_alt:
channel_alt = item.channel_alt
del item.channel_alt
if item.url_alt:
del item.url_alt
# We adjust the category name
if not item.category_new:
item.category_new = ''
for item_local in itemlist: # We go through the Itemlist generated by the channel
item_local.title = re.sub(r'(?i)online|descarga|downloads|trailer|videoteca|gb|autoplay', '', item_local.title).strip()
# item_local.title = re.sub(r'online|descarga|downloads|trailer|videoteca|gb|autoplay', '', item_local.title, flags=re.IGNORECASE).strip()
title = item_local.title
# logger.debug(item_local)
item_local.last_page = 0
del item_local.last_page # We delete traces of pagination
if item_local.contentSeason_save: # We restore the num. seasonal
item_local.contentSeason = item_local.contentSeason_save
# We delete values for each Content if there has been a fail-over
if item_local.channel_alt:
del item_local.channel_alt
if item_local.url_alt:
del item_local.url_alt
if item_local.extra2:
del item_local.extra2
if item_local.library_filter_show:
del item_local.library_filter_show
if item_local.channel_host:
del item_local.channel_host
# We adjust the category name
if item_local.channel == channel_py:
item_local.category = scrapertools.find_single_match(item_local.url, r'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize()
# We restore the additional info saved in the title_subs list, and delete it from Item
title_add = ' '
if item_local.title_subs:
for title_subs in item_local.title_subs:
if "audio" in title_subs.lower(): # restores Audio info
title_add += scrapertools.find_single_match(title_subs, r'[a|A]udio (.*?)')
continue
if scrapertools.find_single_match(title_subs, r'(\d{4})'): # The year is restored, if it has not been given by TMDB
if not item_local.infoLabels['year'] or item_local.infoLabels['year'] == "-":
item_local.infoLabels['year'] = scrapertools.find_single_match(title_subs, r'(\d{4})')
continue
title_add = title_add.rstrip()
title_add = '%s -%s-' % (title_add, title_subs) # all other saved tags are added
item_local.title_subs = []
del item_local.title_subs
# We prepare the video Rating
rating = ''
try:
if item_local.infoLabels['rating'] and item_local.infoLabels['rating'] != 0.0:
rating = float(item_local.infoLabels['rating'])
rating = round(rating, 1)
if rating == 0.0:
rating = ''
except:
logger.error(traceback.format_exc())
__modo_grafico__ = config.get_setting('modo_grafico', item.channel)
# If TMDB has not found the video we clean the year
if item_local.infoLabels['year'] == "-":
item_local.infoLabels['year'] = ''
item_local.infoLabels['aired'] = ''
# If it brought the TMDB-ID, but it did not work, we reset it and tried again
if item_local.infoLabels['tmdb_id'] and not item_local.infoLabels['originaltitle']:
logger.error("*** Wrong TMDB-ID, reset and retry ***")
logger.error(item_local)
del item_local.infoLabels['tmdb_id'] # you can bring a wrong TMDB-ID
try:
tmdb.set_infoLabels(item_local, __modo_grafico__) # we go through TMDB again
except:
logger.error(traceback.format_exc())
logger.error(item_local)
# If TMDB has not found anything and we have used the year of the web, we try without year
if not item_local.infoLabels['tmdb_id']:
if item_local.infoLabels['year']: # We try again only if there was a year, I may be wrong
year = item_local.infoLabels['year'] # we save the year in case the new search is not successful
item_local.infoLabels['year'] = "-" # reset the year
try:
tmdb.set_infoLabels(item_local, __modo_grafico__) # we go through TMDB again
except:
logger.error(traceback.format_exc())
if not item_local.infoLabels['tmdb_id']: # it has been successful?
item_local.infoLabels['year'] = year # no, we restore the year and leave it now
# For Episodes, I take the year of exposure and not the year of beginning of the series
if item_local.infoLabels['aired']:
item_local.infoLabels['year'] = scrapertools.find_single_match(str(item_local.infoLabels['aired']), r'\/(\d{4})')
if item_local.from_title:
if item_local.contentType == 'movie':
item_local.contentTitle = item_local.from_title
item_local.title = item_local.from_title
else:
item_local.contentSerieName = item_local.from_title
if item_local.contentType == 'season':
item_local.title = item_local.from_title
item_local.title = re.sub(r'(?i)online|descarga|downloads|trailer|videoteca|gb|autoplay', '', item_local.title).strip()
title = item_local.title
# We clean quality of original titles that may have been cast
if item_local.infoLabels['originaltitle'].lower() in item_local.quality.lower():
item_local.quality = re.sub(item_local.infoLabels['originaltitle'], '', item_local.quality)
#item_local.quality = re.sub(item_local.infoLabels['originaltitle'], '', item_local.quality, flags=re.IGNORECASE)
# We prepare the title for series, with no. of seasons, if any
if item_local.contentType in ['season', 'tvshow', 'episode']:
if item_local.contentType == "episode":
# If the title of the episode is not there, but it is in "title", we rescue it
if not item_local.infoLabels['episodio_titulo'] and item_local.infoLabels['title'].lower() != item_local.infoLabels['tvshowtitle'].lower():
item_local.infoLabels['episodio_titulo'] = item_local.infoLabels['title']
if "Temporada" in title: # We make "Season" compatible with Unify
title = '%sx%s al 99 -' % (str(item_local.contentSeason), str(item_local.contentEpisodeNumber))
if " al " in title: # If they are multiple episodes, we put a series name
if " al 99" in title.lower(): # Full season. We are looking for total number of episodes
title = title.replace("99", str(item_local.infoLabels['temporada_num_episodios']))
title = '%s %s' % (title, item_local.contentSerieName)
item_local.infoLabels['episodio_titulo'] = '%s - %s [%s] [%s]' % (scrapertools.find_single_match(title, r'(al \d+)'), item_local.contentSerieName, item_local.infoLabels['year'], rating)
elif item_local.infoLabels['episodio_titulo']:
title = '%s %s, %s' % (title, item_local.infoLabels['episodio_titulo'], item_local.contentSerieName)
item_local.infoLabels['episodio_titulo'] = '%s, %s [%s] [%s]' % (item_local.infoLabels['episodio_titulo'], item_local.contentSerieName, item_local.infoLabels['year'], rating)
else: # If there is no episode title, we will put the name of the series
if item_local.contentSerieName not in title:
title = '%s %s' % (title, item_local.contentSerieName)
item_local.infoLabels['episodio_titulo'] = '%s [%s] [%s]' % (item_local.contentSerieName, item_local.infoLabels['year'], rating)
if not item_local.contentSeason or not item_local.contentEpisodeNumber:
if "Episodio" in title_add:
item_local.contentSeason, item_local.contentEpisodeNumber = scrapertools.find_single_match(title_add, r'Episodio (\d+)x(\d+)')
title = '%s [%s] [%s]' % (title, item_local.infoLabels['year'], rating)
elif item_local.contentType == "season":
if not item_local.contentSeason:
item_local.contentSeason = scrapertools.find_single_match(item_local.url, r'-(\d+)x')
if not item_local.contentSeason:
item_local.contentSeason = scrapertools.find_single_match(item_local.url, r'-temporadas?-(\d+)')
if item_local.contentSeason:
title = '%s -Temporada %s' % (title, str(item_local.contentSeason))
if not item_local.contentSeason_save: # We restore the num. seasonal
item_local.contentSeason_save = item_local.contentSeason # And we save him again
del item_local.infoLabels['season'] # It works wrong with num. seasonal. Then we restore it
else:
title = '%s -Temporada !!!' % (title)
elif item.action == "search" or item.extra == "search":
title += " -Serie-"
if (item_local.extra == "varios" or item_local.extra == "documentales") and (item.action == "search" or item.extra == "search" or item.action == "listado_busqueda"):
title += " -Varios-"
item_local.contentTitle += " -Varios-"
title += title_add # Additional tags are added, if any
# Now we make up the titles a bit depending on whether smart titles have been selected or not
if not config.get_setting("unify"): # If Smart Titles NOT selected:
title = '%s [COLOR yellow][%s][/COLOR] [%s] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (title, str(item_local.infoLabels['year']), rating, item_local.quality, str(item_local.language))
else: # If Smart Titles YES selected:
title = title.replace("[", "-").replace("]", "-").replace(".", ",").replace("GB", "G B").replace("Gb", "G b").replace("gb", "g b").replace("MB", "M B").replace("Mb", "M b").replace("mb", "m b")
# We clean the empty labels
if item_local.infoLabels['episodio_titulo']:
item_local.infoLabels['episodio_titulo'] = item_local.infoLabels['episodio_titulo'].replace(" []", "").strip()
title = title.replace("--", "").replace(" []", "").replace("()", "").replace("(/)", "").replace("[/]", "").strip()
title = re.sub(r'\s?\[COLOR \w+\]\[\[?\s?\]?\]\[\/COLOR\]', '', title).strip()
title = re.sub(r'\s?\[COLOR \w+\]\s?\[\/COLOR\]', '', title).strip()
if item.category_new == "newest": # It comes from News. We mark the title with the name of the channel
if scrapertools.find_single_match(item_local.url, r'http.?\:\/\/(?:www.)?(\w+)\.\w+\/'):
title += ' -%s-' % scrapertools.find_single_match(item_local.url, r'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize()
else:
title += ' -%s-' % item_local.channel.capitalize()
if item_local.contentType == "movie":
if scrapertools.find_single_match(item_local.url, r'http.?\:\/\/(?:www.)?(\w+)\.\w+\/'):
item_local.contentTitle += ' -%s-' % scrapertools.find_single_match(item_local.url, r'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize()
else:
item_local.contentTitle += ' -%s-' % item_local.channel.capitalize()
elif "Episodio " in title:
if not item_local.contentSeason or not item_local.contentEpisodeNumber:
item_local.contentSeason, item_local.contentEpisodeNumber = scrapertools.find_single_match(title_add, r'Episodio (\d+)x(\d+)')
item_local.title = title
#logger.debug("url: " + item_local.url + " / title: " + item_local.title + " / content title: " + item_local.contentTitle + "/" + item_local.contentSerieName + " / calidad: " + item_local.quality + "[" + str(item_local.language) + "]" + " / year: " + str(item_local.infoLabels['year']))
#logger.debug(item_local)
# If judicial intervention, I warn !!!
if item.intervencion:
for clone_inter, autoridad in item.intervencion:
thumb_intervenido = get_thumb(autoridad)
itemlist_fo.append(item.clone(action='', title="[COLOR yellow]" + clone_inter.capitalize() + ': [/COLOR]' + intervenido_judicial + '. Reportar el problema en el foro', thumbnail=thumb_intervenido))
del item.intervencion
# If there has been a fail-over, I will comment
if channel_alt and item.category_new != "newest":
itemlist_fo.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR] [ALT ] en uso'))
itemlist_fo.append(item.clone(action='', title="[COLOR yellow]" + channel_alt.capitalize() + '[/COLOR] inaccesible'))
if len(itemlist_fo) > 0:
itemlist = itemlist_fo + itemlist
del item.category_new
return (item, itemlist)
def post_tmdb_seasons(item, itemlist):
logger.debug()
"""
Past to manage the Seasons menu of a Series
The activation key for this method is the variable item.season_colapse that puts the channel in the Listing Item.
This variable will have to disappear when it is added to the Video Library so that episodes are analyzed in the traditional way.
Review all the episodes produced in itemlist by "episodes" of the channel to extract the seasons. Puts a title for All Temps.
Create a menu with the different seasons, as well as the titles of Title Update and Add to Video Library
If there has been a Fail-over or a Judicial Intervention, it also announces it
The method call from Episodes, before passing Itemlist pot TMDB, is:
from lib import generictools
item, itemlist = generictools.post_tmdb_seasons (item, itemlist)
If there is only one season, please return the original itemlist so that the episodes are painted the traditional way
"""
# logger.debug(item)
season = 0
itemlist_temporadas = []
itemlist_fo = []
if config.get_setting("no_pile_on_seasons", 'videolibrary') == 2: # If you do not want to show seasonally, we are leaving ...
if item.season_colapse: # We remove the indicator from the list by Seasons
del item.season_colapse
return (item, itemlist)
# We restore values if there has been a fail-over
channel_alt = ''
if item.channel == channel_py:
if item.channel_alt:
channel_alt = item.category
item.category = item.channel_alt.capitalize()
del item.channel_alt
else:
if item.channel_alt:
channel_alt = item.channel
item.channel = item.channel_alt
item.category = item.channel_alt.capitalize()
del item.channel_alt
if item.url_alt:
item.url = item.url_alt
del item.url_alt
# First we create a title for ALL Seasons
# Passed by TMDB to Serial, for additional data
try:
tmdb.set_infoLabels(item, True) # TMDB of each Temp
except:
logger.error(traceback.format_exc())
item_season = item.clone()
if item_season.season_colapse: # We remove the indicator from the list by Seasons
del item_season.season_colapse
title = '** Todas las Temporadas' # We add title of ALL Seasons (traditional way)
if item_season.infoLabels['number_of_episodes']: # We put the number of episodes of the Series
title += ' [%sx%s epi]' % (str(item_season.infoLabels['number_of_seasons']), str(item_season.infoLabels['number_of_episodes']))
rating = '' # We put the rating, if it is different from that of the Series
if item_season.infoLabels['rating'] and item_season.infoLabels['rating'] != 0.0:
try:
rating = float(item_season.infoLabels['rating'])
rating = round(rating, 1)
except:
logger.error(traceback.format_exc())
if rating and rating == 0.0:
rating = ''
if not config.get_setting("unify"): # If Smart Titles NOT selected:
title = '%s [COLOR yellow][%s][/COLOR] [%s] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (title, str(item_season.infoLabels['year']), rating, item_season.quality, str(item_season.language))
else: # We fixed it a bit for Unify
title = title.replace('[', '-').replace(']', '-').replace('.', ',').strip()
title = title.replace("--", "").replace("[]", "").replace("()", "").replace("(/)", "").replace("[/]", "").strip()
if config.get_setting("show_all_seasons", 'videolibrary'):
itemlist_temporadas.append(item_season.clone(title=title, from_title_season_colapse=item.title))
# We review all the episodes to detect the different seasons
for item_local in itemlist:
if item_local.contentSeason != season:
season = item_local.contentSeason # If a different season is detected a title is prepared
item_season = item.clone()
item_season.contentSeason = item_local.contentSeason # Season number is set to get better TMDB data
item_season.title = 'Temporada %s' % item_season.contentSeason
itemlist_temporadas.append(item_season.clone(from_title_season_colapse=item.title))
# If there is more than one season it is followed, or it has been forced to list by seasons, if the original Itemlist is not returned
if len(itemlist_temporadas) > 2 or config.get_setting("no_pile_on_seasons", 'videolibrary') == 0:
for item_local in itemlist_temporadas:
if "** Todas las Temporadas" in item_local.title: # If it's the title of ALL Seasons, we ignore it
continue
# Passed by TMDB to the Seasons
try:
tmdb.set_infoLabels(item_local, True) # TMDB of each Temp
except:
logger.error(traceback.format_exc())
if item_local.infoLabels['temporada_air_date']: # Temp issue date
item_local.title += ' [%s]' % str(scrapertools.find_single_match(str(item_local.infoLabels['temporada_air_date']), r'\/(\d{4})'))
#rating = '' # We put the rating, if it is different from that of the Series
#if item_local.infoLabels['rating'] and item_local.infoLabels['rating'] != 0.0:
# try:
# rating = float(item_local.infoLabels['rating'])
# rating = round(rating, 1)
# except:
# logger.error(traceback.format_exc())
#if rating and rating > 0.0:
# item_local.title += ' [%s]' % str(rating)
if item_local.infoLabels['temporada_num_episodios']: # No. of Temp Episodes
item_local.title += ' [%s epi]' % str(item_local.infoLabels['temporada_num_episodios'])
if not config.get_setting("unify"): # If Smart Titles NOT selected:
item_local.title = '%s [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (item_local.title, item_local.quality, str(item_local.language))
else: # We fixed it a bit for Unify
item_local.title = item_local.title.replace("[", "-").replace("]", "-").replace(".", ",").replace("GB", "G B").replace("Gb", "G b").replace("gb", "g b").replace("MB", "M B").replace("Mb", "M b").replace("mb", "m b")
item_local.title = item_local.title.replace("--", "").replace("[]", "").replace("()", "").replace("(/)", "").replace("[/]", "").strip()
#logger.debug(item_local)
else: # If there is more than one season it is followed, if the original Itemlist is not returned
if item.season_colapse:
del item.season_colapse
return (item, itemlist)
# We allow the updating of titles, either for immediate use, or to add to the video library
itemlist_temporadas.append(item.clone(title="** [COLOR yelow]Actualizar Títulos - vista previa videoteca[/COLOR] **", action="actualizar_titulos", tmdb_stat=False, from_action=item.action, from_title_tmdb=item.title, from_update=True))
# It is a standard channel, just a line of Add to Video Library
title = ''
if item.infoLabels['status'] and item.infoLabels['status'].lower() == "ended":
title += ' [TERMINADA]'
itemlist_temporadas.append(item_season.clone(title="[COLOR yellow]Añadir esta serie a videoteca-[/COLOR]" + title, action="add_serie_to_library", extra="episodios", add_menu=True))
# If judicial intervention, I warn !!!
if item.intervencion:
for clone_inter, autoridad in item.intervencion:
thumb_intervenido = get_thumb(autoridad)
itemlist_fo.append(item.clone(action='', title="[COLOR yellow]" + clone_inter.capitalize() + ': [/COLOR]' + intervenido_judicial + '. Reportar el problema en el foro', thumbnail=thumb_intervenido))
del item.intervencion
# If there has been a fail-over, I will comment
if channel_alt:
itemlist_fo.append(item.clone(action='', title="[COLOR yellow]" + channel_alt.capitalize() + '[/COLOR] [ALT ] en uso'))
itemlist_fo.append(item.clone(action='', title="[COLOR yellow]" + item.category.capitalize() + '[/COLOR] inaccesible'))
if len(itemlist_fo) > 0:
itemlist_temporadas = itemlist_fo + itemlist_temporadas
return (item, itemlist_temporadas)
def post_tmdb_episodios(item, itemlist):
logger.debug()
itemlist_fo = []
"""
Last for makeup of the titles obtained from TMDB in Episodes.
InfoLabel takes all the data of interest and places them in different variables, mainly title
so that it is compatible with Unify, and if there are no Smart Titles, so that the format is the most
similar to Unify.
Keep track of the num. of episodes per season, trying to fix Web and TMDB errors
The method call from Episodes, after passing Itemlist pot TMDB, is:
from lib import generictools
item, itemlist = generictools.post_tmdb_episodes (item, itemlist)
"""
# logger.debug(item)
modo_serie_temp = ''
if config.get_setting('seleccionar_serie_temporada', item.channel) >= 0:
modo_serie_temp = config.get_setting('seleccionar_serie_temporada', item.channel)
modo_ultima_temp = ''
if config.get_setting('seleccionar_ult_temporadda_activa', item.channel) is True or config.get_setting('seleccionar_ult_temporadda_activa', item.channel) is False:
modo_ultima_temp = config.get_setting('seleccionar_ult_temporadda_activa', item.channel)
# Initiates variables to control the number of episodes per season
num_episodios = 1
num_episodios_lista = []
for i in range(0, 50): num_episodios_lista += [0]
num_temporada = 1
num_temporada_max = 99
num_episodios_flag = True
# We restore the Season number to make the choice of Video Library more flexible
contentSeason = item.contentSeason
if item.contentSeason_save:
contentSeason = item.contentSeason_save
item.contentSeason = item.contentSeason_save
del item.contentSeason_save
# We adjust the category name
if item.channel == channel_py:
item.category = scrapertools.find_single_match(item.url, r'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize()
# We restore values if there has been a fail-over
channel_alt = ''
if item.channel == channel_py:
if item.channel_alt:
channel_alt = item.category
item.category = item.channel_alt.capitalize()
del item.channel_alt
else:
if item.channel_alt:
channel_alt = item.channel
item.channel = item.channel_alt
item.category = item.channel_alt.capitalize()
del item.channel_alt
if item.url_alt:
item.url = item.url_alt
del item.url_alt
if item.title_from_channel:
del item.title_from_channel
if item.ow_force:
del item.ow_force
if item.season_colapse:
del item.season_colapse
if item.from_action:
del item.from_action
if item.from_channel:
del item.from_channel
if item.library_filter_show:
del item.library_filter_show
if item.channel_host:
del item.channel_host
for item_local in itemlist: # We go through the Itemlist generated by the channel
if item_local.add_videolibrary:
del item_local.add_videolibrary
if item_local.add_menu:
del item_local.add_menu
if item_local.contentSeason_save:
del item_local.contentSeason_save
if item_local.title_from_channel:
del item_local.title_from_channel
if item_local.library_playcounts:
del item_local.library_playcounts
if item_local.library_urls:
del item_local.library_urls
if item_local.path:
del item_local.path
if item_local.nfo:
del item_local.nfo
if item_local.update_last:
del item_local.update_last
if item_local.update_next:
del item_local.update_next
if item_local.channel_host:
del item_local.channel_host
if item_local.intervencion:
del item_local.intervencion
if item_local.ow_force:
del item_local.ow_force
if item_local.season_colapse:
del item_local.season_colapse
if item_local.from_action:
del item_local.from_action
if item_local.from_channel:
del item_local.from_channel
if item_local.emergency_urls and isinstance(item_local.emergency_urls, dict):
del item_local.emergency_urls
if item_local.library_filter_show:
del item_local.library_filter_show
if item_local.extra2:
del item_local.extra2
item_local.wanted = 'xyz'
del item_local.wanted
item_local.text_color = 'xyz'
del item_local.text_color
item_local.tmdb_stat = 'xyz'
del item_local.tmdb_stat
item_local.totalItems = 'xyz'
del item_local.totalItems
item_local.unify = 'xyz'
del item_local.unify
item_local.title = re.sub(r'(?i)online|descarga|downloads|trailer|videoteca|gb|autoplay', '', item_local.title).strip()
# logger.debug(item_local)
# We adjust the category name if it is a clone of NewPct1
if item_local.channel == channel_py:
item_local.category = scrapertools.find_single_match(item_local.url, r'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize()
# We restore values for each Episode if there has been a fail-over of a NewPct1 clone
if item_local.channel == channel_py:
if item_local.channel_alt:
item_local.category = item_local.channel_alt
del item_local.channel_alt
else:
if item_local.channel_alt:
item_local.channel = item_local.channel_alt
del item_local.channel_alt
if item_local.url_alt:
host_act = scrapertools.find_single_match(item_local.url, r':\/\/(.*?)\/')
host_org = scrapertools.find_single_match(item_local.url_alt, r':\/\/(.*?)\/')
item_local.url = item_local.url.replace(host_act, host_org)
del item_local.url_alt
# If you are updating video library of a NewPct1 series, we restore the channel with the name of the clone
if item_local.channel == channel_py and (item.library_playcounts or item.add_videolibrary):
item_local.channel = scrapertools.find_single_match(item_local.url, r'http.?\:\/\/(?:www.)?(\w+)\.\w+\/')
# If the series title is verified in TMDB, it tries to discover the out of range episodes,
# which are probable errors of the Web
if item.tmdb_stat:
if item_local.infoLabels['number_of_seasons']:
# If the season num is out of control, it gets 0, and itemlist is reclassified
if item_local.contentSeason > item_local.infoLabels['number_of_seasons'] + 1:
logger.error("ERROR 07: EPISODES: Season number out of range " + " / SEASON: " + str(item_local.contentSeason) + " / " + str(item_local.contentEpisodeNumber) + " / MAX_SEASONS: " + str(item_local.infoLabels['number_of_seasons']) + " / SEASON_LIST: " + str(num_episodios_lista))
item_local.contentSeason = 0
itemlist = sorted(itemlist, key=lambda it: (int(it.contentSeason), int(it.contentEpisodeNumber)))
else:
num_temporada_max = item_local.infoLabels['number_of_seasons']
else:
if item_local.contentSeason > num_temporada_max + 1:
logger.error("ERROR 07: EPISODES: Season number out of range " + " / SEASON: " + str(item_local.contentSeason) + " / " + str(item_local.contentEpisodeNumber) + " / MAX_SEASONS: " + str(num_temporada_max) + " / SEASON_LIST: " + str(num_episodios_lista))
item_local.contentSeason = 0
itemlist = sorted(itemlist, key=lambda it: (int(it.contentSeason), int(it.contentEpisodeNumber)))
# We save in number of episodes of the season
try:
if num_temporada != item_local.contentSeason:
num_temporada = item_local.contentSeason
num_episodios = 0
if item_local.infoLabels['temporada_num_episodios'] and int(item_local.infoLabels['temporada_num_episodios']) > int(num_episodios):
num_episodios = item_local.infoLabels['temporada_num_episodios']
except:
num_episodios = 0
logger.error(traceback.format_exc())
# We prepare the video Rating
rating = ''
try:
if item_local.infoLabels['rating'] and item_local.infoLabels['rating'] != 0.0:
rating = float(item_local.infoLabels['rating'])
rating = round(rating, 1)
if rating == 0.0:
rating = ''
except:
logger.error(traceback.format_exc())
# If TMDB has not found the video we clean the year
if item_local.infoLabels['year'] == "-":
item_local.infoLabels['year'] = ''
item_local.infoLabels['aired'] = ''
# For Episodes, I take the year of exposure and not the year of beginning of the series
elif item_local.infoLabels['aired']:
item_local.infoLabels['year'] = scrapertools.find_single_match(str(item_local.infoLabels['aired']), r'\/(\d{4})')
# We clean quality of original titles that may have been cast
if item_local.infoLabels['originaltitle'].lower() in item_local.quality.lower():
item_local.quality = re.sub(item_local.infoLabels['originaltitle'], '', item_local.quality)
# item_local.quality = re.sub(item_local.infoLabels['originaltitle'], '', item_local.quality, flags=re.IGNORECASE)
# If the title of the episode is not there, but it is in "title", we rescue it
if not item_local.infoLabels['episodio_titulo'] and item_local.infoLabels['title'].lower() != item_local.infoLabels['tvshowtitle'].lower():
item_local.infoLabels['episodio_titulo'] = item_local.infoLabels['title']
item_local.infoLabels['episodio_titulo'] = item_local.infoLabels['episodio_titulo'].replace('GB', 'G B').replace('MB', 'M B')
# We prepare the title to be compatible with Add Series to Video Library
if "Temporada" in item_local.title: # We make "Season" compatible with Unify
item_local.title = '%sx%s al 99 -' % (str(item_local.contentSeason), str(item_local.contentEpisodeNumber))
if " al " in item_local.title: # If they are multiple episodes, we put a series name
if " al 99" in item_local.title.lower(): # Full season. We are looking for the total number of episodes of the season
item_local.title = item_local.title.replace("99", str(num_episodios))
item_local.title = '%s %s' % (item_local.title, item_local.contentSerieName)
item_local.infoLabels['episodio_titulo'] = '%s - %s [%s] [%s]' % (scrapertools.find_single_match(item_local.title, r'(al \d+)'), item_local.contentSerieName, item_local.infoLabels['year'], rating)
elif item_local.infoLabels['episodio_titulo']:
item_local.title = '%s %s' % (item_local.title, item_local.infoLabels['episodio_titulo'])
item_local.infoLabels['episodio_titulo'] = '%s [%s] [%s]' % (item_local.infoLabels['episodio_titulo'], item_local.infoLabels['year'], rating)
else: # If there is no episode title, we will put the name of the series
item_local.title = '%s %s' % (item_local.title, item_local.contentSerieName)
item_local.infoLabels['episodio_titulo'] = '%s [%s] [%s]' % (item_local.contentSerieName, item_local.infoLabels['year'], rating)
# We compose the final title, although with Unify you will use infoLabels ['episode_title']
item_local.infoLabels['title'] = item_local.infoLabels['episodio_titulo']
item_local.title = item_local.title.replace("[", "-").replace("]", "-")
item_local.title = '%s [%s] [%s] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (item_local.title, item_local.infoLabels['year'], rating, item_local.quality, str(item_local.language))
# We remove empty fields
item_local.infoLabels['episodio_titulo'] = item_local.infoLabels['episodio_titulo'].replace("[]", "").strip()
item_local.infoLabels['title'] = item_local.infoLabels['title'].replace("[]", "").strip()
item_local.title = item_local.title.replace("[]", "").strip()
item_local.title = re.sub(r'\s?\[COLOR \w+\]\[\[?-?\s?\]?\]\[\/COLOR\]', '', item_local.title).strip()
item_local.title = re.sub(r'\s?\[COLOR \w+\]-?\s?\[\/COLOR\]', '', item_local.title).strip()
item_local.title = item_local.title.replace(".", ",").replace("GB", "G B").replace("Gb", "G b").replace("gb", "g b").replace("MB", "M B").replace("Mb", "M b").replace("mb", "m b")
# If the information of num. total episodes of TMDB is not correct, we try to calculate it
if num_episodios < item_local.contentEpisodeNumber:
num_episodios = item_local.contentEpisodeNumber
if num_episodios > item_local.contentEpisodeNumber:
item_local.infoLabels['temporada_num_episodios'] = num_episodios
num_episodios_flag = False
if num_episodios and not item_local.infoLabels['temporada_num_episodios']:
item_local.infoLabels['temporada_num_episodios'] = num_episodios
num_episodios_flag = False
try:
num_episodios_lista[item_local.contentSeason] = num_episodios
except:
logger.error(traceback.format_exc())
#logger.debug("title: " + item_local.title + " / url: " + item_local.url + " / calidad: " + item_local.quality + " / Season: " + str(item_local.contentSeason) + " / EpisodeNumber: " + str(item_local.contentEpisodeNumber) + " / num_episodios_lista: " + str(num_episodios_lista) + str(num_episodios_flag))
#logger.debug(item_local)
# If you are updating video library of a NewPct1 series, we restore the channel with the name of the clone
if item.channel == channel_py and (item.library_playcounts or item.add_videolibrary):
item.channel = scrapertools.find_single_match(item.url, r'http.?\:\/\/(?:www.)?(\w+)\.\w+\/')
# After reviewing each episode, we close with the footer
# First we update all episodes with their maximum number of episodes per season
try:
if not num_episodios_flag: # If the number of episodes is not reported, we update episodes of the entire series
for item_local in itemlist:
item_local.infoLabels['temporada_num_episodios'] = int(num_episodios_lista[item_local.contentSeason])
except:
logger.error("ERROR 07: EPISODES: Season number out of range" + " / SEASON: " + str(item_local.contentSeason) + " / " + str(item_local.contentEpisodeNumber) + " / MAX_SEASONS: " + str(num_temporada_max) + " / SEASON_LIST: " + str(num_episodios_lista))
logger.error(traceback.format_exc())
# We allow the updating of titles, either for immediate use, or to add to the video library
itemlist.append(item.clone(title="** Update Titles - video library preview **", action="actualizar_titulos", tmdb_stat=False, from_action=item.action, from_title_tmdb=item.title, from_update=True))
# Delete num. Season if you do not come from the Add to Video Library menu and you are not updating the Video Library
if not item.library_playcounts: # if you are not updating the Video Library
if modo_serie_temp != '': # and can change to series-season
if item.contentSeason and not item.add_menu:
del item.infoLabels['season'] # The decision to put it or not is made in the menu area
# We put the title of Add to the Video Library, with the no. of episodes from the last season and the status of the Series
if config.get_videolibrary_support() and len(itemlist) > 1:
item_local = itemlist[-2]
title = ''
if item_local.infoLabels['temporada_num_episodios']:
title += ' [Temp. de %s ep.]' % item_local.infoLabels['temporada_num_episodios']
if item_local.infoLabels['status'] and item_local.infoLabels['status'].lower() == "ended":
title += ' [TERMINADA]'
if item_local.quality: #L The Video Library does not take the quality of the episode, but of the series. I put of the episode
item.quality = item_local.quality
if modo_serie_temp != '':
# We are in a channel that can select between managing complete Series or by Season
# It will have a line to Add the complete Series and another to Add only the current Season
if item.action == 'get_seasons': # if it is update from video library, standard title
# If there is a new Season, it is activated as the current one
if item.library_urls[item.channel] != item.url and (item.contentType == "season" or modo_ultima_temp):
item.library_urls[item.channel] = item.url # The url is updated pointing to the last Season
try:
from core import videolibrarytools # Update url in .nfo is forced
itemlist_fake = [] # An empty Itemlist is created to update only the .nfo
videolibrarytools.save_tvshow(item, itemlist_fake) # The .nfo is updated
except:
logger.error("ERROR 08: EPISODES: Unable to update the URL to the new Season")
logger.error(traceback.format_exc())
itemlist.append(item.clone(title="[COLOR yellow]Add this Series to Video Library-[/COLOR]" + title, action="add_serie_to_library"))
elif modo_serie_temp == 1: # if it is Series we give the option to save the last season or the complete series
itemlist.append(item.clone(title="[COLOR yellow]Add last Temp. to Video Library-[/COLOR]" + title, action="add_serie_to_library", contentType="season", contentSeason=contentSeason, url=item_local.url, add_menu=True))
itemlist.append(item.clone(title="[COLOR yellow]Add this Series to Video Library-[/COLOR]" + title, action="add_serie_to_library", contentType="tvshow", add_menu=True))
else: # if not, we give the option to save the current season or the complete series
itemlist.append(item.clone(title="[COLOR yellow]Add this Series to Video Library-[/COLOR]" + title, action="add_serie_to_library", contentType="tvshow", add_menu=True))
if item.add_videolibrary and not item.add_menu:
item.contentSeason = contentSeason
itemlist.append(item.clone(title="[COLOR yellow]Aadd this Temp. to Video Library-[/COLOR]" + title, action="add_serie_to_library", contentType="season", contentSeason=contentSeason, add_menu=True))
else: # It is a standard channel, just a line of Add to Video Library
itemlist.append(item.clone(title="[COLOR yellow]Add this series to video library-[/COLOR]" + title, action="add_serie_to_library", extra="episodios", add_menu=True))
# If judicial intervention, I warn !!!
if item.intervencion:
for clone_inter, autoridad in item.intervencion:
thumb_intervenido = get_thumb(autoridad)
itemlist_fo.append(item.clone(action='', title="[COLOR yellow]" + clone_inter.capitalize() + ': [/COLOR]' + intervenido_judicial + '. Report the problem in the forum', thumbnail=thumb_intervenido))
del item.intervencion
# If there has been a fail-over, I will comment
if channel_alt:
itemlist_fo.append(item.clone(action='', title="[COLOR yellow]" + channel_alt.capitalize() + '[/COLOR] [ALT ] In use'))
itemlist_fo.append(item.clone(action='', title="[COLOR yellow]" + item.category.capitalize() + '[/COLOR] Inaccessible'))
if len(itemlist_fo) > 0:
itemlist = itemlist_fo + itemlist
if item.add_videolibrary: # We are Adding to the Video Library.
del item.add_videolibrary # We already delete the indicator
if item.add_menu: # Option that warns if it has been added to the Video Library
del item.add_menu # from the Episodes page or from the Contextual Menu
# logger.debug(item)
return (item, itemlist)
def post_tmdb_findvideos(item, itemlist):
logger.debug()
"""
Call to create a pseudo title with all the relevant data from the video.
InfoLabel takes all the data of interest and places them in different variables, mainly the title. Keep track of the num. of episodes per season
The call to the method from Findvideos, at the beginning, is:
from lib import generictools
item, itemlist = generictools.post_tmdb_findvideos (item, itemlist)
In Itemlist it returns an Item with the pseudo title. There the channel will add the rest.
"""
# logger.debug(item)
# Know if we are in a popup window launched from a bullet in the main menu,
# with the function "play_from_library"
item.unify = False
Window_IsMedia = False
try:
import xbmc
if xbmc.getCondVisibility('Window.IsMedia') == 1:
Window_IsMedia = True
item.unify = config.get_setting("unify")
except:
item.unify = config.get_setting("unify")
logger.error(traceback.format_exc())
if item.contentSeason_save: # We restore the num. seasonal
item.contentSeason = item.contentSeason_save
del item.contentSeason_save
if item.library_filter_show:
del item.library_filter_show
# We save the information of max num. of episodes per season after TMDB
num_episodios = item.contentEpisodeNumber
if item.infoLabels['temporada_num_episodios'] and item.contentEpisodeNumber <= item.infoLabels['temporada_num_episodios']:
num_episodios = item.infoLabels['temporada_num_episodios']
# Get updated video information. In a second TMDB reading it gives more information than in the first
#if not item.infoLabels['tmdb_id'] or (not item.infoLabels['episodio_titulo'] and item.contentType == 'episode'):
# tmdb.set_infoLabels(item, True)
#elif (not item.infoLabels['tvdb_id'] and item.contentType == 'episode') or item.contentChannel == "videolibrary":
# tmdb.set_infoLabels(item, True)
try:
tmdb.set_infoLabels(item, True) # TMDB of each Temp
except:
logger.error(traceback.format_exc())
# We restore the information of max num. of episodes per season after TMDB
try:
if item.infoLabels['temporada_num_episodios']:
if int(num_episodios) > int(item.infoLabels['temporada_num_episodios']):
item.infoLabels['temporada_num_episodios'] = num_episodios
else:
item.infoLabels['temporada_num_episodios'] = num_episodios
except:
logger.error(traceback.format_exc())
# We adjust the category name
if item.channel == channel_py:
category = scrapertools.find_single_match(item.url, r'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize()
if category:
item.category = category
if item.armagedon: #Es una situación catastrófica?
itemlist.append(item.clone(action='', title=item.category + ': [COLOR hotpink]Using emergency links[/COLOR]'))
# We remove the category or title name, if you have it
if item.contentTitle:
item.contentTitle = re.sub(r' -%s-' % item.category, '', item.contentTitle)
item.title = re.sub(r' -%s-' % item.category, '', item.title)
# We clean up the year and episode ratings
if item.infoLabels['episodio_titulo']:
item.infoLabels['episodio_titulo'] = re.sub(r'\s?\[.*?\]', '', item.infoLabels['episodio_titulo'])
item.infoLabels['episodio_titulo'] = re.sub(r'\s?\(.*?\)', '', item.infoLabels['episodio_titulo'])
item.infoLabels['episodio_titulo'] = item.infoLabels['episodio_titulo'].replace(item.contentSerieName, '')
if item.infoLabels['aired'] and item.contentType == "episode":
item.infoLabels['year'] = scrapertools.find_single_match(str(item.infoLabels['aired']), r'\/(\d{4})')
rating = '' # We put the rating
try:
if item.infoLabels['rating'] and item.infoLabels['rating'] != 0.0:
rating = float(item.infoLabels['rating'])
rating = round(rating, 1)
if rating == 0.0:
rating = ''
except:
logger.error(traceback.format_exc())
if item.quality.lower() in ['gb', 'mb']:
item.quality = item.quality.replace('GB', 'G B').replace('Gb', 'G b').replace('MB', 'M B').replace('Mb', 'M b')
# I'm looking for "duration" in infoLabels
tiempo = 0
if item.infoLabels['duration']:
try:
if config.get_platform(True)['num_version'] < 18 or not Window_IsMedia:
tiempo = item.infoLabels['duration']
elif xbmc.getCondVisibility('Window.IsMedia') == 1:
item.quality = re.sub(r'\s?\[\d+:\d+\ h]', '', item.quality)
else:
tiempo = item.infoLabels['duration']
except:
tiempo = item.infoLabels['duration']
logger.error(traceback.format_exc())
elif item.contentChannel == 'videolibrary': # No, does it come from the Video Library? we look in the DB
# I read from the Kodi BD the length of the movie or episode. In "from_fields" you can put the columns you want
nun_records = 0
try:
if item.contentType == 'movie':
nun_records, records = get_field_from_kodi_DB(item, from_fields='c11') # Leo from BD Kodi movie length
else:
nun_records, records = get_field_from_kodi_DB(item, from_fields='c09') # Leo from BD Kodi episode length
except:
logger.error(traceback.format_exc())
if nun_records > 0: # Are there records?
# It is an array, I look for the record field: add in the FOR a fieldX for a new column
for strFileName, field1 in records:
tiempo = field1
try: # we calculate the time in hh: mm
tiempo_final = int(tiempo) # I convert it to int, but it can be null
if tiempo_final > 0: # If the time is 0, we pass
if tiempo_final > 700: # If it's in seconds
tiempo_final = tiempo_final / 60 # I transform it into minutes
horas = tiempo_final / 60 # I transform it into hours
resto = tiempo_final - (horas * 60) # I keep the remaining minutes of the hour
if not scrapertools.find_single_match(item.quality, r'(\[\d+:\d+)'): # if it already has the duration, we pass
item.quality += ' [/COLOR][COLOR white][%s:%s h]' % (str(horas).zfill(2), str(resto).zfill(2)) # I add it to Server Quality
except:
logger.error(traceback.format_exc())
# We adjust the category name
if item.channel != channel_py:
item.category = item.channel.capitalize()
# We specially format the title for an episode
title = ''
title_gen = ''
if item.contentType == "episode": # Series
title = '%sx%s' % (str(item.contentSeason), str(item.contentEpisodeNumber).zfill(2)) # Season and Episode
if item.infoLabels['temporada_num_episodios']:
title = '%s (de %s)' % (title, str(item.infoLabels['temporada_num_episodios'])) # Total Episodes
# If they are multiple episodes, and it comes from Video Library, we put series name
if (" al " in item.title or " Al " in item.title) and not "al " in item.infoLabels['episodio_titulo']:
title = '%s al %s - ' % (title, scrapertools.find_single_match(item.title, r'[al|Al] (\d+)'))
else:
title = '%s %s' % (title, item.infoLabels['episodio_titulo']) # Title Episode
title_gen = '%s, ' % title
if item.contentType == "episode" or item.contentType == "season": # Series or Seasons
title_gen += '%s [COLOR yellow][%s][/COLOR] [%s] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR] [%s]' % (item.contentSerieName, item.infoLabels['year'], rating, item.quality, str(item.language), scrapertools.find_single_match(item.title, r'\s\[(\d+,?\d*?\s\w[b|B])\]')) # Rating, Quality, Language, Size
if item.infoLabels['status'] and item.infoLabels['status'].lower() == "ended":
title_gen = '[TERM.] %s' % title_gen # It marks when the Series is finished and there will be no more production
item.title = title_gen
else: # Films
title = item.title
title_gen = item.title
# We clean empty labels
title_gen = re.sub(r'\s?\[COLOR \w+\]\[\[?\s?\]?\]\[\/COLOR\]', '', title_gen).strip() # We remove empty labels
title_gen = re.sub(r'\s?\[COLOR \w+\]\s?\[\/COLOR\]', '', title_gen).strip() # We remove empty colors
title_gen = title_gen.replace(" []", "").strip() # We remove empty labels
title_videoteca = title_gen # We save the title for Video Library
if not item.unify: # If Smart Titles NOT selected:
title_gen = '**- [COLOR gold]Enlaces Ver: [/COLOR]%s[COLOR gold] -**[/COLOR]' % (title_gen)
else: # If Smart Titles YES selected:
title_gen = '[COLOR gold]Enlaces Ver: [/COLOR]%s' % (title_gen)
if item.channel_alt:
title_gen = '[COLOR yellow]%s [/COLOR][ALT]: %s' % (item.category.capitalize(), title_gen)
# elif (config.get_setting("quit_channel_name", "videolibrary") == 1 or item.channel == channel_py) and item.contentChannel == "videolibrary":
else:
title_gen = '[COLOR white]%s: %s' % (item.category.capitalize(), title_gen)
# If judicial intervention, I warn !!!
if item.intervencion:
for clone_inter, autoridad in item.intervencion:
thumb_intervenido = get_thumb(autoridad)
itemlist.append(item.clone(action='', title="[COLOR yellow]" + clone_inter.capitalize() + ': [/COLOR]' + intervenido_judicial + '. Reportar el problema en el foro', thumbnail=thumb_intervenido))
del item.intervencion
# We paint the pseudo-title with all the information available from the video
itemlist.append(item.clone(action="", server = "", title=title_gen)) # Title with all the data of the video
if item.action == 'show_result': # Comes from a global search
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)
# we added the option to Add to Video Library for movies (no series)
if (item.contentType == 'movie' or item.contentType == 'season') and item.contentChannel != "videolibrary":
# We allow the updating of titles, either for immediate use, or to add to the video library
itemlist.append(item.clone(title="** [COLOR yelow]Actualizar Títulos - vista previa videoteca[/COLOR] **", action="actualizar_titulos", extra="peliculas", tmdb_stat=False, from_action=item.action, from_title_tmdb=item.title, from_update=True))
if item.contentType == 'movie' and item.contentChannel != "videolibrary":
itemlist.append(item.clone(title="**-[COLOR yellow] Añadir a la videoteca [/COLOR]-**", action="add_pelicula_to_library", extra="peliculas", from_action=item.action, from_title_tmdb=item.title))
# We added the option to watch trailers
if item.contentChannel != "videolibrary":
itemlist.append(item.clone(channel="trailertools", title="**-[COLOR magenta] Buscar Trailer [/COLOR]-**", action="buscartrailer", context=""))
# logger.debug(item)
return (item, itemlist)
def get_field_from_kodi_DB(item, from_fields='*', files='file'):
logger.debug()
"""
Call to read from the Kodi DB the input fields received (from_fields, by default "*") of the video indicated in Item
Obviously this only works with Kodi and if the movie or series is listed in the Alpha and Kodi Video Libraries.
You can request that the search be done by files (default), or by folder (series)
The call is:
nun_records, records = generictools.get_field_from_kodi_DB (item, from_fields = 'cXX [, cYY, ...]' [, files = 'file | folder'])
Returns the num of records found and the records. It is important for the caller to verify that "nun_records> 0" before processing "records"
"""
FOLDER_MOVIES = config.get_setting("folder_movies")
FOLDER_TVSHOWS = config.get_setting("folder_tvshows")
VIDEOLIBRARY_PATH = config.get_videolibrary_config_path()
VIDEOLIBRARY_REAL_PATH = config.get_videolibrary_path()
if item.contentType == 'movie': # I add the folder corresponding to the path of the Video Library
path = filetools.join(VIDEOLIBRARY_REAL_PATH, FOLDER_MOVIES)
path2 = filetools.join(VIDEOLIBRARY_PATH, FOLDER_MOVIES)
folder = FOLDER_MOVIES
else:
path = filetools.join(VIDEOLIBRARY_REAL_PATH, FOLDER_TVSHOWS)
path2 = filetools.join(VIDEOLIBRARY_PATH, FOLDER_TVSHOWS)
folder = FOLDER_TVSHOWS
raiz, carpetas, ficheros = filetools.walk(path).next() # ready the series or movies in the Video Library
carpetas = [filetools.join(path, f) for f in carpetas] # I add the content folder to the path
for carpeta in carpetas: # I search the selected content in the folder list
if item.contentType == 'movie' and (item.contentTitle.lower() in carpeta or item.contentTitle in carpeta): # Films?
path = carpeta # We store the folder in the path
break
elif item.contentType in ['tvshow', 'season', 'episode'] and (item.contentSerieName.lower() in carpeta or item.contentSerieName in carpeta): # Series?
path = carpeta #Almacenamos la carpeta en el path
break
path2 += '/%s/' % scrapertools.find_single_match(path, r'%s.(.*?\s\[.*?\])' % folder) # We add the Series or Movies folder, Android format
file_search = '%' # By default it looks for all the files in the folder
if files == 'file': # If a file is requested (default), it is searched
if item.contentType == 'episode': # If it is an episode, put the name, if not leave%
file_search = '%sx%s.strm' % (item.contentSeason, str(item.contentEpisodeNumber).zfill(2)) # Name for episodes
if "\\" in path: # We adjust the / depending on the platform
path = path.replace("/", "\\")
path += "\\" # We end the path with a /
else:
path += "/"
if FOLDER_TVSHOWS in path: # I check if it is CINEMA or SERIES
contentType = "episode_view" # I mark the Kodi Video BBDD table
else:
contentType = "movie_view" # I mark the Kodi Video BBDD table
path1 = path.replace("\\\\", "\\") # for SQL I just need the folder
path2 = path2.replace("\\", "/") # Format no Windows
# Let's execute the SQL statement
if not from_fields:
from_fields = '*'
else:
from_fields = 'strFileName, %s' % from_fields # at least two fields, because one only generates strange things
sql = 'select %s from %s where (strPath like "%s" or strPath like "%s") and strFileName like "%s"' % (from_fields, contentType, path1, path2, file_search)
nun_records = 0
records = None
try:
if config.is_xbmc():
from platformcode import xbmc_videolibrary
nun_records, records = xbmc_videolibrary.execute_sql_kodi(sql) # SQL execution
if nun_records == 0: # is there an error?
logger.error("SQL error: " + sql + ": 0 records") # It will not be listed or there is an error in the SQL
except:
logger.error(traceback.format_exc())
return (nun_records, records)
def fail_over_newpct1(item, patron, patron2=None, timeout=None):
logger.debug()
import ast
"""
Call to find an alternative website to a downed channel, clone of NewPct1
We create an array with the data of the alternative channels. The tuple data is:
- active = 0.1 Indicates if the channel is not active or if it is
- channel name of the alternative channel
- channel_host host of the alternative channel, used to replace part of the url
- contentType indicates what type of content the new channel supports in fail-overs
- action_excluded lists the actions that are excluded for that channel
The method call from the beginning of Submenu, Search_List, Episodes and Findvideos, is:
from lib import generictools
item, data = generictools.fail_over_newpct1 (item, pattern [, pattern2 =] [, timeout =])
- Entry: pattern: with this pattern it is possible to verify if the data of the new website is good
- Input (optional): pattern 2: optional second pattern
- Entry (optional): timeout: maximum wait value in page download. Default 3
- Input (optional): pattern = True: asks to only verify if the channel in use is active, if not, offers another
- Output: data: returns the data of the new website. If it returns empty it is that no alternative was found
"""
# logger.debug(item)
if timeout == None:
timeout = config.get_setting('clonenewpct1_timeout_downloadpage', channel_py) # Timeout downloadpage
if timeout == 0: timeout = None
if item.action == "search" or item.action == "listado_busqueda": timeout = timeout * 2 # More time for searches
data = ''
channel_failed = ''
url_alt = []
item.category = scrapertools.find_single_match(item.url, r'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize()
if not item.extra2:
item.extra2 = 'z9z8z7z6z5'
patron_alt = ''
verify_torrent = ''
if patron is not True and '|' in patron: # We check if there are two alternative patterns
try:
verify_torrent, patron1, patron_alt = patron.split('|') # If so, we separate them and treat them
patron = patron1
except:
logger.error(traceback.format_exc())
# Array with the data of the alternative channels
# We load in .json of the channel to see the lists of values in settings
fail_over = channeltools.get_channel_json(channel_py)
for settings in fail_over['settings']: # All settings are scrolled
if settings['id'] == "clonenewpct1_channels_list": # We found in setting
fail_over = settings['default'] # Load list of clones
break
fail_over_list = ast.literal_eval(fail_over)
# logger.debug(str(fail_over_list))
if item.from_channel and item.from_channel != 'videolibrary': #Desde search puede venir con el nombre de canal equivocado
item.channel = item.from_channel
# We walk the Array identifying the channel that fails
for active, channel, channel_host, contentType, action_excluded in fail_over_list:
if item.channel == channel_py:
if channel != item.category.lower(): # is the channel / category failing?
continue
else:
if channel != item.channel: # is the channel failing?
continue
channel_failed = channel # we save the name of the channel or category
channel_host_failed = channel_host # we save the hostname
channel_url_failed = item.url # we save the url
#logger.debug(channel_failed + ' / ' + channel_host_failed)
if patron == True and active == '1': # we have only been asked to verify the clone
return (item, data) # we leave, with the same clone, if it is active
if (item.action == 'episodios' or item.action == "update_tvshow" or item.action == "get_seasons" or item.action == 'findvideos') and item.contentType not in contentType: # supports fail_over of this content?
logger.error("ERROR 99: " + item.action.upper() + ": Unsupported Action for Channel Fail-Over: " + item.url)
return (item, data) # does not support fail_over of this content, we can not do anything
break
if not channel_failed:
logger.error('Pattern: ' + str(patron) + ' / fail_over_list: ' + str(fail_over_list))
logger.error(item)
return (item, data) # Something has not worked, we can not do anything
# We go through the Array identifying active channels that work, other than the fallen one, that support the content
for active, channel, channel_host, contentType, action_excluded in fail_over_list:
data_alt = ''
if channel == channel_failed or active == '0' or item.action in action_excluded or item.extra2 in action_excluded: # is the new channel valid?
continue
if (item.action == 'episodios' or item.action == "update_tvshow" or item.action == "get_seasons" or item.action == 'findvideos') and item.contentType not in contentType: # does it support content?
continue
# We make the channel and url name change, keeping the previous ones as ALT
item.channel_alt = channel_failed
if item.channel != channel_py:
item.channel = channel
item.category = channel.capitalize()
item.url_alt = channel_url_failed
item.url = channel_url_failed
channel_host_bis = re.sub(r'(?i)http.*://', '', channel_host)
channel_host_failed_bis = re.sub(r'(?i)http.*://', '', channel_host_failed)
item.url = item.url.replace(channel_host_failed_bis, channel_host_bis)
url_alt += [item.url] # we save the url for the loop
item.channel_host = channel_host
# logger.debug(str(url_alt))
# We remove the series code, because it can vary between websites
if item.action == "episodios" or item.action == "get_seasons" or item.action == "update_tvshow":
item.url = re.sub(r'\/\d+\/?$', '', item.url) # it seems that with the title only finds the series, usually ...
url_alt = [item.url] # we save the url for the loop, but for now we ignore the initial with serial code
# if it is an episode, we generalize the url so that it can be found in another clone. We remove the quality from the end of the url
elif item.action == "findvideos" and item.contentType == "episode":
try:
# We remove the 0 to the left of the episode. Some clones do not accept it
inter1, inter2, inter3 = scrapertools.find_single_match(item.url, r'(http.*?\/temporada-\d+.*?\/capitulo.?-)(\d+)(.*?\/)')
inter2 = re.sub(r'^0', '', inter2)
if inter1 + inter2 + inter3 not in url_alt:
url_alt += [inter1 + inter2 + inter3]
# in this format we only remove the quality from the end of the url
if scrapertools.find_single_match(item.url, r'http.*?\/temporada-\d+.*?\/capitulo.?-\d+.*?\/') not in url_alt:
url_alt += [scrapertools.find_single_match(item.url, r'http.*?\/temporada-\d+.*?\/capitulo.?-\d+.*?\/')]
except:
logger.error("ERROR 88: " + item.action + ": Error converting url: " + item.url)
logger.error(traceback.format_exc())
logger.debug('Converted URLs: ' + str(url_alt))
if patron == True: # we have only been asked to verify the clone
return (item, data) # we leave, with a new clone
# We read the new url .. There may be several alternatives to the original url
for url in url_alt:
try:
if item.post:
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(url, post=item.post, timeout=timeout).data)
else:
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(url, timeout=timeout).data)
data_comillas = data.replace("'", "\"")
except:
data = ''
logger.error(traceback.format_exc())
if not data: # no luck, we try the following url
logger.error("ERROR 01: " + item.action + ": The Web does not respond or the URL is wrong: " + url)
continue
# We have managed to read the web, we validate if we find a valid link in this structure
# Avoid misleading pages that can put the channel in an infinite loop
if (not ".com/images/no_imagen.jpg" in data and not ".com/images/imagen-no-disponible.jpg" in data) or item.action != "episodios":
if patron:
data_alt = scrapertools.find_single_match(data, patron)
if not data_alt:
data_alt = scrapertools.find_single_match(data_comillas, patron)
if data_alt and patron_alt:
data_alt = scrapertools.find_single_match(data, patron_alt)
if not data_alt and patron_alt:
data_alt = scrapertools.find_single_match(data_comillas, patron_alt)
if patron2 != None:
data_alt = scrapertools.find_single_match(data_alt, patron2)
if not data_alt: # no luck, we tried the next channel
logger.error("ERROR 02: " + item.action + ": The structure of the Web has changed: " + url + " / Patron: " + patron + " / " +patron_alt)
web_intervenida(item, data)
data = ''
continue
else:
logger.error("ERROR 02: " + item.action + ": The structure of the Web has changed: " + url + " / Patron: " + patron + " / " +patron_alt)
web_intervenida(item, data)
data = ''
continue
if not data: # no luck, we tried the following clone
url_alt = []
continue
else:
break
del item.extra2 # We delete exclusive temporary action
if not data: # If you have not found anything, we leave cleaning variables
if item.channel == channel_py:
if item.channel_alt:
item.category = item.channel_alt.capitalize()
del item.channel_alt
else:
if item.channel_alt:
item.channel = item.channel_alt
del item.channel_alt
if item.url_alt:
item.url = item.url_alt
del item.url_alt
item.channel_host = channel_host_failed
# logger.debug(item)
return (item, data)
def web_intervenida(item, data, desactivar=True):
logger.debug()
"""
Call to verify if the crash of a Newpct1 clone is due to judicial intervention
The method call from is:
from lib import generictools
item = generictools.web_intervened (item, data [, disable = True])
- Entry: data: result of the download. It allows us to analyze if it is an intervention
- Input: disable = True: indicates that you disable the channel or clone in case of judicial intervention
- Output: item.intervention: return an array with the name of the intervened clone and the thumb of the intervening authority. The channel can announce it.
- Output: If it is a clone of Newpct1, the clone is disabled in the Channel's .json. If it's another channel, the channel in your .json is disabled.
"""
intervencion = ()
judicial = ''
# We verify that it is a judicial intervention
if intervenido_policia in data or intervenido_guardia in data or intervenido_sucuri in data:
if intervenido_guardia in data:
judicial = 'intervenido_gc.png' # thumb of the Benemérita
if intervenido_policia in data:
judicial = 'intervenido_pn.jpeg' # thumb of the National Police
if intervenido_sucuri in data:
judicial = 'intervenido_sucuri.png' # thumb of Juices
category = item.category
if not item.category:
category = item.channel
intervencion = (category, judicial) # We keep the channel / category name and the judicial thumb
if not item.intervencion:
item.intervencion = [] # If the array does not exist, we create it
item.intervencion += [intervencion] # We add this intervention to the array
logger.error("ERROR 99: " + category + ": " + judicial + ": " + item.url + ": DISABLED=" + str(desactivar) + " / DATA: " + data)
if desactivar == False: # If we don't want to disable the channel, we go
return item
# We load in .json of the channel to see the lists of values in settings. Load the cluttered keys !!!
from core import filetools
import json
json_data = channeltools.get_channel_json(item.channel)
if item.channel == channel_py: # If it's a clone of Newpct1, we disable it
for settings in json_data['settings']: # All settings are scrolled
if settings['id'] == "clonenewpct1_channels_list": # We found in setting
action_excluded = scrapertools.find_single_match(settings['default'], r"\('\d', '%s', '[^']+', '[^']*', '([^']*)'\)" % item.category.lower()) #extraemos el valor de action_excluded
if action_excluded:
if "intervenido" not in action_excluded:
action_excluded += ', %s' % judicial # We add the thumb of the judicial authority
else:
action_excluded = '%s' % judicial
# We replace the status to disabled and add the thumb of the judicial authority
settings['default'] = re.sub(r"\('\d', '%s', ('[^']+', '[^']*'), '[^']*'\)" % item.category.lower(), r"('0', '%s', \1, '%s')" % (item.category.lower(), action_excluded), settings['default'])
break
else:
# json_data['active'] = False # Channel is disabled
json_data['thumbnail'] = ', thumb_%s' % judicial # We keep the thumb of the judicial authority
# We save the changes made in the .json
try:
if item.channel != channel_py:
disabled = config.set_setting('enabled', False, item.channel) # We deactivate the channel
disabled = config.set_setting('include_in_global_search', False, item.channel) # We get it out of global searches
channel_path = filetools.join(config.get_runtime_path(), "channels", item.channel + ".json")
with open(channel_path, 'w') as outfile: # We record the updated .json
json.dump(json_data, outfile, sort_keys = True, indent = 2, ensure_ascii = False)
except:
logger.error("ERROR 98 when saving the file: %s" % channel_path)
logger.error(traceback.format_exc())
# logger.debug(item)
return item
def regenerate_clones():
logger.debug()
import json
from core import videolibrarytools
"""
Regenerate .json files that have been crushed with migration. Also delete tvshow.nfo files in films.
Temporary and controlled use method
"""
try:
# Find the paths where to leave the control .json file, and the Video Library
json_path = filetools.exists(filetools.join(config.get_runtime_path(), 'verify_cached_torrents.json'))
if json_path:
logger.debug('Previously repaired video library: WE ARE GOING')
return False
json_path = filetools.join(config.get_runtime_path(), 'verify_cached_torrents.json')
filetools.write(json_path, json.dumps({"CINE_verify": True})) # Prevents another simultaneous process from being launched
json_error_path = filetools.join(config.get_runtime_path(), 'error_cached_torrents.json')
json_error_path_BK = filetools.join(config.get_runtime_path(), 'error_cached_torrents_BK.json')
videolibrary_path = config.get_videolibrary_path() # We calculate the absolute path from the Video Library
movies = config.get_setting("folder_movies")
series = config.get_setting("folder_tvshows")
torrents_movies = filetools.join(videolibrary_path, config.get_setting("folder_movies")) # path of CINE
torrents_series = filetools.join(videolibrary_path, config.get_setting("folder_tvshows")) # path the SERIES
# We load in .json from Newpct1 to see the lists of values in settings
fail_over_list = channeltools.get_channel_json(channel_py)
for settings in fail_over_list['settings']: # All settings are scrolled
if settings['id'] == "clonenewpct1_channels_list": # We found in setting
fail_over_list = settings['default'] # Load list of clones
#Inicializa variables
torren_list = []
torren_list.append(torrents_movies)
# torren_list.append(torrents_series)
i = 0
j = 0
k = 0
descomprimidos = []
errores = []
json_data = dict()
# Browse the FILM and SERIES folders of the Video Library, reading, unzipping and rewriting the .torrent files
for contentType in torren_list:
for root, folders, files in filetools.walk(contentType):
nfo = ''
newpct1 = False
file_list = str(files)
logger.error(file_list)
# Delete the Tvshow.nfo files and check if the .nfo has more than one channel and one is clone Newpct1
for file in files:
# logger.debug('file - nfos: ' + file)
if 'tvshow.nfo' in file:
file_path = filetools.join(root, 'tvshow.nfo')
filetools.remove(file_path)
continue
if '.nfo' in file:
peli_name = file.replace('.nfo', '')
nfo = ''
try:
head_nfo, nfo = videolibrarytools.read_nfo(filetools.join(root, file))
except:
logger.error('** NFO: read error in: ' + file)
break
if not nfo:
logger.error('** NFO: read error in: ' + file)
break
if nfo.ow_force: # If you have ow_force we remove it to avoid future problems
del nfo.ow_force
try:
filetools.write(filetools.join(root, file), head_nfo + nfo.tojson()) # I update the .nfo
except:
logger.error('** NFO: typing error in: ' + file)
break
if '.torrent' not in file_list and nfo.emergency_urls:
del nfo.emergency_urls # If you have emergency_urls, we reset it
try:
filetools.write(filetools.join(root, file), head_nfo + nfo.tojson()) # I update the .nfo
except:
logger.error('** NFO: typing error in: ' + file)
break
newpct1 = True # we set to reset the .jsons
if len(nfo.library_urls) > 1: # Do you have more than one channel?
for canal, url in nfo.library_urls.items():
canal_json = "[%s].json" % canal
if canal_json not in file_list: # Zombie channel, we delete it
logger.error('pop: ' + canal)
nfo.library_urls.pop(canal, None)
if nfo.emergency_urls:
del nfo.emergency_urls # If you have emergency_urls, we reset it
try:
filetools.write(filetools.join(root, file), head_nfo + nfo.tojson()) # I update the .nfo
except:
logger.error('** NFO: typing error in: ' + file)
break
newpct1 = True # we set to reset the .jsons
canal_nwepct1 = "'%s'" % canal
if canal_nwepct1 in fail_over_list: # Some channel is clone of Newpct1
newpct1 = True # If yes, we mark it
if nfo.emergency_urls:
del nfo.emergency_urls # If you have emergency_urls, we reset it
try:
filetools.write(filetools.join(root, file), head_nfo + nfo.tojson()) # I update the .nfo
except:
logger.error('** NFO: typing error in: ' + file)
break
# Area to fill the .json files
if not newpct1:
continue
for file in files:
file_path = filetools.join(root, file)
if '.json' in file:
logger.debug('** file: ' + file)
canal_json = scrapertools.find_single_match(file, r'\[(\w+)\].json')
if canal_json not in nfo.library_urls:
filetools.remove(file_path) # we delete the .json is a zombie
item_movie = ''
try:
item_movie = Item().fromjson(filetools.read(file_path)) # we read the .json
except:
logger.error('** JSON: read error in: ' + file)
continue
if not item_movie:
logger.error('** JSON: read error in: ' + file)
continue
if item_movie.emergency_urls: del item_movie.emergency_urls
item_movie.channel = canal_json # channel name
item_movie.category = canal_json.capitalize() # category
item_movie.url = nfo.library_urls[canal_json] # url
if scrapertools.find_single_match(item_movie.title, r'(.*?)\[\d+.\d+\s*.\s*B\]'):
item_movie.title = scrapertools.find_single_match(item_movie.title, r'(.*?)\[\d+.\d+\s*.\s*B\]').strip() # we remove Size
if item_movie.added_replacing: del item_movie.added_replacing # remove trace from the replaced channel
try:
filetools.write(file_path, item_movie.tojson()) # We save the new .json from the movie
except:
logger.error('** JSON: typing error in: ' + file)
else:
errores += [file]
if '.torrent' in file:
filetools.remove(file_path) # we delete the saved .torrent
logger.error('** List of movies repaireds: ' + str(errores))
filetools.write(json_error_path, json.dumps(json_data))
filetools.write(json_error_path_BK, json.dumps(json_data))
filetools.write(json_path, json.dumps({"CINE_verify": True}))
except:
filetools.remove(json_path) # we delete the lock so that it can be launched again
logger.error('CINEMA Video Library REPAIR process error')
logger.error(traceback.format_exc())
return True
def dejuice(data):
logger.debug()
# Method to unobtrusive JuicyCodes data
import base64
from lib import jsunpack
juiced = scrapertools.find_single_match(data, r'JuicyCodes.Run\((.*?)\);')
b64_data = juiced.replace('+', '').replace('"', '')
b64_decode = base64.b64decode(b64_data)
dejuiced = jsunpack.unpack(b64_decode)
return dejuiced
def privatedecrypt(url, headers=None):
data = httptools.downloadpage(url, headers=headers, follow_redirects=False).data
data = re.sub(r'\n|\r|\t|&nbsp;|<br>|\s{2,}', "", data)
packed = scrapertools.find_single_match(data, r'(eval\(.*?);var')
unpacked = jsunpack.unpack(packed)
server = scrapertools.find_single_match(unpacked, r"src:.'(http://\D+)/")
id = scrapertools.find_single_match(unpacked, r"src:.'http://\D+/.*?description:.'(.*?).'")
if server == '':
if 'powvideo' in unpacked:
id = scrapertools.find_single_match(unpacked, ",description:.'(.*?).'")
server = 'https://powvideo.net'
if server != '' and id != '':
url = '%s/%s' % (server, id)
else:
url = ''
return url