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