2554 lines
151 KiB
Python
2554 lines
151 KiB
Python
# -*- 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.info()
|
||
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.info()
|
||
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
|
||
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.info()
|
||
|
||
"""
|
||
#### 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.info()
|
||
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, '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("*** TMDB-ID erroneo, reseteamos y reintentamos ***")
|
||
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, '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, '-(\d+)x')
|
||
if not item_local.contentSeason:
|
||
item_local.contentSeason = scrapertools.find_single_match(item_local.url, '-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, '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.info()
|
||
|
||
"""
|
||
|
||
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.info()
|
||
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, '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: EPISODIOS: Num. de Temporada fuera de rango " + " / TEMPORADA: " + str(item_local.contentSeason) + " / " + str(item_local.contentEpisodeNumber) + " / MAX_TEMPORADAS: " + str(item_local.infoLabels['number_of_seasons']) + " / LISTA_TEMPORADAS: " + 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: EPISODIOS: Num. de Temporada fuera de rango " + " / TEMPORADA: " + str(item_local.contentSeason) + " / " + str(item_local.contentEpisodeNumber) + " / MAX_TEMPORADAS: " + str(num_temporada_max) + " / LISTA_TEMPORADAS: " + 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, '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: EPISODIOS: Num de Temporada fuera de rango " + " / TEMPORADA: " + str(item_local.contentSeason) + " / " + str(item_local.contentEpisodeNumber) + " / MAX_TEMPORADAS: " + str(num_temporada_max) + " / LISTA_TEMPORADAS: " + 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="** [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))
|
||
|
||
# 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: EPISODIOS: No se ha podido actualizar la URL a la nueva Temporada")
|
||
logger.error(traceback.format_exc())
|
||
itemlist.append(item.clone(title="[COLOR yellow]Añadir esta Serie a Videoteca-[/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]Añadir última Temp. a Videoteca-[/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]Añadir esta Serie a Videoteca-[/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]Añadir esta Serie a Videoteca-[/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]Añadir esta Temp. a Videoteca-[/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]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 = 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.info()
|
||
|
||
"""
|
||
|
||
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]Usando enlaces de emergencia[/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, '(\[\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_torrent_size(url, referer=None, post=None, torrents_path=None, data_torrent=False, \
|
||
timeout=5, file_list=False, lookup=True, local_torr=None, headers={}, short_pad=False):
|
||
logger.info()
|
||
from servers import torrent
|
||
|
||
"""
|
||
|
||
Module extracted from the old ZenTorrent channel
|
||
|
||
Calculate the size of files containing a .torrent. Download the .torrent file in a folder,
|
||
read and decode it. If it contains multiple files, add the size of all of them
|
||
|
||
Call: generictools.get_torrent_size (url, data_torrent = False)
|
||
Entry: url: url of the .torrent file
|
||
Entry: referer: url of referer in case of call with post
|
||
Entry: post: content of the post in case of call with post
|
||
Entry: data_torrent: Flag in case you want the contents of the .torretn back
|
||
Output: size: str with the size and type of measurement (MB, GB, etc)
|
||
Output: torrent_f: dict () with the content of the .torrent (optional)
|
||
Output: files: dict () with the names of the torrent files and their size (optional)
|
||
|
||
"""
|
||
|
||
def convert_size(size):
|
||
import math
|
||
if (size == 0):
|
||
return '0B'
|
||
size_name = ("B", "KB", "M·B", "G·B", "TB", "PB", "EB", "ZB", "YB")
|
||
i = int(math.floor(math.log(size, 1024)))
|
||
p = math.pow(1024, i)
|
||
#s = round(size / p, 2)
|
||
s = round(old_div(size, p), 2)
|
||
return '%s %s' % (s, size_name[i])
|
||
|
||
def decode(text):
|
||
try:
|
||
src = tokenize(text)
|
||
if not PY3:
|
||
data = decode_item(src.next, src.next()) #Py2
|
||
else:
|
||
data = decode_item(src.__next__, next(src)) #Py3
|
||
for token in src: # look for more tokens
|
||
raise SyntaxError("trailing junk")
|
||
except (AttributeError, ValueError, StopIteration):
|
||
try:
|
||
data = data
|
||
except:
|
||
data = src
|
||
|
||
return data
|
||
|
||
def tokenize(text, match=re.compile("([idel])|(\d+):|(-?\d+)").match):
|
||
i = 0
|
||
while i < len(text):
|
||
m = match(text, i)
|
||
s = m.group(m.lastindex)
|
||
i = m.end()
|
||
if m.lastindex == 2:
|
||
yield "s"
|
||
yield text[i:i + int(s)]
|
||
i = i + int(s)
|
||
else:
|
||
yield s
|
||
|
||
def decode_item(next, token):
|
||
if token == "i":
|
||
# integer: "i" value "e"
|
||
data = int(next())
|
||
if next() != "e":
|
||
raise ValueError
|
||
elif token == "s":
|
||
# string: "s" value (virtual tokens)
|
||
data = next()
|
||
elif token == "l" or token == "d":
|
||
# container: "l" (or "d") values "e"
|
||
data = []
|
||
tok = next()
|
||
while tok != "e":
|
||
data.append(decode_item(next, tok))
|
||
tok = next()
|
||
if token == "d":
|
||
#data = dict(zip(data[0::2], data[1::2]))
|
||
data = dict(list(zip(data[0::2], data[1::2])))
|
||
else:
|
||
raise ValueError
|
||
return data
|
||
|
||
|
||
#Móludo principal
|
||
size = ''
|
||
torrent_f = ''
|
||
torrent_file = ''
|
||
files = {}
|
||
try:
|
||
#torrents_path = config.get_videolibrary_path() + '/torrents' #path para dejar el .torrent
|
||
|
||
#if not os.path.exists(torrents_path):
|
||
# os.mkdir(torrents_path) #si no está la carpeta la creamos
|
||
|
||
#urllib.URLopener.version = 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36 SE 2.X MetaSr 1.0'
|
||
#urllib.urlretrieve(url, torrents_path + "/generictools.torrent") #desacargamos el .torrent a la carpeta
|
||
#torrent_file = open(torrents_path + "/generictools.torrent", "rb").read() #leemos el .torrent
|
||
|
||
if ((url and not local_torr) or url.startswith('magnet')):
|
||
torrents_path, torrent_file = torrent.caching_torrents(url, \
|
||
referer=referer, post=post, torrents_path=torrents_path, \
|
||
timeout=timeout, lookup=lookup, data_torrent=True, headers=headers)
|
||
elif local_torr:
|
||
torrent_file = filetools.read(local_torr)
|
||
if not torrent_file:
|
||
if not lookup:
|
||
return (size, torrents_path, torrent_f, files)
|
||
elif file_list and data_torrent:
|
||
return (size, torrent_f, files)
|
||
elif file_list:
|
||
return (size, files)
|
||
elif data_torrent:
|
||
return (size, torrent_f)
|
||
return size #Si hay un error, devolvemos el "size" y "torrent" vacíos
|
||
|
||
torrent_f = decode(torrent_file) #decodificamos el .torrent
|
||
|
||
#si sólo tiene un archivo, tomamos la longitud y la convertimos a una unidad legible, si no dará error
|
||
try:
|
||
sizet = torrent_f["info"]['length']
|
||
size = convert_size(sizet)
|
||
|
||
files = torrent_f["info"].copy()
|
||
if 'path' not in files: files.update({'path': ['']})
|
||
if 'piece length' in files: del files['piece length']
|
||
if 'pieces' in files: del files['pieces']
|
||
if 'name' in files: del files['name']
|
||
files = [files]
|
||
files.append({"__name": torrent_f["info"]["name"], 'length': 0})
|
||
except:
|
||
pass
|
||
|
||
#si tiene múltiples archivos sumamos la longitud de todos
|
||
if not size:
|
||
try:
|
||
check_video = scrapertools.find_multiple_matches(str(torrent_f["info"]["files"]), "'length': (\d+).*?}")
|
||
sizet = sum([int(i) for i in check_video])
|
||
size = convert_size(sizet)
|
||
|
||
files = torrent_f["info"]["files"][:]
|
||
files.append({"__name": torrent_f["info"]["name"], 'length': 0})
|
||
|
||
except:
|
||
size = 'ERROR'
|
||
|
||
except:
|
||
size = 'ERROR'
|
||
logger.error('ERROR al buscar el tamaño de un .Torrent: ' + str(url))
|
||
logger.error(traceback.format_exc())
|
||
|
||
#try:
|
||
# os.remove(torrents_path + "/generictools.torrent") #borramos el .torrent
|
||
#except:
|
||
# pass
|
||
|
||
if '.rar' in str(files):
|
||
size = '[COLOR magenta][B]RAR-[/B][/COLOR]%s' % size
|
||
|
||
#logger.debug(str(url))
|
||
logger.info(str(size))
|
||
|
||
if not lookup:
|
||
return (size, torrents_path, torrent_f, files)
|
||
elif file_list and data_torrent:
|
||
return (size, torrent_f, files)
|
||
elif file_list:
|
||
return (size, files)
|
||
elif data_torrent:
|
||
return (size, torrent_f)
|
||
return size
|
||
|
||
|
||
def get_field_from_kodi_DB(item, from_fields='*', files='file'):
|
||
logger.info()
|
||
"""
|
||
|
||
Llamada para leer de la DB de Kodi los campos que se reciben de entrada (from_fields, por defecto "*") del vídeo señalado en Item
|
||
Obviamente esto solo funciona con Kodi y si la película o serie está catalogada en las Videotecas de Alfa y Kodi
|
||
Se puede pedir que la búdqueda se haga por archivos (defecto), o por carpeta (series)
|
||
|
||
La llamada es:
|
||
nun_records, records = generictools.get_field_from_kodi_DB(item, from_fields='cXX[, cYY,...]'[, files = 'file|folder'])
|
||
|
||
Devuelve el num de registros encontrados y los registros. Es importante que el llamador verifique que "nun_records > 0" antes de tratar "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': #Agrego la carpeta correspondiente al path de la Videoteca
|
||
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() #listo las series o películas en la Videoteca
|
||
carpetas = [filetools.join(path, f) for f in carpetas] #agrego la carpeta del contenido al path
|
||
for carpeta in carpetas: #busco el contenido seleccionado en la lista de carpetas
|
||
if item.contentType == 'movie' and (item.contentTitle.lower() in carpeta or item.contentTitle in carpeta): #Películas?
|
||
path = carpeta #Almacenamos la carpeta en el 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, '%s.(.*?\s\[.*?\])' % folder) #Agregamos la carpeta de la Serie o Películas, formato Android
|
||
file_search = '%' #Por defecto busca todos los archivos de la carpeta
|
||
if files == 'file': #Si se ha pedido son un archivo (defecto), se busca
|
||
if item.contentType == 'episode': #Si es episodio, se pone el nombre, si no de deja %
|
||
file_search = '%sx%s.strm' % (item.contentSeason, str(item.contentEpisodeNumber).zfill(2)) #Nombre para episodios
|
||
|
||
if "\\" in path: #Ajustamos los / en función de la plataforma
|
||
path = path.replace("/", "\\")
|
||
path += "\\" #Terminamos el path con un /
|
||
else:
|
||
path += "/"
|
||
|
||
if FOLDER_TVSHOWS in path: #Compruebo si es CINE o SERIE
|
||
contentType = "episode_view" #Marco la tabla de BBDD de Kodi Video
|
||
else:
|
||
contentType = "movie_view" #Marco la tabla de BBDD de Kodi Video
|
||
path1 = path.replace("\\\\", "\\") #para la SQL solo necesito la carpeta
|
||
path2 = path2.replace("\\", "/") #Formato no Windows
|
||
|
||
#Ejecutmos la sentencia SQL
|
||
if not from_fields:
|
||
from_fields = '*'
|
||
else:
|
||
from_fields = 'strFileName, %s' % from_fields #al menos dos campos, porque uno solo genera cosas raras
|
||
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) #ejecución de la SQL
|
||
if nun_records == 0: #hay error?
|
||
logger.error("Error en la SQL: " + sql + ": 0 registros") #No estará catalogada o hay un error en el SQL
|
||
except:
|
||
logger.error(traceback.format_exc())
|
||
|
||
return (nun_records, records)
|
||
|
||
|
||
def fail_over_newpct1(item, patron, patron2=None, timeout=None):
|
||
logger.info()
|
||
import ast
|
||
|
||
"""
|
||
|
||
Llamada para encontrar una web alternativa a un canal caído, clone de NewPct1
|
||
|
||
Creamos una array con los datos de los canales alternativos. Los datos de la tupla son:
|
||
|
||
- active = 0,1 Indica si el canal no está activo o sí lo está
|
||
- channel nombre del canal alternativo
|
||
- channel_host host del canal alternativo, utilizado para el reemplazo de parte de la url
|
||
- contentType indica que tipo de contenido que soporta el nuevo canal en fail-overs
|
||
- action_excluded lista las acciones que está excluidas para ese canal
|
||
|
||
La llamada al método desde el principio de Submenu, Listado_Búsqueda, Episodios y Findvideos, es:
|
||
|
||
from lib import generictools
|
||
item, data = generictools.fail_over_newpct1(item, patron[, patron2=][, timeout=])
|
||
|
||
- Entrada: patron: con este patron permite verificar si los datos de la nueva web son buenos
|
||
- Entrada (opcional): patron2: segundo patron opcional
|
||
- Entrada (opcional): timeout: valor de espera máximo en download de página. Por defecto 3
|
||
- Entrada (opcional): patron=True: pide que sólo verifique si el canal en uso está activo, si no, ofrece otro
|
||
- Salida: data: devuelve los datos del la nueva web. Si vuelve vacía es que no se ha encontrado alternativa
|
||
|
||
"""
|
||
#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 #Mas tiempo para búsquedas
|
||
|
||
data = ''
|
||
channel_failed = ''
|
||
url_alt = []
|
||
item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize()
|
||
if not item.extra2:
|
||
item.extra2 = 'z9z8z7z6z5'
|
||
|
||
patron_alt = ''
|
||
verify_torrent = ''
|
||
if patron is not True and '|' in patron: #Comprobamos si hay dos patrones alternativos
|
||
try:
|
||
verify_torrent, patron1, patron_alt = patron.split('|') #Si es así, los separamos y los tratamos
|
||
patron = patron1
|
||
except:
|
||
logger.error(traceback.format_exc())
|
||
|
||
#Array con los datos de los canales alternativos
|
||
#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
|
||
fail_over = settings['default'] #Carga lista de 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
|
||
#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:
|
||
if channel != item.category.lower(): #es el canal/categoría que falla?
|
||
continue
|
||
else:
|
||
if channel != item.channel: #es el canal que falla?
|
||
continue
|
||
channel_failed = channel #salvamos el nombre del canal o categoría
|
||
channel_host_failed = channel_host #salvamos el nombre del host
|
||
channel_url_failed = item.url #salvamos la url
|
||
#logger.debug(channel_failed + ' / ' + channel_host_failed)
|
||
|
||
if patron == True and active == '1': #solo nos han pedido verificar el clone
|
||
return (item, data) #nos vamos, con el mismo clone, si está activo
|
||
if (item.action == 'episodios' or item.action == "update_tvshow" or item.action == "get_seasons" or item.action == 'findvideos') and item.contentType not in contentType: #soporta el fail_over de este contenido?
|
||
logger.error("ERROR 99: " + item.action.upper() + ": Acción no soportada para Fail-Over en canal: " + item.url)
|
||
return (item, data) #no soporta el fail_over de este contenido, no podemos hacer nada
|
||
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
|
||
|
||
#Recorremos el Array identificando canales activos que funcionen, distintos del caído, que soporten el contenido
|
||
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: #es válido el nuevo canal?
|
||
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: #soporta el contenido?
|
||
continue
|
||
|
||
#Hacemos el cambio de nombre de canal y url, conservando las anteriores como 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] #salvamos la url para el bucle
|
||
item.channel_host = channel_host
|
||
#logger.debug(str(url_alt))
|
||
|
||
#quitamos el código de series, porque puede variar entre webs
|
||
if item.action == "episodios" or item.action == "get_seasons" or item.action == "update_tvshow":
|
||
item.url = re.sub(r'\/\d+\/?$', '', item.url) #parece que con el título solo ecuentra la serie, normalmente...
|
||
url_alt = [item.url] #salvamos la url para el bucle, pero de momento ignoramos la inicial con código de serie
|
||
|
||
#si es un episodio, generalizamos la url para que se pueda encontrar en otro clone. Quitamos la calidad del final de la url
|
||
elif item.action == "findvideos" and item.contentType == "episode":
|
||
try:
|
||
#quitamos el 0 a la izquierda del episodio. Algunos clones no lo aceptan
|
||
inter1, inter2, inter3 = scrapertools.find_single_match(item.url, '(http.*?\/temporada-\d+.*?\/capitulo.?-)(\d+)(.*?\/)')
|
||
inter2 = re.sub(r'^0', '', inter2)
|
||
if inter1 + inter2 + inter3 not in url_alt:
|
||
url_alt += [inter1 + inter2 + inter3]
|
||
|
||
#en este formato solo quitamos la calidad del final de la url
|
||
if scrapertools.find_single_match(item.url, 'http.*?\/temporada-\d+.*?\/capitulo.?-\d+.*?\/') not in url_alt:
|
||
url_alt += [scrapertools.find_single_match(item.url, 'http.*?\/temporada-\d+.*?\/capitulo.?-\d+.*?\/')]
|
||
except:
|
||
logger.error("ERROR 88: " + item.action + ": Error al convertir la url: " + item.url)
|
||
logger.error(traceback.format_exc())
|
||
logger.debug('URLs convertidas: ' + str(url_alt))
|
||
|
||
if patron == True: #solo nos han pedido verificar el clone
|
||
return (item, data) #nos vamos, con un nuevo clone
|
||
|
||
#Leemos la nueva url.. Puede haber varias alternativas a la url original
|
||
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 ha habido suerte, probamos con la siguiente url
|
||
logger.error("ERROR 01: " + item.action + ": La Web no responde o la URL es erronea: " + url)
|
||
continue
|
||
|
||
#Hemos logrado leer la web, validamos si encontramos un línk válido en esta estructura
|
||
#Evitar páginas engañosas que puede meter al canal en un loop infinito
|
||
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 ha habido suerte, probamos con el siguiente canal
|
||
logger.error("ERROR 02: " + item.action + ": Ha cambiado la estructura de la Web: " + url + " / Patron: " + patron + " / " +patron_alt)
|
||
web_intervenida(item, data)
|
||
data = ''
|
||
continue
|
||
else:
|
||
#Función especial para encontrar en otro clone un .torrent válido
|
||
if verify_torrent == 'torrent:check:status':
|
||
from core import videolibrarytools
|
||
if not data_alt.startswith("http"): #Si le falta el http.: lo ponemos
|
||
data_alt = scrapertools.find_single_match(item.channel_host, '(\w+:)//') + data_alt
|
||
if videolibrarytools.verify_url_torrent(data_alt): #verificamos si el .torrent existe
|
||
item.url = url #guardamos la url que funciona
|
||
break #nos vamos, con la nueva url del .torrent verificada
|
||
data = ''
|
||
continue #no vale el .torrent, continuamos
|
||
item.url = url #guardamos la url que funciona, sin verificar
|
||
break #por fin !!! Este canal parece que funciona
|
||
else:
|
||
logger.error("ERROR 02: " + item.action + ": Ha cambiado la estructura de la Web: " + url + " / Patron: " + patron + " / " +patron_alt)
|
||
web_intervenida(item, data)
|
||
data = ''
|
||
continue
|
||
|
||
if not data: #no ha habido suerte, probamos con el siguiente clone
|
||
url_alt = []
|
||
continue
|
||
else:
|
||
break
|
||
|
||
del item.extra2 #Borramos acción temporal excluyente
|
||
if not data: #Si no ha logrado encontrar nada, salimos limpiando 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 verify_channel(channel):
|
||
return channel
|
||
#Lista con los datos de los canales alternativos
|
||
#Cargamos en .json del canal para ver las listas de valores en settings
|
||
# clones = channeltools.get_channel_json(channel_py)
|
||
# for settings in clones['settings']: #Se recorren todos los settings
|
||
# if settings['id'] == "clonenewpct1_channels_list": #Encontramos en setting
|
||
# clones = settings['default'] #Carga lista de clones
|
||
# channel_alt = "'%s'" % channel
|
||
# if channel_alt in clones: #Si es un clon se pone como canal newpct1, si no se deja
|
||
# channel = channel_py
|
||
# return channel
|
||
|
||
|
||
def web_intervenida(item, data, desactivar=True):
|
||
logger.info()
|
||
|
||
"""
|
||
|
||
Llamada para verificar si la caída de un clone de Newpct1 es debido a una intervención judicial
|
||
|
||
La llamada al método desde es:
|
||
|
||
from lib import generictools
|
||
item = generictools.web_intervenida(item, data[, desactivar=True])
|
||
|
||
- Entrada: data: resultado de la descarga. Nos permite analizar si se trata de una intervención
|
||
- Entrada: desactivar=True: indica que desactiva el canal o clone en caso de intervención judicial
|
||
- Salida: item.intervencion: devuele un array con el nombre del clone intervenido y el thumb de la autoridad que interviene. El canal puede anunciarlo.
|
||
- Salida: Si es un clone de Newpct1, se desactiva el clone en el .json del Canal. Si es otro canal, se desactiva el canal en su .json.
|
||
|
||
"""
|
||
|
||
intervencion = ()
|
||
judicial = ''
|
||
|
||
#Verificamos que sea una intervención judicial
|
||
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 de la Benemérita
|
||
if intervenido_policia in data:
|
||
judicial = 'intervenido_pn.jpeg' #thumb de la Policia Nacional
|
||
if intervenido_sucuri in data:
|
||
judicial = 'intervenido_sucuri.png' #thumb de Sucuri
|
||
category = item.category
|
||
if not item.category:
|
||
category = item.channel
|
||
intervencion = (category, judicial) #Guardamos el nombre canal/categoría y el thumb judicial
|
||
if not item.intervencion:
|
||
item.intervencion = [] #Si no existe el array, lo creamos
|
||
item.intervencion += [intervencion] #Añadimos esta intervención al array
|
||
|
||
logger.error("ERROR 99: " + category + ": " + judicial + ": " + item.url + ": DESACTIVADO=" + str(desactivar) + " / DATA: " + data)
|
||
|
||
if desactivar == False: #Si no queremos desactivar el canal, nos vamos
|
||
return item
|
||
|
||
#Cargamos en .json del canal para ver las listas de valores en settings. Carga las claves desordenadas !!!
|
||
from core import filetools
|
||
import json
|
||
json_data = channeltools.get_channel_json(item.channel)
|
||
|
||
if item.channel == channel_py: #Si es un clone de Newpct1, lo desactivamos
|
||
for settings in json_data['settings']: #Se recorren todos los settings
|
||
if settings['id'] == "clonenewpct1_channels_list": #Encontramos en setting
|
||
action_excluded = scrapertools.find_single_match(settings['default'], "\('\d', '%s', '[^']+', '[^']*', '([^']*)'\)" % item.category.lower()) #extraemos el valor de action_excluded
|
||
if action_excluded:
|
||
if "intervenido" not in action_excluded:
|
||
action_excluded += ', %s' % judicial #Agregamos el thumb de la autoridad judicial
|
||
else:
|
||
action_excluded = '%s' % judicial
|
||
|
||
#Reemplazamos el estado a desactivado y agregamos el thumb de la autoridad judicial
|
||
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 #Se desactiva el canal
|
||
json_data['thumbnail'] = ', thumb_%s' % judicial #Guardamos el thumb de la autoridad judicial
|
||
|
||
#Guardamos los cambios hechos en el .json
|
||
try:
|
||
if item.channel != channel_py:
|
||
disabled = config.set_setting('enabled', False, item.channel) #Desactivamos el canal
|
||
disabled = config.set_setting('include_in_global_search', False, item.channel) #Lo sacamos de las búquedas globales
|
||
channel_path = filetools.join(config.get_runtime_path(), "channels", item.channel + ".json")
|
||
with open(channel_path, 'w') as outfile: #Grabamos el .json actualizado
|
||
json.dump(json_data, outfile, sort_keys = True, indent = 2, ensure_ascii = False)
|
||
except:
|
||
logger.error("ERROR 98 al salvar el archivo: %s" % channel_path)
|
||
logger.error(traceback.format_exc())
|
||
|
||
#logger.debug(item)
|
||
|
||
return item
|
||
|
||
|
||
def redirect_clone_newpct1(item, head_nfo=None, it=None, path=False, overwrite=False, lookup=False):
|
||
# logger.info()
|
||
#
|
||
# """
|
||
#
|
||
# Llamada para redirigir cualquier llamada a un clone de NewPct1 a NewPct1.py, o de una url de un canal caido a una alternativa
|
||
# Incluye las llamadas estándar del canal y la llamadas externas:
|
||
# - Play fron Library
|
||
# - Videolibrary Update
|
||
#
|
||
# La lógica es reemplazar item.channel por "newpct1" y dejar el nombre del clone en item.category.
|
||
# De esta forma utiliza siempre el código de NewPct1.py, aunque con las urls y apariencia del clone seleccionado por el usuario.
|
||
#
|
||
# En el caso de un canal/clone caído o intervenido judicialmente, puede reemplazar el canal en item.channel, o el clone en item.category, y la parte de item.url que se introduzca en una tabla. Esta conversión sólo se realiza si el canal original está inactivo, pero lo realiza siempre para los clones, o si el canal de origen y destino son los mismos.
|
||
#
|
||
# Este método interroga el .json de NewPct1 para extraer la lista de canales clones. Si item.channel es un clone de NewPct1 y está en esa lista, actualiza item.channel='newpct1'
|
||
#
|
||
# También en este .json está la tabla para la conversión de canales y urls:
|
||
# - activo: está o no activa esta entrada
|
||
# - canal_org: canal o clone de origen
|
||
# - canal_des: canal o clone de destino (puede ser el mismo)
|
||
# - url_org: parte de la url a sustituir de canal o clone de origen
|
||
# - url_des: parte de la url a sustituir de canal o clone de destino
|
||
# - patron1: expresión Regex aplicable a la url (opcional)
|
||
# - patron2: expresión Regex aplicable a la url (opcional)
|
||
# - patron3: expresión Regex aplicable a la url (opcional)
|
||
# - patron4: expresión Regex aplicable a la url (opcional)
|
||
# - patron5: expresión Regex aplicable a la url (opcional)
|
||
# - content_inc: contenido al que aplica esta entrada, o * (item.contentType o item.extra)
|
||
# - content_exc: contenido que se excluye de esta entrada (item.contentType) (opcional). opción para 'emerg'
|
||
# - ow_force: indicador para la acción de "service.py". Puede crear la variable item.ow_force:
|
||
# - force: indica al canal que analize toda la serie y que service la reescriba
|
||
# - auto: indica a service que la reescriba
|
||
# - no: no acción para service, solo redirige en visionado de videolibrary
|
||
# - del: borra las estrucuturas de un determinado canal en service, quizás creadas por errores de un canal
|
||
# - emerg: funcionalidad muy similar a la de "del". se general dinámicamente cada vez que entra un canal con el estado activado en el .json de "emergency_urls". Permite cargar las urls de emergencia en todos los elementos existentes de la Videoteca para canal afectado
|
||
# ejemplos:
|
||
# ('1', 'mejortorrent', 'mejortorrent1', 'http://www.mejortorrent.com/', 'https://mejortorrent1.com/', '(http.?:\/\/.*?\/)', 'http.?:\/\/.*?\/.*?-torrent.?-[^-]+-(?:[^-]+-)([^0-9]+-)', 'http.?:\/\/.*?\/.*?-torrent.?-[^-]+-(?:[^-]+-)[^0-9]+-\\d+-(Temporada-).html', 'http.?:\/\/.*?\/.*?-torrent.?-[^-]+-(?:[^-]+-)[^0-9]+-(\\d+)-', '', 'tvshow, season', '', 'force'),
|
||
# ('1', 'mejortorrent', 'mejortorrent1', 'http://www.mejortorrent.com/', 'https://mejortorrent1.com/', '(http.?:\/\/.*?\/)', 'http.?:\/\/.*?\/.*?-torrent.?-[^-]+-([^.]+).html', '', '', '', 'movie', '', 'force')",
|
||
# ('1', 'torrentrapid', 'torrentlocura', 'http://torrentrapid.com/', 'http://torrentlocura.com/', '', '', '', '', '', '*', '', 'no'),
|
||
# ('1', 'newpct1', '', '', '', '', '', '', '', '', '*', '', 'del'),
|
||
# ('1', 'torrentrapid', 'torrentrapid', '', '', '', '', '', '', '', '*', '1 ó 2', 'emerg'),
|
||
#
|
||
# La llamada recibe el parámetro Item, el .nfo y los devuleve actualizados, así como opcionalmente el parámetro "overwrite· que puede forzar la reescritura de todos los archivos de la serie, y el parámetro "path" si viene de service. Por último, recibe opcionalmente el parámetro "lookup" si se quiere solo averigurar si habrá migración para ese título, pero sin realizarla.
|
||
#
|
||
# """
|
||
# #logger.debug(item)
|
||
# #if it != None: logger.debug(it)
|
||
# if not it:
|
||
# it = Item()
|
||
# item_back = item.clone()
|
||
# it_back = item.clone()
|
||
# ow_force_param = True
|
||
# update_stat = 0
|
||
# delete_stat = 0
|
||
# canal_org_des_list = []
|
||
# json_path_list = []
|
||
# emergency_urls_force = False
|
||
# status_migration = False
|
||
#
|
||
# #if item.ow_force == '1': #Ha podido qudar activado de una pasada anteriores
|
||
# # del item.ow_force
|
||
# # logger.error('** item.ow_force: ' + item.path) #aviso que ha habido una incidencia
|
||
# if it.ow_force == '1': #Ha podido quedar activado de una pasada anterior
|
||
# del it.ow_force
|
||
# if path and it.infoLabels['mediatype'] == 'tvshow':
|
||
# try:
|
||
# nfo = filetools.join(path, '/tvshow.nfo')
|
||
# filetools.write(nfo, head_nfo + it.tojson()) #escribo el .nfo de la peli por si aborta update
|
||
# logger.error('** .nfo ACTUALIZADO: it.ow_force: ' + nfo) #aviso que ha habido una incidencia
|
||
# except:
|
||
# logger.error('** .nfo ERROR actualizar: it.ow_force: ' + nfo) #aviso que ha habido una incidencia
|
||
# logger.error(traceback.format_exc())
|
||
#
|
||
# #Array con los datos de los canales alternativos
|
||
# #Cargamos en .json de Newpct1 para ver las listas de valores en settings
|
||
# fail_over_list = channeltools.get_channel_json(channel_py)
|
||
# for settings in fail_over_list['settings']: #Se recorren todos los settings
|
||
# if settings['id'] == "clonenewpct1_channels_list": #Encontramos en setting
|
||
# fail_over_list = settings['default'] #Carga lista de clones
|
||
# if settings['id'] == "intervenidos_channels_list": #Encontramos en setting
|
||
# intervencion = settings['default'] #Carga lista de clones y canales intervenidos
|
||
#
|
||
# #primero tratamos los clones de Newpct1
|
||
# channel_alt = item.channel
|
||
# #if item.url and not it.library_urls:
|
||
# # channel_alt = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').lower() #Salvamos en nombre del canal o clone
|
||
# # if not channel_alt:
|
||
# # channel_alt = item.channel
|
||
# channel = "'%s'" % channel_alt
|
||
# category = ''
|
||
# if channel_alt != 'videolibrary':
|
||
# item.category = channel_alt.capitalize()
|
||
# category = "'%s'" % channel_alt
|
||
# channel_py_alt = 'xyz123'
|
||
# if channel in fail_over_list : #Si es un clone de Newpct1, se actualiza el canal y la categoría
|
||
# item.channel = channel_py
|
||
# channel_py_alt = "'%s'" % channel_py
|
||
# if item.channel_host: #y se borran resto de pasadas anteriores
|
||
# del item.channel_host
|
||
#
|
||
# if it.emergency_urls:
|
||
# item.emergency_urls = it.emergency_urls #Refrescar desde el .nfo
|
||
#
|
||
# #Analizamos si hay series o películas que migrar, debido a que se ha activado en el .json del canal la opción "guardar"
|
||
# #"emergency_urls = 1", y hay que calcularla para todos los episodios y película existentes en la Videoteca.
|
||
# #Si "emergency_urls" está activada para uno o más canales, se verifica en el .nfo del vídeo si ya se ha realizado
|
||
# #la carga de las urls de emergencia. Sí se ha hecho, se ignora el proceso de conversión. Si no, se convierte por el
|
||
# #canal en curso cuando hay item.url, o para todos los canales en item.library_urls si no hay un canal específico en curso.
|
||
# #El mecanismo consiste en generar una regla temporal de migración para cada canal activado. Esta regla actua borrando
|
||
# #todos los .json de la serie/película. En el caso de la serie, el proceso de actualización de la videoteca los regenerará
|
||
# #automáticamente. En el caso de peliculas, se general aquí el json actualizado y se marca el .nfo como actualizado.
|
||
# #Cuando en el .json se activa "Borrar", "emergency_urls = 2", se borran todos los enlaces existentes
|
||
# #Cuando en el .json se activa "Actualizar", "emergency_urls = 3", se actualizan todos los enlaces existentes
|
||
#
|
||
# """
|
||
# status_migration = regenerate_clones() #TEMPORAL: Reparación de Videoteca con Newpct1
|
||
#
|
||
# verify_cached_torrents() #TEMPORAL: verificamos si los .torrents son correctos
|
||
# try: #Si ha habido errores, vemos la lista y los reparamos
|
||
# json_error_path = filetools.join(config.get_runtime_path(), 'error_cached_torrents.json')
|
||
# if filetools.exists(json_error_path): #hay erroer que hay que reparar?
|
||
# from core import jsontools
|
||
# json_error_file = jsontools.load(filetools.read(json_error_path)) #Leemos la lista de errores
|
||
# if not json_error_file:
|
||
# filetools.remove(json_error_path) #si ya no quedan errores, borramos el .json
|
||
# elif path in json_error_file: #está este títu,o en la lista de errores?
|
||
# json_error_file.pop(path) #sí. Lo quitamos
|
||
# if not json_error_file:
|
||
# filetools.remove(json_error_path) #si ya no quedan errores, borramos el .json
|
||
# else:
|
||
# filetools.write(json_error_path, jsontools.dump(json_error_file)) #si quedan, actualizamos el .json
|
||
# if item.contentType == 'movie': #si es una pelicula, forzamos su actualización
|
||
# emergency_urls_force = True
|
||
# else: #si es una serie, que regenere los episodios que faltan (en error)
|
||
# item.ow_force = '1' #... de todas las temporadas
|
||
# except:
|
||
# logger.error('Error en el proceso de REPARACION de vídeos con .torrents dañados')
|
||
# logger.error(traceback.format_exc())
|
||
#
|
||
# #Arreglo temporal para Newpct1
|
||
# try:
|
||
# if channel in fail_over_list or channel_alt == 'videolibrary':
|
||
# channel_bis = channel_py
|
||
# if not item.url and it.library_urls and channel_alt == 'videolibrary':
|
||
# for canal_vid, url_vid in it.library_urls.items(): #Se recorre "item.library_urls" para buscar canales candidatos
|
||
# canal_vid_alt = "'%s'" % canal_vid
|
||
# if canal_vid_alt in fail_over_list: #Se busca si es un clone de newpct1
|
||
# channel_bis = channel_py
|
||
# channel_alt = canal_vid
|
||
# channel = "'%s'" % channel_alt
|
||
# break
|
||
# else:
|
||
# channel_bis = canal_vid
|
||
# if channel_bis == channel_py and config.get_setting("emergency_urls", channel_bis) == 1 and config.get_setting("emergency_urls_torrents", channel_bis) and item.emergency_urls and item.emergency_urls.get(channel_alt, False):
|
||
# raiz, carpetas_series, ficheros = filetools.walk(path).next()
|
||
# objetivo = '[%s]_01.torrent' % channel_alt
|
||
# encontrado = False
|
||
# for fichero in ficheros:
|
||
# if objetivo in fichero:
|
||
# encontrado = True
|
||
# break
|
||
# if not encontrado:
|
||
# logger.error('REGENERANDO: ' + str(item.emergency_urls))
|
||
# item.emergency_urls.pop(channel_alt, None)
|
||
# except:
|
||
# logger.error('Error en el proceso de RECARGA de URLs de Emergencia')
|
||
# logger.error(traceback.format_exc())
|
||
# """
|
||
#
|
||
# try:
|
||
# if item.url and not channel_py in item.url and it.emergency_urls: #Viene de actualización de videoteca de series
|
||
# #Analizamos si el canal ya tiene las urls de emergencia: guardar o borrar
|
||
# if (config.get_setting("emergency_urls", item.channel) == 1 and (not item.emergency_urls or (item.emergency_urls and not item.emergency_urls.get(channel_alt, False)))) or (config.get_setting("emergency_urls", item.channel) == 2 and item.emergency_urls.get(channel_alt, False)) or config.get_setting("emergency_urls", item.channel) == 3 or emergency_urls_force:
|
||
# intervencion += ", ('1', '%s', '%s', '', '', '', '', '', '', '', '*', '%s', 'emerg')" % (channel_alt, channel_alt, config.get_setting("emergency_urls", item.channel))
|
||
#
|
||
# elif it.library_urls: #Viene de "listar peliculas´"
|
||
# for canal_vid, url_vid in it.library_urls.items(): #Se recorre "item.library_urls" para buscar canales candidatos
|
||
# if canal_vid == channel_py: #Si tiene Newcpt1 en canal, es un error
|
||
# continue
|
||
# canal_vid_alt = "'%s'" % canal_vid
|
||
# if canal_vid_alt in fail_over_list: #Se busca si es un clone de newpct1
|
||
# channel_bis = channel_py
|
||
# else:
|
||
# channel_bis = canal_vid
|
||
# #Analizamos si el canal ya tiene las urls de emergencia: guardar o borrar
|
||
# if (config.get_setting("emergency_urls", channel_bis) == 1 and (not it.emergency_urls or (it.emergency_urls and not it.emergency_urls.get(canal_vid, False)))) or (config.get_setting("emergency_urls", channel_bis) == 2 and it.emergency_urls.get(canal_vid, False)) or config.get_setting("emergency_urls", channel_bis) == 3 or emergency_urls_force:
|
||
# intervencion += ", ('1', '%s', '%s', '', '', '', '', '', '', '', '*', '%s', 'emerg')" % (canal_vid, canal_vid, config.get_setting("emergency_urls", channel_bis))
|
||
# except:
|
||
# logger.error('Error en el proceso de ALMACENAMIENTO de URLs de Emergencia')
|
||
# logger.error(traceback.format_exc())
|
||
#
|
||
# #Ahora tratamos las webs intervenidas, tranformamos la url, el nfo y borramos los archivos obsoletos de la serie
|
||
# if (channel not in intervencion and channel_py_alt not in intervencion and category not in intervencion and channel_alt != 'videolibrary') or not item.infoLabels or status_migration: #lookup o migración
|
||
# return (item, it, overwrite) #... el canal/clone está listado
|
||
#
|
||
# import ast
|
||
# intervencion_list = ast.literal_eval(intervencion) #Convertir a Array el string
|
||
# #logger.debug(intervencion_list)
|
||
#
|
||
# if lookup == True:
|
||
# overwrite = False #Solo avisamos si hay cambios
|
||
# i = 0
|
||
# for activo, canal_org, canal_des, url_org, url_des, patron1, patron2, patron3, patron4, patron5, content_inc, content_exc, ow_force in intervencion_list:
|
||
# i += 1
|
||
# opt = ''
|
||
# #Es esta nuestra entrada?
|
||
# if activo == '1' and (canal_org == channel_alt or canal_org == item.category.lower() or channel_alt == 'videolibrary' or ow_force == 'del' or ow_force == 'emerg'):
|
||
#
|
||
# if item.url:
|
||
# logger.debug('INTERV. LIST: ' + str(intervencion_list[i-1]) + ' / CHANNEL: ' + str(channel_alt) + ' / URL: ' + str(item.url))
|
||
#
|
||
# if ow_force == 'del' or ow_force == 'emerg': #Si es un borrado de estructuras erroneas, hacemos un proceso aparte
|
||
# canal_des_def = canal_des #Si hay canal de sustitución para item.library_urls, lo usamos
|
||
# if not canal_des_def and canal_org in item.library_urls and len(item.library_urls) == 1: #Si no, lo extraemos de la url
|
||
# canal_des_def = scrapertools.find_single_match(item.library_urls[canal_org], 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').lower() #salvamos la url actual de la estructura a borrar
|
||
# url_total = ''
|
||
# if item.url:
|
||
# url_total = item.url #Si existe item.url, lo salvamos para futuro uso
|
||
# if item.library_urls and canal_org in item.library_urls: #Si existe una entrada con el canal a borrar, lo procesamos
|
||
# if lookup == True: #Queremos que el canal solo visualice sin migración?
|
||
# overwrite = True #Avisamos que hay cambios
|
||
# continue
|
||
# logger.error('** REGLA: ' + canal_org + ', ' + canal_des+ ', ' + ow_force)
|
||
# logger.error('item.library_urls PREVIA: ' + str(item.library_urls))
|
||
# url_total = item.library_urls[canal_org] #salvamos la url actual de la estructura a borrar
|
||
# url_total_status = False
|
||
# if len(item.library_urls) == 1 or canal_des: #si el nuevo canal no existe ya...
|
||
# item.library_urls.update({canal_des_def: url_total}) #restauramos la url con el nuevo canal
|
||
# url_total_status = True #marcamos esta url como válida
|
||
# overwrite = True #Le decimos que sobreescriba todos los .jsons
|
||
# item.ow_force = '1' #Le decimos que revise todas las temporadas
|
||
# if len(item.library_urls) > 1 and ow_force == 'del':
|
||
# item.library_urls.pop(canal_org, None) #borramos la url del canal a borrar
|
||
# overwrite = True #Le decimos que sobreescriba todos los .jsons
|
||
# item.ow_force = '1' #Le decimos que revise todas las temporadas
|
||
# if it.library_urls:
|
||
# it.library_urls = item.library_urls #lo salvamos en el .nfo, si lo hay
|
||
#
|
||
# if item.url and item.url == url_total and url_total_status == False: #si la url es la del canal borrado...
|
||
# for canal_vid, url_vid in item.library_urls.items():
|
||
# canal_vid_alt = "'%s'" % canal_vid
|
||
# if canal_vid_alt not in intervencion: #... la sustituimos por la primera válida
|
||
# item.url = url_vid
|
||
# break
|
||
# if canal_vid_alt in fail_over_list: #Si es un clone de Newpct1, salvamos la nueva categoría
|
||
# item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').lower() #Salvamos categoría
|
||
# else:
|
||
# item.category = canal_vid.capitalize() #si no, salvamos nueva categoría
|
||
# logger.error('item.library_urls ACTUALIZADA: ' + str(item.library_urls))
|
||
#
|
||
# if lookup == False: #si es migración completa...
|
||
# delete_stat += 1 #Ya hemos actualizado algo, o habrá que hacerlo...
|
||
# if ow_force == 'emerg': opt = content_exc #Salvamos la opción de Guardar o Borrar enlaces
|
||
# canal_org_des_list += [(canal_org, canal_des, url_total, opt, ow_force)] #salvamos el resultado para su proceso
|
||
#
|
||
# else:
|
||
# if channel_alt == 'videolibrary': #Viene de videolibrary.list_movies: IMPRESCINDIBLE
|
||
# for canal_vid, url_vid in item.library_urls.items():
|
||
# if canal_org != canal_vid: #Miramos si canal_org de la regla está en item.library_urls
|
||
# continue
|
||
# else:
|
||
# channel_alt = canal_org #Sí, ponermos el nombre del canal de origen
|
||
# channel_b = "'%s'" % canal_org
|
||
# if channel_b in fail_over_list: #Si es un clone de Newpct1, se actualiza a newpct1
|
||
# channel_alt = channel_py
|
||
# if channel_alt == 'videolibrary':
|
||
# continue
|
||
# if item.contentType == "list": #Si viene de Videolibrary, le cambiamos ya el canal
|
||
# if item.channel != channel_py:
|
||
# item.channel = canal_des #Cambiamos el canal. Si es clone, lo hace el canal
|
||
# continue #Salimos sin hacer nada más. item está casi vacío
|
||
# if item.contentType not in content_inc and "*" not in content_inc: #Está el contenido el la lista de incluidos
|
||
# continue
|
||
# if item.contentType in content_exc: #Está el contenido excluido?
|
||
# continue
|
||
# channel_enabled = 0
|
||
# channel_enabled_alt = 1
|
||
# if item.channel != channel_py:
|
||
# try:
|
||
# if channeltools.is_enabled(channel_alt): channel_enabled = 1 #Verificamos que el canal esté inactivo
|
||
# if config.get_setting('enabled', channel_alt) == False: channel_enabled_alt = 0
|
||
# channel_enabled = channel_enabled * channel_enabled_alt #Si está inactivo en algún sitio, tomamos eso
|
||
# except:
|
||
# pass
|
||
# if channel_enabled == 1 and canal_org != canal_des: #Si el canal está activo, puede ser solo...
|
||
# continue #... una intervención que afecte solo a una región
|
||
# if ow_force == 'no' and it.library_urls: #Esta regla solo vale para findvideos...
|
||
# continue #... salidmos si estamos actualizando
|
||
# if lookup == True: #Queremos que el canal solo visualice sin migración?
|
||
# if ow_force != 'no':
|
||
# overwrite = True #Avisamos que hay cambios
|
||
# continue #Salimos sin tocar archivos
|
||
# url_total = ''
|
||
# if item.url:
|
||
# url_total = item.url
|
||
# elif not item.url and item.library_urls:
|
||
# url_total = item.library_urls[canal_org]
|
||
# url_total = url_total.replace(url_org, url_des) #reemplazamos una parte de url
|
||
# url = ''
|
||
# if patron1: #Hay expresión regex?
|
||
# url += scrapertools.find_single_match(url_total, patron1) #La aplicamos a url
|
||
# if patron2: #Hay más expresión regex?
|
||
# url += scrapertools.find_single_match(url_total, patron2) #La aplicamos a url
|
||
# if patron3: #Hay más expresión regex?
|
||
# url += scrapertools.find_single_match(url_total, patron3) #La aplicamos a url
|
||
# if patron4: #Hay más expresión regex?
|
||
# url += scrapertools.find_single_match(url_total, patron4) #La aplicamos a url
|
||
# if patron5: #Hay más expresión regex?
|
||
# url += scrapertools.find_single_match(url_total, patron5) #La aplicamos a url
|
||
# if url:
|
||
# url_total = url #Guardamos la suma de los resultados intermedios
|
||
# if item.channel == channel_py or channel in fail_over_list: #Si es Newpct1...
|
||
# if item.contentType == "tvshow":
|
||
# url_total = re.sub(r'\/\d+\/?$', '', url_total) #parece que con el título encuentra la serie, normalmente...
|
||
# update_stat += 1 #Ya hemos actualizado algo
|
||
# canal_org_des_list += [(canal_org, canal_des, url_total, opt, ow_force)] #salvamos el resultado para su proceso
|
||
#
|
||
# if update_stat > 0 or delete_stat > 0: #Ha habido alguna actualización o borrado? Entonces salvamos
|
||
# if (update_stat > 0 and path != False) or item.ow_force == '1':
|
||
# logger.error('** Lista de Actualizaciones a realizar: ' + str(canal_org_des_list))
|
||
# for canal_org_def, canal_des_def, url_total, opt_def, ow_force_def in canal_org_des_list: #pasamos por todas las "parejas" cambiadas
|
||
# url_total_def = url_total
|
||
# if ow_force_def != 'del' and ow_force_def != 'emerg':
|
||
# if item.url:
|
||
# item.url = url_total #Salvamos la url convertida
|
||
# if item.library_urls:
|
||
# item.library_urls.pop(canal_org_def, None)
|
||
# item.library_urls.update({canal_des_def: url_total})
|
||
# it.library_urls = item.library_urls
|
||
# if item.channel != channel_py and item.channel != 'videolibrary':
|
||
# item.channel = canal_des_def #Cambiamos el canal. Si es clone, lo hace el canal
|
||
# if channel_alt == item.category.lower(): #Actualizamos la Categoría y si la tenía
|
||
# item.category = item.channel.capitalize()
|
||
# if ow_force_def == 'force' and item.contentType != 'movie': #Queremos que el canal revise la serie entera?
|
||
# item.ow_force = '1' #Se lo decimos
|
||
# if ow_force_def in ['force', 'auto']: #Sobreescribir la series?
|
||
# overwrite = True #Sí, lo marcamos
|
||
#
|
||
# if it.library_urls and path != False and ow_force_def != 'no': #Continuamos si hay .nfo, path, y queremos actualizarlo
|
||
# item.update_next = '1'
|
||
# del item.update_next #Borramos estos campos para forzar la actualización ya
|
||
# it.update_next = '1'
|
||
# del it.update_next
|
||
#
|
||
# #Verificamos que las webs de los canales estén activas antes de borrar los .json, para asegurar que se pueden regenerar
|
||
# i = 0
|
||
# canal_org_des_list_ALT = [] #Creamos esta lista para salvar las parejas
|
||
# canal_org_des_list_ALT.extend(canal_org_des_list) #... y borrar de la original las web caidas
|
||
# for canal_org_def, canal_des_def, url_total, opt_def, ow_force_def in canal_org_des_list_ALT: #pasamos por las "parejas" a borrar
|
||
# if "magnet:" in url_total or type(url_total) != str: #Si la url es un Magnet, o es una lista, pasamos
|
||
# i += 1
|
||
# continue
|
||
# try:
|
||
# response = httptools.downloadpage(url_total)
|
||
# except:
|
||
# logger.error(traceback.format_exc())
|
||
# logger.error('Web ' + canal_des_def.upper() + ' ERROR. Regla no procesada: ' + str(canal_org_des_list[i]))
|
||
# del canal_org_des_list[i] #Borro regla
|
||
# continue #... y paso a la siguiente
|
||
# if not response:
|
||
# logger.error('Web ' + canal_des_def.upper() + ' INACTIVA. Regla no procesada: ' + str(canal_org_des_list[i]))
|
||
# del canal_org_des_list[i] #Borro regla
|
||
# continue #... y paso a la siguiente
|
||
# i += 1
|
||
# if i == 0:
|
||
# item = item_back.clone() #Restauro las imágenes inciales
|
||
# it = it_back.clone()
|
||
# item.torrent_caching_fail = True #Marcamos el proceso como fallido
|
||
# return (item, it, False)
|
||
#
|
||
# # Listamos todos los ficheros de la serie, asi evitamos tener que comprobar si existe uno por uno
|
||
# canal_erase_list = []
|
||
# from core import videolibrarytools
|
||
# raiz, carpetas_series, ficheros = filetools.walk(path).next()
|
||
# ficheros = [filetools.join(path, f) for f in ficheros] #Almacenamos la lista de archivos de la carpeta
|
||
# #logger.error(ficheros)
|
||
# for archivo in ficheros:
|
||
# for canal_org_def, canal_des_def, url_total, opt_def, ow_force_def in canal_org_des_list: #pasamos por las "parejas" a borrar
|
||
# canal_erase = '[%s]' % canal_org_def
|
||
# canal_erase_alt = "'%s'" % canal_org_def
|
||
# canal_new = '[%s]' % canal_des_def
|
||
# archivo_alt = "'%s'" % scrapertools.find_single_match(archivo, '\[(\w+)\].json')
|
||
# if archivo_alt == "''": archivo_alt = "'xyz123'"
|
||
# #logger.error(canal_erase + canal_new + archivo + archivo_alt)
|
||
# #Borramos los .json que sean de los canal afectados, incluidos todos los de los clones de newpct1 si éste es el canal
|
||
# if canal_erase in archivo or (ow_force_def == 'emerg' and canal_erase_alt in fail_over_list and archivo_alt in fail_over_list and it.contentType != 'movie'):
|
||
# if canal_des_def and it.contentType == 'movie' and not '.torrent' in archivo: #Si es película ...
|
||
# item_json = ''
|
||
# item_json = Item().fromjson(filetools.read(archivo)) #leemos el .json ante de borrarlo para salvar...
|
||
# if not item_json: #error al leer el .json. Algo no funciona...
|
||
# continue
|
||
# title = item_json.title #... el título con su formato
|
||
# language = item_json.language #... los idiomas, que no están en el .nfo
|
||
# wanted = item_json.wanted #... y wanted con el título original
|
||
# json_path = archivo.replace(canal_erase, canal_new) #Salvamos el path del .json para luego crearlo
|
||
# json_path_list += [(canal_org_def, canal_des_def, url_total, json_path, title, language, wanted, ow_force_def, opt_def, archivo)]
|
||
# filetools.remove(archivo) #Borramos el .json y el .torrent
|
||
# logger.error('** BORRAMOS: ' + str(archivo))
|
||
# if ow_force_def == 'del' or ow_force_def == 'emerg': #Si la función es 'del' or 'emerg' ...
|
||
# overwrite = True #Le decimos que sobreescriba todos los .jsons
|
||
# item.ow_force = '1' #Le decimos que revise todas las temporadas
|
||
#
|
||
# #Si se ha cambiado algo, se actualizan los .nfo
|
||
# if it.nfo: del it.nfo #Borramos variables innecesarias
|
||
# if it.path: del it.path #Borramos variables innecesarias
|
||
# if it.text_color: del it.text_color #Borramos variables innecesarias
|
||
# if item.contentType == "movie" and ".nfo" in archivo: #Para películas
|
||
# archivo_nfo = archivo #Guardamos el path del .nfo para futuro uso
|
||
# if it.ow_force: del it.ow_force
|
||
# filetools.write(archivo, head_nfo + it.tojson()) #escribo el .nfo de la peli
|
||
# if item.contentType != "movie" and "tvshow.nfo" in archivo:
|
||
# archivo_nfo = archivo #Guardamos el path del .nfo para futuro uso
|
||
# filetools.write(archivo, head_nfo + it.tojson()) #escribo el tvshow.nfo por si aborta update
|
||
#
|
||
# #Aquí convertimos las películas. Después de borrado el .json, dejamos que videolibrarytools lo regenere
|
||
# if item.contentType == "movie": #Dejamos que regenere el archivo .json
|
||
# item_movie = item.clone()
|
||
# if item_movie.ow_force: del item_movie.ow_force
|
||
# item_movie.update_last = '1'
|
||
# if item_movie.update_last: del item_movie.update_last
|
||
# if item_movie.library_playcounts: del item_movie.library_playcounts #Borramos lo que no es necesario en el .json
|
||
# if item_movie.library_urls: del item_movie.library_urls
|
||
# if item_movie.nfo: del item_movie.nfo
|
||
# if item_movie.path: del item_movie.path
|
||
# if item_movie.strm_path: del item_movie.strm_path
|
||
# if item_movie.text_color: del item_movie.text_color
|
||
# if item_movie.channel_host: del item_movie.channel_host
|
||
# if not item_movie.context: item_movie.context = "['buscar_trailer']"
|
||
# if not item_movie.extra: item_movie.extra = "peliculas"
|
||
#
|
||
# if json_path_list:
|
||
# logger.error('** .json LIST: ' + str(json_path_list))
|
||
# for canal_org_def, canal_des_def, url_total, json_path, title, language, wanted, ow_force_def, opt_def, archivo in json_path_list: #pasamos por todos canales
|
||
# logger.error('** ESCRIBIMOS: ' + json_path)
|
||
# item_movie.emergency_urls = False
|
||
# del item_movie.emergency_urls
|
||
# item_movie.channel = canal_des_def #mombre del canal migrado
|
||
# if not item_movie.category: item_movie.category = canal_des_def.capitalize() #categoría
|
||
# item_movie.url = url_total #url migrada
|
||
# if title: item_movie.title = title #restaurmos el título con formato
|
||
# if language: item_movie.language = language #restaurmos los idiomas
|
||
# if wanted: item_movie.wanted = wanted #restaurmos wanted
|
||
# item_movie.added_replacing = canal_org_def #guardamos la traza del canal reemplazado
|
||
#
|
||
# if ow_force_def == 'emerg' and opt_def in ['1', '3']: #Si era una op. para añadir/actualizar urls de emergencia ...
|
||
# item_movie = videolibrarytools.emergency_urls(item_movie, None, archivo) #... ejecutamos "findvideos" del canal para obtenerlas
|
||
# if item_movie.channel_host: del item_movie.channel_host
|
||
# if item_movie.unify: del item_movie.unify
|
||
# if item_movie.extra2: del item_movie.extra2
|
||
# if item_movie.emergency_urls: #... si las hay ...
|
||
# if it.emergency_urls and not isinstance(it.emergency_urls, dict):
|
||
# del it.emergency_urls
|
||
# if not it.emergency_urls: #... lo actualizamos en el .nfo
|
||
# it.emergency_urls = dict() #... iniciamos la variable si no existe
|
||
# it.emergency_urls.update({canal_des_def: True}) #... se marca como activo
|
||
# if it.ow_force: del it.ow_force
|
||
# filetools.write(archivo_nfo, head_nfo + it.tojson()) #actualizo el .nfo de la peli
|
||
# else:
|
||
# logger.error('Error en FINDVIDEOS: ' + archivo + ' / Regla: ' + canal_org_def + ', ' + opt_def + ', ' + ow_force_def)
|
||
#
|
||
# if ow_force_def == 'emerg' and opt_def == '2': #Si era una operación para borrar urls de emergencia ...
|
||
# if it.emergency_urls and not isinstance(it.emergency_urls, dict):
|
||
# del it.emergency_urls
|
||
# if it.emergency_urls and it.emergency_urls.get(item_movie.channel, False):
|
||
# it.emergency_urls.pop(item_movie.channel, None) #borramos la entrada del .nfo
|
||
# if it.ow_force: del it.ow_force
|
||
# filetools.write(archivo_nfo, head_nfo + it.tojson()) #actualizo el .nfo de la peli
|
||
#
|
||
# filetools.write(json_path, item_movie.tojson()) #Salvamos el nuevo .json de la película
|
||
#
|
||
# if (update_stat > 0 and path != False and ow_force_def in ['force', 'auto']) or item.ow_force == '1' or len(json_path_list) > 0:
|
||
# logger.error('ITEM cambiado')
|
||
# if it.emergency_urls:
|
||
# logger.error(it.emergency_urls)
|
||
# logger.error(item)
|
||
#
|
||
# return (item, it, overwrite)
|
||
return item, item, False
|
||
|
||
|
||
def verify_cached_torrents():
|
||
logger.info()
|
||
import json
|
||
|
||
"""
|
||
Verifica que todos los archivos .torrent estén descomprimidos. Si no lo están, los descomprime y regraba
|
||
|
||
Método para uso temporal y controlado
|
||
|
||
Deja el archivo verify_cached_torrents.json como marca de que se ha ejecutado para esa versión de Alfa
|
||
"""
|
||
|
||
try:
|
||
#Localiza los paths donde dejar el archivo .json de control, y de la Videoteca
|
||
json_path = filetools.exists(filetools.join(config.get_runtime_path(), 'verify_cached_torrents.json'))
|
||
if json_path:
|
||
logger.info('Torrents verificados anteriormente: NOS VAMOS')
|
||
return
|
||
json_path = filetools.join(config.get_runtime_path(), 'verify_cached_torrents.json')
|
||
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() #Calculamos el path absoluto a partir de la Videoteca
|
||
movies = config.get_setting("folder_movies")
|
||
series = config.get_setting("folder_tvshows")
|
||
torrents_movies = filetools.join(videolibrary_path, config.get_setting("folder_movies")) #path de CINE
|
||
torrents_series = filetools.join(videolibrary_path, config.get_setting("folder_tvshows")) #path de SERIES
|
||
|
||
#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()
|
||
|
||
#Recorre las carpetas de CINE y SERIES de la Videoteca, leyendo, descomprimiendo y regrabando los archivos .torrent
|
||
for contentType in torren_list:
|
||
for root, folders, files in filetools.walk(contentType):
|
||
for file in files:
|
||
if not '.torrent' in file:
|
||
continue
|
||
i += 1
|
||
torrent_file = ''
|
||
torrent_path = filetools.join(root, file)
|
||
torrent_file = filetools.read(torrent_path)
|
||
if not scrapertools.find_single_match(torrent_file, '^d\d+:\w+\d+:'):
|
||
logger.debug('Torrent comprimido: DESCOMPRIMIENDO: ' + str(torrent_path))
|
||
try:
|
||
torrent_file_deco = ''
|
||
import zlib
|
||
torrent_file_deco = zlib.decompressobj(16 + zlib.MAX_WBITS).decompress(torrent_file)
|
||
except:
|
||
k += 1
|
||
errores += [torrent_path]
|
||
logger.error(traceback.format_exc())
|
||
logger.error('No es un archivo TORRENT. Archivo borrado: ' + str(torrent_path))
|
||
if not json_data.get(root, False):
|
||
json_data[root] = 'ERROR'
|
||
if scrapertools.find_single_match(file, '^\d+x\d+'):
|
||
torrent_json = re.sub(r'\]_\d+.torrent$', '].json', torrent_path)
|
||
filetools.remove(torrent_json)
|
||
filetools.remove(torrent_path)
|
||
continue
|
||
|
||
if not scrapertools.find_single_match(torrent_file_deco, '^d\d+:\w+\d+:'):
|
||
logger.error('Error de DESCOMPRESIÓN: ' + str(torrent_path))
|
||
k += 1
|
||
errores += [torrent_path]
|
||
else:
|
||
filetools.write(torrent_path, torrent_file_deco)
|
||
j += 1
|
||
descomprimidos += [torrent_path]
|
||
else:
|
||
#logger.info('Torrent OK. No hace falta descompresión: ' + str(torrent_path))
|
||
h = 0
|
||
|
||
if json_data:
|
||
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({"torrent_verify": True}))
|
||
except:
|
||
logger.error('Error en el proceso de VERIFICACIÓN de los .torrents')
|
||
logger.error(traceback.format_exc())
|
||
|
||
logger.error(str(i) + ' archivos .torrent revisados. / ' + str(j) + ' descomporimidos / ' + str(k) + ' errores')
|
||
if descomprimidos:
|
||
logger.error('Lista de .torrents DESCOMPRIMIDOS: ' + str(descomprimidos))
|
||
if errores:
|
||
logger.error('Lista de .torrents en ERROR: ' + str(errores))
|
||
|
||
|
||
def regenerate_clones():
|
||
logger.info()
|
||
import json
|
||
from core import videolibrarytools
|
||
|
||
"""
|
||
Regenera los archivos .json que ha sido machacado con la migración. También borrar los archivos tvshow.nfo en
|
||
películas.
|
||
|
||
Método para uso temporal y controlado
|
||
"""
|
||
|
||
try:
|
||
#Localiza los paths donde dejar el archivo .json de control, y de la Videoteca
|
||
json_path = filetools.exists(filetools.join(config.get_runtime_path(), 'verify_cached_torrents.json'))
|
||
if json_path:
|
||
logger.info('Videoteca reparada anteriormente: NOS VAMOS')
|
||
return False
|
||
json_path = filetools.join(config.get_runtime_path(), 'verify_cached_torrents.json')
|
||
filetools.write(json_path, json.dumps({"CINE_verify": True})) #Evita que se lance otro proceso simultaneo
|
||
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() #Calculamos el path absoluto a partir de la Videoteca
|
||
movies = config.get_setting("folder_movies")
|
||
series = config.get_setting("folder_tvshows")
|
||
torrents_movies = filetools.join(videolibrary_path, config.get_setting("folder_movies")) #path de CINE
|
||
torrents_series = filetools.join(videolibrary_path, config.get_setting("folder_tvshows")) #path de SERIES
|
||
|
||
#Cargamos en .json de Newpct1 para ver las listas de valores en settings
|
||
fail_over_list = channeltools.get_channel_json(channel_py)
|
||
for settings in fail_over_list['settings']: #Se recorren todos los settings
|
||
if settings['id'] == "clonenewpct1_channels_list": #Encontramos en setting
|
||
fail_over_list = settings['default'] #Carga lista de 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()
|
||
|
||
#Recorre las carpetas de CINE y SERIES de la Videoteca, leyendo, descomprimiendo y regrabando los archivos .torrent
|
||
for contentType in torren_list:
|
||
for root, folders, files in filetools.walk(contentType):
|
||
nfo = ''
|
||
newpct1 = False
|
||
file_list = str(files)
|
||
logger.error(file_list)
|
||
|
||
#Borra los archivos Tvshow.nfo y verifica si el .nfo tiene más de un canal y uno es clone Newpct1
|
||
for file in files:
|
||
#logger.info('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: error de lectura en: ' + file)
|
||
break
|
||
if not nfo:
|
||
logger.error('** NFO: error de lectura en: ' + file)
|
||
break
|
||
if nfo.ow_force: #Si tiene ow_force lo quitamos para evitar futuros problemas
|
||
del nfo.ow_force
|
||
try:
|
||
filetools.write(filetools.join(root, file), head_nfo + nfo.tojson()) #actualizo el .nfo
|
||
except:
|
||
logger.error('** NFO: error de escritura en: ' + file)
|
||
break
|
||
|
||
if '.torrent' not in file_list and nfo.emergency_urls:
|
||
del nfo.emergency_urls #Si tiene emergency_urls, lo reseteamos
|
||
try:
|
||
filetools.write(filetools.join(root, file), head_nfo + nfo.tojson()) #actualizo el .nfo
|
||
except:
|
||
logger.error('** NFO: error de escritura en: ' + file)
|
||
break
|
||
newpct1 = True #marcamos par a resetar los .jsons
|
||
|
||
if len(nfo.library_urls) > 1: #Tiene más de un canal?
|
||
for canal, url in nfo.library_urls.items():
|
||
canal_json = "[%s].json" % canal
|
||
if canal_json not in file_list: #Canal zomby, lo borramos
|
||
logger.error('pop: ' + canal)
|
||
nfo.library_urls.pop(canal, None)
|
||
if nfo.emergency_urls:
|
||
del nfo.emergency_urls #Si tiene emergency_urls, lo reseteamos
|
||
try:
|
||
filetools.write(filetools.join(root, file), head_nfo + nfo.tojson()) #actualizo el .nfo
|
||
except:
|
||
logger.error('** NFO: error de escritura en: ' + file)
|
||
break
|
||
newpct1 = True #marcamos par a resetar los .jsons
|
||
|
||
canal_nwepct1 = "'%s'" % canal
|
||
if canal_nwepct1 in fail_over_list: #Algún canal es clone de Newpct1
|
||
newpct1 = True #Si es que sí, lo marcamos
|
||
if nfo.emergency_urls:
|
||
del nfo.emergency_urls #Si tiene emergency_urls, lo reseteamos
|
||
try:
|
||
filetools.write(filetools.join(root, file), head_nfo + nfo.tojson()) #actualizo el .nfo
|
||
except:
|
||
logger.error('** NFO: error de escritura en: ' + file)
|
||
break
|
||
|
||
#Zona para arrelgar los archivos .json
|
||
if not newpct1:
|
||
continue
|
||
for file in files:
|
||
file_path = filetools.join(root, file)
|
||
if '.json' in file:
|
||
logger.info('** file: ' + file)
|
||
canal_json = scrapertools.find_single_match(file, '\[(\w+)\].json')
|
||
if canal_json not in nfo.library_urls:
|
||
filetools.remove(file_path) #borramos el .json es un zomby
|
||
item_movie = ''
|
||
try:
|
||
item_movie = Item().fromjson(filetools.read(file_path)) #leemos el .json
|
||
except:
|
||
logger.error('** JSON: error de lectura en: ' + file)
|
||
continue
|
||
if not item_movie:
|
||
logger.error('** JSON: error de lectura en: ' + file)
|
||
continue
|
||
if item_movie.emergency_urls: del item_movie.emergency_urls
|
||
item_movie.channel = canal_json #mombre del canal
|
||
item_movie.category = canal_json.capitalize() #categoría
|
||
item_movie.url = nfo.library_urls[canal_json] #url
|
||
if scrapertools.find_single_match(item_movie.title, '(.*?)\[\d+.\d+\s*.\s*B\]'):
|
||
item_movie.title = scrapertools.find_single_match(item_movie.title, '(.*?)\[\d+.\d+\s*.\s*B\]').strip() #quitamos Size
|
||
if item_movie.added_replacing: del item_movie.added_replacing #quitamos traza del canal reemplazado
|
||
try:
|
||
filetools.write(file_path, item_movie.tojson()) #Salvamos el nuevo .json de la película
|
||
except:
|
||
logger.error('** JSON: error de escritura en: ' + file)
|
||
else:
|
||
errores += [file]
|
||
if '.torrent' in file:
|
||
filetools.remove(file_path) #borramos los .torrent salvados
|
||
|
||
|
||
logger.error('** Lista de peliculas reparadas: ' + 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) #borramos el bloqueo para que se pueda lanzar de nuevo
|
||
logger.error('Error en el proceso de REPARACIÓN de Videoteca de CINE')
|
||
logger.error(traceback.format_exc())
|
||
|
||
return True
|
||
|
||
|
||
def dejuice(data):
|
||
logger.info()
|
||
# Metodo para desobfuscar datos de JuicyCodes
|
||
|
||
import base64
|
||
from lib import jsunpack
|
||
|
||
juiced = scrapertools.find_single_match(data, '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| |<br>|\s{2,}', "", data)
|
||
packed = scrapertools.find_single_match(data, '(eval\(.*?);var')
|
||
unpacked = jsunpack.unpack(packed)
|
||
server = scrapertools.find_single_match(unpacked, "src:.'(http://\D+)/")
|
||
id = scrapertools.find_single_match(unpacked, "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 |