def resolve_video_urls_for_playing(server, url, video_password="", muestra_dialogo=False): """ Función para obtener la url real del vídeo @param server: Servidor donde está alojado el vídeo @type server: str @param url: url del vídeo @type url: str @param video_password: Password para el vídeo @type video_password: str @param muestra_dialogo: Muestra el diálogo de progreso @type muestra_dialogo: bool @return: devuelve la url del video @rtype: list """ logger.info("Server: %s, Url: %s" % (server, url)) server = server.lower() video_urls = [] video_exists = True error_messages = [] opciones = [] # Si el vídeo es "directo" o "local", no hay que buscar más if server == "directo" or server == "local": logger.info("Server: %s, la url es la buena" % server) video_urls.append(["%s [%s]" % (urlparse.urlparse(url)[2][-4:], server), url]) # Averigua la URL del vídeo else: if server: server_parameters = get_server_parameters(server) else: server_parameters = {} if server_parameters: # Muestra un diágo de progreso if muestra_dialogo: progreso = platformtools.dialog_progress("alfa", "Conectando con %s" % server_parameters["name"]) # Cuenta las opciones disponibles, para calcular el porcentaje orden = [ ["free"] + [server] + [premium for premium in server_parameters["premium"] if not premium == server], [server] + [premium for premium in server_parameters["premium"] if not premium == server] + ["free"], [premium for premium in server_parameters["premium"] if not premium == server] + [server] + ["free"] ] if server_parameters["free"] == True: opciones.append("free") opciones.extend( [premium for premium in server_parameters["premium"] if config.get_setting("premium", server=premium)]) priority = int(config.get_setting("resolve_priority")) opciones = sorted(opciones, key=lambda x: orden[priority].index(x)) logger.info("Opciones disponibles: %s | %s" % (len(opciones), opciones)) else: logger.error("No existe conector para el servidor %s" % server) error_messages.append("No existe conector para el servidor %s" % server) muestra_dialogo = False # Importa el server try: server_module = __import__('servers.%s' % server, None, None, ["servers.%s" % server]) logger.info("Servidor importado: %s" % server_module) except: server_module = None logger.error("No se ha podido importar el servidor: %s" % server) import traceback logger.error(traceback.format_exc()) # Si tiene una función para ver si el vídeo existe, lo comprueba ahora if hasattr(server_module, 'test_video_exists'): logger.info("Invocando a %s.test_video_exists" % server) try: video_exists, message = server_module.test_video_exists(page_url=url) if not video_exists: error_messages.append(message) logger.info("test_video_exists dice que el video no existe") else: logger.info("test_video_exists dice que el video SI existe") except: logger.error("No se ha podido comprobar si el video existe") import traceback logger.error(traceback.format_exc()) # Si el video existe y el modo free está disponible, obtenemos la url if video_exists: for opcion in opciones: # Opcion free y premium propio usa el mismo server if opcion == "free" or opcion == server: serverid = server_module server_name = server_parameters["name"] # Resto de opciones premium usa un debrider else: serverid = __import__('servers.debriders.%s' % opcion, None, None, ["servers.debriders.%s" % opcion]) server_name = get_server_parameters(opcion)["name"] # Muestra el progreso if muestra_dialogo: progreso.update((100 / len(opciones)) * opciones.index(opcion), "Conectando con %s" % server_name) # Modo free if opcion == "free": try: logger.info("Invocando a %s.get_video_url" % server) response = serverid.get_video_url(page_url=url, video_password=video_password) video_urls.extend(response) except: logger.error("Error al obtener la url en modo free") error_messages.append("Se ha producido un error en %s" % server_name) import traceback logger.error(traceback.format_exc()) # Modo premium else: try: logger.info("Invocando a %s.get_video_url" % opcion) response = serverid.get_video_url(page_url=url, premium=True, user=config.get_setting("user", server=opcion), password=config.get_setting("password", server=opcion), video_password=video_password) if response and response[0][1]: video_urls.extend(response) elif response and response[0][0]: error_messages.append(response[0][0]) else: error_messages.append("Se ha producido un error en %s" % server_name) except: logger.error("Error en el servidor: %s" % opcion) error_messages.append("Se ha producido un error en %s" % server_name) import traceback logger.error(traceback.format_exc()) # Si ya tenemos URLS, dejamos de buscar if video_urls and config.get_setting("resolve_stop") == True: break # Cerramos el progreso if muestra_dialogo: progreso.update(100, "Proceso finalizado") progreso.close() # Si no hay opciones disponibles mostramos el aviso de las cuentas premium if video_exists and not opciones and server_parameters.get("premium"): listapremium = [get_server_parameters(premium)["name"] for premium in server_parameters["premium"]] error_messages.append( "Para ver un vídeo en %s necesitas<br/>una cuenta en: %s" % (server, " o ".join(listapremium))) # Si no tenemos urls ni mensaje de error, ponemos uno generico elif not video_urls and not error_messages: error_messages.append("Se ha producido un error en %s" % get_server_parameters(server)["name"]) return video_urls, len(video_urls) > 0, "<br/>".join(error_messages)
import re from core import httptools from core import scrapertools from core import servertools from core.item import Item from core.scrapertools import decodeHtmlentities as dhe from platformcode import logger from platformcode import config from core import tmdb from channelselector import get_thumb from channels import filtertools from channels import autoplay __comprueba_enlaces__ = config.get_setting('comprueba_enlaces', 'peliculasdk') __comprueba_enlaces_num__ = config.get_setting('comprueba_enlaces_num', 'peliculasdk') __adult_mode__ = config.get_setting("adult_mode") host = "http://www.peliculasdk.com" IDIOMAS = { 'es': 'Español', 'la': 'Latino', 'su': 'Subtitulado', 'in': 'Inglés' } list_language = IDIOMAS.values() list_quality = [ 'HD-1080', 'HD-720', 'HD-320', 'BR-R', 'BR-S', 'DVD-R', 'DVD-S', 'TS-HQ',
def novedades(item): logger.info() global list_newest threads = [] list_newest = [] start_time = time.time() mode = item.mode if mode == '': mode = 'normal' if mode == 'get_cached': if os.path.exists(menu_cache_path): return get_from_cache(item) multithread = config.get_setting("multithread", "news") logger.info("multithread= " + str(multithread)) if not multithread: if platformtools.dialog_yesno(config.get_localized_string(60515), config.get_localized_string(60516), config.get_localized_string(60517), config.get_localized_string(60518)): if config.set_setting("multithread", True, "news"): multithread = True if mode == 'normal': progreso = platformtools.dialog_progress( item.category, config.get_localized_string(60519)) list_canales, any_active = get_channels_list() if config.is_xbmc(): from channels import side_menu if mode == 'silent' and any_active and len( list_canales[item.extra]) > 0: side_menu.set_menu_settings(item) aux_list = [] for canal in list_canales[item.extra]: if len(aux_list) < 2: aux_list.append(canal) list_canales[item.extra] = aux_list if mode == 'set_cache': list_canales[item.extra] = list_canales[item.extra][2:] if any_active and len(list_canales[item.extra]) > 0: import math # fix float porque la division se hace mal en python 2.x number_of_channels = float(100) / len(list_canales[item.extra]) for index, channel in enumerate(list_canales[item.extra]): channel_id, channel_title = channel percentage = int(math.ceil((index + 1) * number_of_channels)) # if progreso.iscanceled(): # progreso.close() # logger.info("Búsqueda cancelada") # return itemlist # Modo Multi Thread if multithread: t = Thread(target=get_newest, args=[channel_id, item.extra], name=channel_title) t.start() threads.append(t) if mode == 'normal': progreso.update( percentage, "" + '\n' + config.get_localized_string(60520) % channel_title) # Modo single Thread else: if mode == 'normal': logger.info("Obteniendo novedades de channel_id=" + channel_id) progreso.update( percentage, "" + '\n' + config.get_localized_string(60520) % channel_title) get_newest(channel_id, item.extra) # Modo Multi Thread: esperar q todos los hilos terminen if multithread: pendent = [a for a in threads if a.isAlive()] t = float(100) / len(pendent) while pendent: index = (len(threads) - len(pendent)) + 1 percentage = int(math.ceil(index * t)) list_pendent_names = [a.getName() for a in pendent] if mode == 'normal': mensaje = config.get_localized_string(30994) % ( ", ".join(list_pendent_names)) progreso.update( percentage, config.get_localized_string(60521) % (len(threads) - len(pendent), len(threads)) + '\n' + mensaje + '\n' + ' ' + '\n' + ' ') logger.debug(mensaje) if progreso.iscanceled(): logger.info("Busqueda de novedades cancelada") break time.sleep(0.5) pendent = [a for a in threads if a.isAlive()] if mode == 'normal': mensaje = config.get_localized_string(60522) % ( len(list_newest), time.time() - start_time) progreso.update(100, mensaje + '\n' + " " + '\n' + " " + '\n' + " ") logger.info(mensaje) start_time = time.time() # logger.debug(start_time) result_mode = config.get_setting("result_mode", "news") if mode != 'normal': result_mode = 0 if result_mode == 0: # Agrupados por contenido ret = group_by_content(list_newest) elif result_mode == 1: # Agrupados por canales ret = group_by_channel(list_newest) else: # Sin agrupar ret = no_group(list_newest) while time.time() - start_time < 2: # mostrar cuadro de progreso con el tiempo empleado durante almenos 2 segundos time.sleep(0.5) if mode == 'normal': progreso.close() if mode == 'silent': set_cache(item) item.mode = 'set_cache' ret = add_menu_items(item, ret) if mode != 'set_cache': return ret else: if mode != 'set_cache': no_channels = platformtools.dialog_ok( 'Novedades - %s' % item.extra, 'No se ha definido ningun canal para la ' 'busqueda.', 'Utilice el menu contextual ' 'para agregar al menos uno') return
title=fulltitle, thumbnail=thumbnail, plot=plot, fanart=thumbnail, fulltitle=fulltitle, folder=False) filetools.rename(filetools.join(readpath, fichero), fichero[:-4] + ".old") itemlist.append(item) # Si hay Favoritos q guardar if itemlist: favourites_list = read_favourites() for item in itemlist: data = "ActivateWindow(10025,"plugin://plugin.video.alfa/?" + item.tourl( ) + "",return)" favourites_list.append((item.title, item.thumbnail, data)) if save_favourites(favourites_list): logger.debug("Conversion de txt a xml correcta") # Esto solo funcionara al migrar de versiones anteriores, ya no existe "bookmarkpath" try: if config.get_setting("bookmarkpath") != "": check_bookmark(config.get_setting("bookmarkpath")) else: logger.info("No existe la ruta a los favoritos de versiones antiguas") except: pass
def comprobar_actualizaciones(): if config.get_setting('addon_update_atstart', default=False): from platformcode import updater updater.check_addon_updates(verbose=config.get_setting('addon_update_verbose', default=False))
def list_latest(item): logger.info() itemlist = [] if not item.desde: item.desde = 0 perpage = 20 if item.search_type == 'tvshow': color = config.get_setting('context_tracking_color', default='blue') data = do_downloadpage(item.url).decode('iso-8859-1').encode('utf8') # ~ logger.debug(data) matches = re.compile("<div class='online'><table><tr>(.*?)</tr></table></div>", re.DOTALL).findall(data) num_matches = len(matches) if num_matches == 0: return itemlist # Como len(matches)=300, se controla una paginación interna y se muestran en bloques de 20 (perpage) # Se descartan enlaces repetidos en la misma paginación pq algunas pelis se duplican por el idioma/calidad pero apuntan a la misma url for n, elemento in enumerate(matches[item.desde:]): url = scrapertools.find_single_match(elemento, ' href=([^ ]+)') thumb = scrapertools.find_single_match(elemento, ' src=([^ ]+)') title = scrapertools.find_single_match(elemento, ' alt="([^"]+)') language = scrapertools.find_single_match(elemento, '<div class="s7">([^<]+)') # ~ if '-z' in language: continue # descartar descargas directas # ~ lang = _extraer_idioma(language) # No se muestran los idiomas pq sólo se indican los modificados y normalmente hay más, por lo que puede llevar a engaño. if item.search_type == 'movie': vid = scrapertools.find_single_match(url, '/([^/]+)$') url = host + 'secure/titles/' + vid + '?titleId=' + vid if url in [it.url for it in itemlist]: continue # descartar repetidos itemlist.append(item.clone( action='findvideos', url=url, title=title, thumbnail=thumb, contentType='movie', contentTitle=title, infoLabels={'year': '-'} )) else: vid, season, episode = scrapertools.find_single_match(url, '/(\d+)/season/(\d+)/episode/(\d+)$') url_serie = host + 'secure/titles/' + vid + '?titleId=' + vid url_tempo = url_serie + '&seasonNumber=' + season url = url_tempo + '&episodeNumber=' + episode if url in [it.url for it in itemlist]: continue # descartar repetidos show = title.replace(' %sx%s' % (season, episode), '').strip() # Menú contextual: ofrecer acceso a temporada / serie contextual = [] contextual.append({ 'title': '[COLOR pink]Listar temporada %s[/COLOR]' % season, 'action': 'episodios', 'url': url_tempo, 'context': '', 'folder': True, 'link_mode': 'update' }) contextual.append({ 'title': '[COLOR pink]Listar temporadas[/COLOR]', 'action': 'temporadas', 'url': url_serie, 'context': '', 'folder': True, 'link_mode': 'update' }) itemlist.append(item.clone( action='findvideos', url=url, title=title, thumbnail=thumb, context=contextual, contentType='episode', contentSerieName=show, contentSeason=season, contentEpisodeNumber=episode )) if len(itemlist) >= perpage: break tmdb.set_infoLabels(itemlist) # Paginación if item.desde + n + 1 < num_matches: itemlist.append(item.clone( title='>> Página siguiente', desde=item.desde + n + 1, action='list_latest' )) return itemlist
# config.set_setting(name=data[channel_file], value="value", channel=channel_file) # except: pass #channel not in json if __name__ == "__main__": # Se ejecuta en cada inicio import xbmc import time # modo adulto: # sistema actual 0: Nunca, 1:Siempre, 2:Solo hasta que se reinicie Kodi # si es == 2 lo desactivamos. if config.get_platform(True)['num_version'] >= 17.0: from lib.alfaresolver import updated, update_now if not updated(): update_now() if config.get_setting("adult_mode") == 2: config.set_setting("adult_mode", 0) update_wait = [0, 10000, 20000, 30000, 60000] wait = update_wait[int(config.get_setting("update_wait", "videolibrary"))] if wait > 0: xbmc.sleep(wait) # Verificar quick-fixes al abrirse Kodi, y dejarlo corriendo como Thread if not config.dev_mode(): from platformcode import updater updater.check_addon_init() # get_channel_json() -> disabilitato, lo si fa con l'updater # Copia Custom code a las carpetas de Alfa desde la zona de Userdata from platformcode import custom_code
def list_all(item): logger.info itemlist = list() next = False data = httptools.downloadpage(item.url).data soup = BeautifulSoup(data, "html5lib", from_encoding="utf-8") matches = soup.find_all("div", class_="post") first = item.first last = first + 20 if last >= len(matches): last = len(matches) next = True for elem in matches[first:last]: title = "" url = elem.a["href"] thumb = elem.img["src"] langs = elem.find("div", "tituloidioma") language = languages_from_flags(langs, "png") full_title = elem.find("div", class_="title").text.split('(') cleantitle = full_title[0] if len(full_title) > 1: year = re.sub('\)', '', full_title[1]) else: year = '-' if not config.get_setting('unify'): title = '%s [%s] %s' % (cleantitle, year, language) itemlist.append( Item(channel=item.channel, title='%s' % title, url=url, action='findvideos', contentTitle=cleantitle, thumbnail=thumb, language=language, infoLabels={'year': year})) tmdb.set_infoLabels_itemlist(itemlist, True) # Pagination if not next: url_next_page = item.url first = last else: try: current = soup.find("span", class_="current").text except: return itemlist url_next_page = '%spage/%s' % (host, str(int(current) + 1)) first = 0 if url_next_page and len(matches) > 21: itemlist.append( Item(channel=item.channel, title="Siguiente >>", url=url_next_page, action='list_all', first=first)) return itemlist
def findvideos(item): logger.info() itemlist = list() data = httptools.downloadpage(item.url).data data = scrapertools.unescape(data) soup = BeautifulSoup(data, "html5lib", from_encoding="utf-8") lang = soup.find_all("b") lang_list = get_langs(lang) lang_count = 0 for tab_soup in soup.find_all("div", class_="contenedor_tab"): lang = lang_list[lang_count] for elem in tab_soup.find_all("iframe"): title = "" enc_url = scrapertools.find_single_match(elem["data-data"], '([^\+]+)\+(.+)?') s = base64.b64decode(enc_url[0]) i = enc_url[1] hidden_url = "https://encriptando.com" + s + i hidden_data = httptools.downloadpage(hidden_url, follow_redirects=False, headers={ 'Referer': host }).data var, val = scrapertools.find_single_match( hidden_data.replace("'", '"'), 'var (k|s)="([^"]+)";') url = decrypt(var, val) if var == "k": url += "|%s" % item.url if not config.get_setting('unify'): title = ' [%s]' % lang itemlist.append( Item(channel=item.channel, title='%s' + title, url=url, action='play', language=lang, infoLabels=item.infoLabels)) lang_count += 1 itemlist = servertools.get_servers_itemlist( itemlist, lambda x: x.title % x.server.capitalize()) # Requerido para FilterTools itemlist = filtertools.get_links(itemlist, item, list_language) # Requerido para AutoPlay autoplay.start(itemlist, item) if config.get_videolibrary_support( ) and len(itemlist) > 0 and item.extra != 'findvideos': itemlist.append( Item(channel=item.channel, title= '[COLOR yellow]Añadir esta pelicula a la videoteca[/COLOR]', url=item.url, action="add_pelicula_to_library", extra="findvideos", contentTitle=item.contentTitle)) return itemlist
def mainlist(item): logger.info() itemlist = [] list_canales, any_active = get_channels_list() channel_language = config.get_setting("channel_language", default="auto") if channel_language == 'auto': channel_language = auto_filter() #if list_canales['peliculas']: thumbnail = get_thumb("channels_movie.png") new_item = Item(channel=item.channel, action="novedades", extra="peliculas", title=config.get_localized_string(30122), thumbnail=thumbnail) set_category_context(new_item) itemlist.append(new_item) # thumbnail = get_thumb("channels_movie_4k.png") # new_item = Item(channel=item.channel, action="novedades", extra="4k", title=config.get_localized_string(70208), thumbnail=thumbnail) # # set_category_context(new_item) # itemlist.append(new_item) #if list_canales['terror']: # thumbnail = get_thumb("channels_horror.png") # new_item = Item(channel=item.channel, action="novedades", extra="terror", title=config.get_localized_string(70209), # thumbnail=thumbnail) # set_category_context(new_item) # itemlist.append(new_item) #if list_canales['infantiles']: # thumbnail = get_thumb("channels_children.png") # new_item = Item(channel=item.channel, action="novedades", extra="infantiles", title=config.get_localized_string(60510), # thumbnail=thumbnail) # set_category_context(new_item) # itemlist.append(new_item) #if list_canales['series']: thumbnail = get_thumb("channels_tvshow.png") new_item = Item(channel=item.channel, action="novedades", extra="series", title=config.get_localized_string(60511), thumbnail=thumbnail) set_category_context(new_item) itemlist.append(new_item) #if list_canales['anime']: thumbnail = get_thumb("channels_anime.png") new_item = Item(channel=item.channel, action="novedades", extra="anime", title=config.get_localized_string(60512), thumbnail=thumbnail) set_category_context(new_item) itemlist.append(new_item) if channel_language == "all": # if list_canales['Italiano']: thumbnail = get_thumb("channels_italian.png") new_item = Item(channel=item.channel, action="novedades", extra="italiano", title=config.get_localized_string(70563), thumbnail=thumbnail) set_category_context(new_item) itemlist.append(new_item) # if list_canales['Torrent']: # thumbnail = get_thumb("channels_torrent.png") # new_item = Item(channel=item.channel, action="novedades", extra="torrent", title=config.get_localized_string(70171), thumbnail=thumbnail) # set_category_context(new_item) # itemlist.append(new_item) #if list_canales['documentales']: thumbnail = get_thumb("channels_documentary.png") new_item = Item(channel=item.channel, action="novedades", extra="documentales", title=config.get_localized_string(60513), thumbnail=thumbnail) set_category_context(new_item) itemlist.append(new_item) return itemlist
def setting_channel(item): channels_path = os.path.join(config.get_runtime_path(), "channels", '*.json') channel_language = config.get_setting("channel_language", default="auto") if channel_language == 'auto': channel_language = auto_filter() list_controls = [] for infile in sorted(glob.glob(channels_path)): channel_id = os.path.basename(infile)[:-5] channel_parameters = channeltools.get_channel_parameters(channel_id) # No incluir si es un canal inactivo if not channel_parameters["active"]: continue # No incluir si es un canal para adultos, y el modo adulto está desactivado if channel_parameters["adult"] and config.get_setting( "adult_mode") == 0: continue # No incluir si el canal es en un idioma filtrado if channel_language != "all" and channel_language not in channel_parameters["language"] \ and "*" not in channel_parameters["language"]: continue # No incluir si en su configuracion el canal no existe 'include_in_newest' include_in_newest = config.get_setting( "include_in_newest_" + item.extra, channel_id) if include_in_newest is None: continue control = { 'id': channel_id, 'type': "bool", 'label': channel_parameters["title"], 'default': include_in_newest, 'enabled': True, 'visible': True } list_controls.append(control) caption = config.get_localized_string(60533) + item.title.replace( config.get_localized_string(60525), "- ").strip() if config.get_setting("custom_button_value_news", item.channel): custom_button_label = config.get_localized_string(59992) else: custom_button_label = config.get_localized_string(59991) return platformtools.show_channel_settings(list_controls=list_controls, caption=caption, callback="save_settings", item=item, custom_button={ 'visible': True, 'function': "cb_custom_button", 'close': False, 'label': custom_button_label })
def onInit(self): self.setCoordinateResolution(2) self.focus = -1 self.buttons = [] posx= 0 posy= 145 space = 30 selected = 'selected0.png' width = 260 height = 30 textcolor = "0xffffd700" conditional_textcolor = "0xffff3030" shadow = "0xFF000000" offsetx = 30 offsety = 0 font = 'font25_title' if config.get_setting('start_page'): label = 'Inicio' self.button_start = xbmcgui.ControlButton(posx, posy, width, height, label, font=font, alignment=0x00000000, noFocusTexture='', focusTexture=media_path + selected, textColor=textcolor, shadowColor=shadow, textOffsetX=offsetx, textOffsetY=offsety) self.addControl(self.button_start) self.buttons.append(self.button_start) posy += space * 2 label = 'Menú Clasico' self.button_alfa = xbmcgui.ControlButton(posx, posy, width, height, label, font=font, alignment=0x00000000, noFocusTexture='', focusTexture=media_path+selected, textColor=textcolor, shadowColor=shadow, textOffsetX=offsetx, textOffsetY=offsety) self.addControl(self.button_alfa) self.buttons.append(self.button_alfa) posy += space label = 'Configuracion' self.button_config = xbmcgui.ControlButton(posx, posy, width, height, label, font=font, alignment=0x00000000, noFocusTexture='', focusTexture=media_path + selected, textColor=textcolor, shadowColor=shadow, textOffsetX=offsetx, textOffsetY=offsety) self.addControl(self.button_config) self.buttons.append(self.button_config) posy += space*2 label = 'Peliculas' self.button_peliculas = xbmcgui.ControlButton(posx, posy, width, height, label, font=font, alignment=0x00000000, noFocusTexture='', focusTexture=media_path+selected, textColor=textcolor, shadowColor=shadow, textOffsetX=offsetx, textOffsetY=offsety) self.addControl(self.button_peliculas) self.buttons.append(self.button_peliculas) posy += space label = 'Series' self.button_series = xbmcgui.ControlButton(posx, posy, width, height, label, font=font, alignment=0x00000000, noFocusTexture='', focusTexture=media_path+selected, textColor=textcolor, shadowColor=shadow, textOffsetX=offsetx, textOffsetY=offsety) self.addControl(self.button_series) self.buttons.append(self.button_series) posy += space label = 'Anime' self.button_anime = xbmcgui.ControlButton(posx, posy, width, height, label, font=font, alignment=0x00000000, noFocusTexture='', focusTexture=media_path+selected, textColor=textcolor, shadowColor=shadow, textOffsetX=offsetx, textOffsetY=offsety) self.addControl(self.button_anime) self.buttons.append(self.button_anime) posy += space label = 'Infantiles' self.button_infantil = xbmcgui.ControlButton(posx, posy, width, height, label, font=font, alignment=0x00000000, noFocusTexture='', focusTexture=media_path+selected, textColor=textcolor, shadowColor=shadow, textOffsetX=offsetx, textOffsetY=offsety) self.addControl(self.button_infantil) self.buttons.append(self.button_infantil) posy += space label = 'Documentales' self.button_docu = xbmcgui.ControlButton(posx, posy, width, height, label, font=font, alignment=0x00000000, noFocusTexture='', focusTexture=media_path + selected, textColor=textcolor, shadowColor=shadow, textOffsetX=offsetx, textOffsetY=offsety) self.addControl(self.button_docu) self.buttons.append(self.button_docu) posy += space label = 'Terror' self.button_terror = xbmcgui.ControlButton(posx, posy, width, height, label, font=font, alignment=0x00000000, noFocusTexture='', focusTexture=media_path+selected, textColor=textcolor, shadowColor=shadow, textOffsetX=offsetx, textOffsetY=offsety) self.addControl(self.button_terror) self.buttons.append(self.button_terror) posy += space label = 'Latino' self.button_lat = xbmcgui.ControlButton(posx, posy, width, height, label, font=font, alignment=0x00000000, noFocusTexture='', focusTexture=media_path+selected, textColor=textcolor, shadowColor=shadow, textOffsetX=offsetx, textOffsetY=offsety) self.addControl(self.button_lat) self.buttons.append(self.button_lat) posy += space label = 'Castellano' self.button_cast = xbmcgui.ControlButton(posx, posy, width, height, label, font=font, alignment=0x00000000, noFocusTexture='', focusTexture=media_path + selected, textColor=textcolor, shadowColor=shadow, textOffsetX=offsetx, textOffsetY=offsety) self.addControl(self.button_cast) self.buttons.append(self.button_cast) posy += space label = 'Torrents' self.button_torrent = xbmcgui.ControlButton(posx, posy, width, height, label, font=font, alignment=0x00000000, noFocusTexture='', focusTexture=media_path+selected, textColor=textcolor, shadowColor=shadow, textOffsetX=offsetx, textOffsetY=offsety) self.addControl(self.button_torrent) self.buttons.append(self.button_torrent) start_page_item = get_start_page() if config.get_setting('start_page') and start_page_item.channel =='news': posy += space label = 'Canales Activos' self.button_config = xbmcgui.ControlButton(posx, posy, width, height, label, font=font, alignment=0x00000000, noFocusTexture='', focusTexture=media_path+selected, textColor=conditional_textcolor, shadowColor=shadow, textOffsetX=offsetx, textOffsetY=offsety) self.addControl(self.button_config) self.buttons.append(self.button_config) posy += space*2 label = 'Buscar' self.button_buscar = xbmcgui.ControlButton(posx, posy, width, height, label, font=font, alignment=0x00000000, noFocusTexture='', focusTexture=media_path + selected, textColor=textcolor, shadowColor=shadow, textOffsetX=offsetx, textOffsetY=offsety) self.addControl(self.button_buscar) self.buttons.append(self.button_buscar) posy += space label = 'Buscar Actor' self.button_actor = xbmcgui.ControlButton(posx, posy, width, height, label, font=font, alignment=0x00000000, noFocusTexture='', focusTexture=media_path + selected, textColor=textcolor, shadowColor=shadow, textOffsetX=offsetx, textOffsetY=offsety) self.addControl(self.button_actor) self.buttons.append(self.button_actor) posy += space label = 'Donde Buscar' self.button_config_search = xbmcgui.ControlButton(posx, posy, width, height, label, font=font, alignment=0x00000000, noFocusTexture='', focusTexture=media_path + selected, textColor=conditional_textcolor, shadowColor=shadow, textOffsetX=offsetx, textOffsetY=offsety) self.addControl(self.button_config_search) self.buttons.append(self.button_config_search) label='' self.button_close = xbmcgui.ControlButton(260, 0, 1020, 725, label, noFocusTexture='', focusTexture='') self.addControl(self.button_close)
# ------------------------------------------------------------ import os from core.item import Item from core import jsontools from platformcode import config, logger from platformcode import launcher import xbmc, xbmcgui, xbmcplugin, xbmcaddon media_path = os.path.join(config.get_runtime_path(), "resources/skins/Default/media/side_menu/") menu_settings_path = os.path.join(config.get_data_path(), "settings_channels", 'menu_settings_data.json') if os.path.exists(menu_settings_path): menu_node = jsontools.get_node_from_file('menu_setting_data.json', 'menu') else: menu_node = {'categoria actual':config.get_setting('category')} jsontools.update_node(menu_node, 'menu_settings_data.json', "menu") ACTION_SHOW_FULLSCREEN = 36 ACTION_GESTURE_SWIPE_LEFT = 511 ACTION_SELECT_ITEM = 7 ACTION_PREVIOUS_MENU = 10 ACTION_MOVE_LEFT = 1 ACTION_MOVE_RIGHT = 2 ACTION_MOVE_DOWN = 4 ACTION_MOVE_UP = 3 def set_menu_settings(item): if os.path.exists(menu_settings_path):
headers = "" def findhost(): global host, headers permUrl = httptools.downloadpage('https://www.cb01.uno/', follow_redirects=False).headers host = 'https://www.' + permUrl['location'].replace( 'https://www.google.it/search?q=site:', '') headers = [['Referer', host]] list_servers = ['verystream', 'openload', 'streamango', 'wstream'] list_quality = ['HD', 'SD', 'default'] checklinks = config.get_setting('checklinks', 'cineblog01') checklinks_number = config.get_setting('checklinks_number', 'cineblog01') # esclusione degli articoli 'di servizio' blacklist = [ 'BENVENUTI', 'Richieste Serie TV', 'CB01.UNO ▶ TROVA L’INDIRIZZO UFFICIALE ', 'Aggiornamento Quotidiano Serie TV', 'OSCAR 2019 â–¶ CB01.UNO: Vota il tuo film preferito! 🎬', 'Openload: la situazione. Benvenuto Verystream', 'Openload: lo volete ancora?' ] @support.menu def mainlist(item):
def mark_content_as_watched_on_alfa(path): from channels import videolibrary from core import videolibrarytools """ marca toda la serie o película como vista o no vista en la Videoteca de Alfa basado en su estado en la Videoteca de Kodi @type str: path @param path: carpeta de contenido a marcar """ logger.info() #logger.debug("path: " + path) FOLDER_MOVIES = config.get_setting("folder_movies") FOLDER_TVSHOWS = config.get_setting("folder_tvshows") VIDEOLIBRARY_PATH = config.get_videolibrary_config_path() if not VIDEOLIBRARY_PATH: return # Solo podemos marcar el contenido como vista en la BBDD de Kodi si la BBDD es local, # en caso de compartir BBDD esta funcionalidad no funcionara #if config.get_setting("db_mode", "videolibrary"): # return path2 = '' if "special://" in VIDEOLIBRARY_PATH: if FOLDER_TVSHOWS in path: path2 = re.sub(r'.*?%s' % FOLDER_TVSHOWS, VIDEOLIBRARY_PATH + "/" + FOLDER_TVSHOWS, path).replace("\\", "/") if FOLDER_MOVIES in path: path2 = re.sub(r'.*?%s' % FOLDER_MOVIES, VIDEOLIBRARY_PATH + "/" + FOLDER_MOVIES, path).replace("\\", "/") if "\\" in path: path = path.replace("/", "\\") head_nfo, item = videolibrarytools.read_nfo( path) #Leo el .nfo del contenido if not item or not isinstance(item.library_playcounts, dict): logger.error('.NFO no encontrado o erroneo: ' + path) return if FOLDER_TVSHOWS in path: #Compruebo si es CINE o SERIE contentType = "episode_view" #Marco la tabla de BBDD de Kodi Video nfo_name = "tvshow.nfo" #Construyo el nombre del .nfo path1 = path.replace("\\\\", "\\").replace( nfo_name, '') #para la SQL solo necesito la carpeta if not path2: path2 = path1.replace("\\", "/") #Formato no Windows else: path2 = path2.replace(nfo_name, '') else: contentType = "movie_view" #Marco la tabla de BBDD de Kodi Video path1 = path.replace("\\\\", "\\") #Formato Windows if not path2: path2 = path1.replace("\\", "/") #Formato no Windows nfo_name = scrapertools.find_single_match( path2, '\]\/(.*?)$') #Construyo el nombre del .nfo path1 = path1.replace(nfo_name, '') #para la SQL solo necesito la carpeta path2 = path2.replace(nfo_name, '') #para la SQL solo necesito la carpeta path2 = filetools.remove_smb_credential( path2 ) #Si el archivo está en un servidor SMB, quitamos las credenciales #Ejecutmos la sentencia SQL sql = 'select strFileName, playCount from %s where (strPath like "%s" or strPath like "%s")' % ( contentType, path1, path2) nun_records = 0 records = None nun_records, records = execute_sql_kodi(sql) #ejecución de la SQL if nun_records == 0: #hay error? logger.error("Error en la SQL: " + sql + ": 0 registros") return #salimos: o no está catalogado en Kodi, o hay un error en la SQL for title, playCount in records: #Ahora recorremos todos los registros obtenidos if contentType == "episode_view": title_plain = title.replace( '.strm', '') #Si es Serie, quitamos el sufijo .strm else: title_plain = scrapertools.find_single_match( item.strm_path, '.(.*?\s\[.*?\])') #si es peli, quitamos el título if playCount is None or playCount == 0: #todavía no se ha visto, lo ponemos a 0 playCount_final = 0 elif playCount >= 1: playCount_final = 1 elif not PY3 and isinstance(title_plain, (str, unicode)): title_plain = title_plain.decode("utf-8").encode( "utf-8" ) #Hacemos esto porque si no genera esto: u'title_plain' elif PY3 and isinstance(var, bytes): title_plain = title_plain.decode('utf-8') item.library_playcounts.update({title_plain: playCount_final }) #actualizamos el playCount del .nfo if item.infoLabels[ 'mediatype'] == "tvshow": #Actualizamos los playCounts de temporadas y Serie for season in item.library_playcounts: if "season" in season: #buscamos las etiquetas "season" dentro de playCounts season_num = int( scrapertools.find_single_match( season, 'season (\d+)')) #salvamos el núm, de Temporada item = videolibrary.check_season_playcount( item, season_num ) #llamamos al método que actualiza Temps. y Series filetools.write(path, head_nfo + item.tojson())
from core.item import Item from core import channeltools, servertools, scrapertools from platformcode import platformtools, config, logger from platformcode.launcher import run from threading import Thread from specials.search import save_search if sys.version_info[0] >= 3: PY3 = True from concurrent import futures else: PY3 = False from concurrent_py2 import futures info_language = ["de", "en", "es", "fr", "it", "pt"] # from videolibrary.json def_lang = info_language[config.get_setting("info_language", "videolibrary")] close_action = False update_lock = threading.Lock() moduleDict = {} searchActions = [] def busy(state): if state: xbmc.executebuiltin('ActivateWindow(busydialognocancel)') else: xbmc.executebuiltin('Dialog.Close(busydialognocancel)') def set_workers(): workers = config.get_setting( 'thread_number') if config.get_setting('thread_number') > 0 else None return workers
def set_content(content_type, silent=False): """ Procedimiento para auto-configurar la videoteca de kodi con los valores por defecto @type content_type: str ('movie' o 'tvshow') @param content_type: tipo de contenido para configurar, series o peliculas """ continuar = True msg_text = "" videolibrarypath = config.get_setting("videolibrarypath") if content_type == 'movie': scraper = [ config.get_localized_string(70093), config.get_localized_string(70096) ] seleccion = platformtools.dialog_select( config.get_localized_string(70094), scraper) # Instalar The Movie Database if seleccion == -1 or seleccion == 0: if not xbmc.getCondVisibility( 'System.HasAddon(metadata.themoviedb.org)'): if not silent: # Preguntar si queremos instalar metadata.themoviedb.org install = platformtools.dialog_yesno( config.get_localized_string(60046)) else: install = True if install: try: # Instalar metadata.themoviedb.org xbmc.executebuiltin( 'InstallAddon(metadata.themoviedb.org)', True) logger.info( "Instalado el Scraper de películas de TheMovieDB") except: pass continuar = (install and xbmc.getCondVisibility( 'System.HasAddon(metadata.themoviedb.org)')) if not continuar: msg_text = config.get_localized_string(60047) if continuar: xbmc.executebuiltin( 'Addon.OpenSettings(metadata.themoviedb.org)', True) # Instalar Universal Movie Scraper elif seleccion == 1: if continuar and not xbmc.getCondVisibility( 'System.HasAddon(metadata.universal)'): continuar = False if not silent: # Preguntar si queremos instalar metadata.universal install = platformtools.dialog_yesno( config.get_localized_string(70095)) else: install = True if install: try: xbmc.executebuiltin('InstallAddon(metadata.universal)', True) if xbmc.getCondVisibility( 'System.HasAddon(metadata.universal)'): continuar = True except: pass continuar = (install and continuar) if not continuar: msg_text = config.get_localized_string(70097) if continuar: xbmc.executebuiltin('Addon.OpenSettings(metadata.universal)', True) else: # SERIES scraper = [ config.get_localized_string(70098), config.get_localized_string(70093) ] seleccion = platformtools.dialog_select( config.get_localized_string(70107), scraper) # Instalar The TVDB if seleccion == -1 or seleccion == 0: if not xbmc.getCondVisibility( 'System.HasAddon(metadata.tvdb.com)'): if not silent: # Preguntar si queremos instalar metadata.tvdb.com install = platformtools.dialog_yesno( config.get_localized_string(60048)) else: install = True if install: try: # Instalar metadata.tvdb.com xbmc.executebuiltin('InstallAddon(metadata.tvdb.com)', True) logger.info( "Instalado el Scraper de series de The TVDB") except: pass continuar = (install and xbmc.getCondVisibility( 'System.HasAddon(metadata.tvdb.com)')) if not continuar: msg_text = config.get_localized_string(70099) if continuar: xbmc.executebuiltin('Addon.OpenSettings(metadata.tvdb.com)', True) # Instalar The Movie Database elif seleccion == 1: if continuar and not xbmc.getCondVisibility( 'System.HasAddon(metadata.tvshows.themoviedb.org)'): continuar = False if not silent: # Preguntar si queremos instalar metadata.tvshows.themoviedb.org install = platformtools.dialog_yesno( config.get_localized_string(70100)) else: install = True if install: try: # Instalar metadata.tvshows.themoviedb.org xbmc.executebuiltin( 'InstallAddon(metadata.tvshows.themoviedb.org)', True) if xbmc.getCondVisibility( 'System.HasAddon(metadata.tvshows.themoviedb.org)' ): continuar = True except: pass continuar = (install and continuar) if not continuar: msg_text = config.get_localized_string(60047) if continuar: xbmc.executebuiltin( 'Addon.OpenSettings(metadata.tvshows.themoviedb.org)', True) idPath = 0 idParentPath = 0 if continuar: continuar = False # Buscamos el idPath sql = 'SELECT MAX(idPath) FROM path' nun_records, records = execute_sql_kodi(sql) if nun_records == 1: idPath = records[0][0] + 1 sql_videolibrarypath = videolibrarypath if sql_videolibrarypath.startswith("special://"): sql_videolibrarypath = sql_videolibrarypath.replace( '/profile/', '/%/').replace('/home/userdata/', '/%/') sep = '/' elif scrapertools.find_single_match(sql_videolibrarypath, '(^\w+:\/\/)'): sep = '/' else: sep = os.sep if not sql_videolibrarypath.endswith(sep): sql_videolibrarypath += sep # Buscamos el idParentPath sql = 'SELECT idPath, strPath FROM path where strPath LIKE "%s"' % sql_videolibrarypath nun_records, records = execute_sql_kodi(sql) if nun_records == 1: idParentPath = records[0][0] videolibrarypath = records[0][1][:-1] continuar = True else: # No existe videolibrarypath en la BD: la insertamos sql_videolibrarypath = videolibrarypath if not sql_videolibrarypath.endswith(sep): sql_videolibrarypath += sep sql = 'INSERT INTO path (idPath, strPath, scanRecursive, useFolderNames, noUpdate, exclude) VALUES ' \ '(%s, "%s", 0, 0, 0, 0)' % (idPath, sql_videolibrarypath) nun_records, records = execute_sql_kodi(sql) if nun_records == 1: continuar = True idParentPath = idPath idPath += 1 else: msg_text = config.get_localized_string(70101) if continuar: continuar = False # Fijamos strContent, strScraper, scanRecursive y strSettings if content_type == 'movie': strContent = 'movies' scanRecursive = 2147483647 useFolderNames = 1 if seleccion == -1 or seleccion == 0: strScraper = 'metadata.themoviedb.org' path_settings = filetools.translatePath( "special://profile/addon_data/metadata.themoviedb.org/settings.xml" ) elif seleccion == 1: strScraper = 'metadata.universal' path_settings = filetools.translatePath( "special://profile/addon_data/metadata.universal/settings.xml" ) settings_data = filetools.read(path_settings) strSettings = ' '.join(settings_data.split()).replace("> <", "><") strSettings = strSettings.replace("\"", "\'") strActualizar = "¿Desea configurar este Scraper en español como opción por defecto para películas?" if not videolibrarypath.endswith(sep): videolibrarypath += sep strPath = videolibrarypath + config.get_setting( "folder_movies") + sep else: strContent = 'tvshows' scanRecursive = 0 useFolderNames = 0 if seleccion == -1 or seleccion == 0: strScraper = 'metadata.tvdb.com' path_settings = filetools.translatePath( "special://profile/addon_data/metadata.tvdb.com/settings.xml" ) elif seleccion == 1: strScraper = 'metadata.tvshows.themoviedb.org' path_settings = filetools.translatePath( "special://profile/addon_data/metadata.tvshows.themoviedb.org/settings.xml" ) settings_data = filetools.read(path_settings) strSettings = ' '.join(settings_data.split()).replace("> <", "><") strSettings = strSettings.replace("\"", "\'") strActualizar = "¿Desea configurar este Scraper en español como opción por defecto para series?" if not videolibrarypath.endswith(sep): videolibrarypath += sep strPath = videolibrarypath + config.get_setting( "folder_tvshows") + sep logger.info("%s: %s" % (content_type, strPath)) # Comprobamos si ya existe strPath en la BD para evitar duplicados sql = 'SELECT idPath FROM path where strPath="%s"' % strPath nun_records, records = execute_sql_kodi(sql) sql = "" if nun_records == 0: # Insertamos el scraper sql = 'INSERT INTO path (idPath, strPath, strContent, strScraper, scanRecursive, useFolderNames, ' \ 'strSettings, noUpdate, exclude, idParentPath) VALUES (%s, "%s", "%s", "%s", %s, %s, ' \ '"%s", 0, 0, %s)' % ( idPath, strPath, strContent, strScraper, scanRecursive, useFolderNames, strSettings, idParentPath) else: if not silent: # Preguntar si queremos configurar themoviedb.org como opcion por defecto actualizar = platformtools.dialog_yesno( config.get_localized_string(70098), strActualizar) else: actualizar = True if actualizar: # Actualizamos el scraper idPath = records[0][0] sql = 'UPDATE path SET strContent="%s", strScraper="%s", scanRecursive=%s, useFolderNames=%s, strSettings="%s" ' \ 'WHERE idPath=%s' % (strContent, strScraper, scanRecursive, useFolderNames, strSettings, idPath) if sql: nun_records, records = execute_sql_kodi(sql) if nun_records == 1: continuar = True if not continuar: msg_text = config.get_localized_string(60055) if not continuar: heading = config.get_localized_string(70102) % content_type elif content_type == 'SERIES' and not xbmc.getCondVisibility( 'System.HasAddon(metadata.tvshows.themoviedb.org)'): heading = config.get_localized_string(70103) % content_type msg_text = config.get_localized_string(60058) else: heading = config.get_localized_string(70103) % content_type msg_text = config.get_localized_string(70104) platformtools.dialog_notification(heading, msg_text, icon=1, time=3000) logger.info("%s: %s" % (heading, msg_text))
def set_workers(): workers = config.get_setting( 'thread_number') if config.get_setting('thread_number') > 0 else None return workers
from core import tmdb from core.item import Item from channels import filtertools from channels import autoplay from platformcode import config, logger IDIOMAS = {'EspaL': 'Cast', 'LatinoL': 'Lat', 'SubL': 'VOSE', 'OriL': 'VO'} list_language = IDIOMAS.values() CALIDADES = {'1080p': '1080', '720p': '720', '480p': '480', '360p': '360'} list_quality = ['1080', '720', '480', '360'] list_servers = ['powvideo'] __comprueba_enlaces__ = config.get_setting('comprueba_enlaces', 'goovie') __comprueba_enlaces_num__ = config.get_setting('comprueba_enlaces_num', 'goovie') host = 'https://goovie.co/' def mainlist(item): logger.info() autoplay.init(item.channel, list_servers, list_quality) itemlist = [] itemlist.append( Item(channel=item.channel,
from channels import autoplay #IDIOMAS = {'CAST': 'Castellano', 'LAT': 'Latino', 'VO': 'Version Original'} IDIOMAS = {'Castellano': 'CAST', 'Latino': 'LAT', 'Version Original': 'VO'} list_language = list(IDIOMAS.values()) list_quality = [] list_servers = ['torrent'] #host = 'https://www.subtorrents.tv/' #sufix = '.tv/' host = 'https://www.subtorrents.one/' sufix = '.one/' channel = 'subtorrents' categoria = channel.capitalize() color1, color2, color3 = ['0xFF58D3F7', '0xFF2E64FE', '0xFF0404B4'] __modo_grafico__ = config.get_setting('modo_grafico', channel) modo_ultima_temp = config.get_setting( 'seleccionar_ult_temporadda_activa', channel) #Actualización sólo últ. Temporada? timeout = config.get_setting('timeout_downloadpage', channel) def mainlist(item): logger.info() itemlist = [] thumb_pelis_hd = get_thumb("channels_movie_hd.png") thumb_series = get_thumb("channels_tvshow.png") thumb_buscar = get_thumb("search.png") thumb_separador = get_thumb("next.png") thumb_settings = get_thumb("setting_0.png")
def check_for_update(overwrite=True): logger.info("Actualizando series...") p_dialog = None serie_actualizada = False update_when_finished = False hoy = datetime.date.today() estado_verify_playcount_series = False try: if config.get_setting("update", "videolibrary") != 0 or overwrite: config.set_setting("updatelibrary_last_check", hoy.strftime('%Y-%m-%d'), "videolibrary") heading = config.get_localized_string(60389) p_dialog = platformtools.dialog_progress_bg( config.get_localized_string(20000), heading) p_dialog.update(0, '') show_list = [] for path, folders, files in filetools.walk( videolibrarytools.TVSHOWS_PATH): show_list.extend([ filetools.join(path, f) for f in files if f == "tvshow.nfo" ]) if show_list: t = float(100) / len(show_list) for i, tvshow_file in enumerate(show_list): head_nfo, serie = videolibrarytools.read_nfo(tvshow_file) path = filetools.dirname(tvshow_file) logger.info("serie=" + serie.contentSerieName) p_dialog.update(int(math.ceil((i + 1) * t)), heading, serie.contentSerieName) #Verificamos el estado del serie.library_playcounts de la Serie por si está incompleto try: estado = False #Si no hemos hecho la verificación o no tiene playcount, entramos estado = config.get_setting("verify_playcount", "videolibrary") if not estado or estado == False or not serie.library_playcounts: #Si no se ha pasado antes, lo hacemos ahora serie, estado = videolibrary.verify_playcount_series( serie, path ) #También se pasa si falta un PlayCount por completo except: logger.error(traceback.format_exc()) else: if estado: #Si ha tenido éxito la actualización... estado_verify_playcount_series = True #... se marca para cambiar la opción de la Videoteca interval = int(serie.active) # Podria ser del tipo bool if not serie.active: # si la serie no esta activa descartar if not overwrite: #Sincronizamos los episodios vistos desde la videoteca de Kodi con la de Alfa, aunque la serie esté desactivada try: if config.is_xbmc(): #Si es Kodi, lo hacemos from platformcode import xbmc_videolibrary xbmc_videolibrary.mark_content_as_watched_on_alfa( path + '/tvshow.nfo') except: logger.error(traceback.format_exc()) continue # obtenemos las fecha de actualizacion y de la proxima programada para esta serie update_next = serie.update_next if update_next: y, m, d = update_next.split('-') update_next = datetime.date(int(y), int(m), int(d)) else: update_next = hoy update_last = serie.update_last if update_last: y, m, d = update_last.split('-') update_last = datetime.date(int(y), int(m), int(d)) else: update_last = hoy # si la serie esta activa ... if overwrite or config.get_setting("updatetvshows_interval", "videolibrary") == 0: # ... forzar actualizacion independientemente del intervalo serie_actualizada = update(path, p_dialog, i, t, serie, overwrite) if not serie_actualizada: update_next = hoy + datetime.timedelta(days=interval) elif interval == 1 and update_next <= hoy: # ...actualizacion diaria serie_actualizada = update(path, p_dialog, i, t, serie, overwrite) if not serie_actualizada and update_last <= hoy - datetime.timedelta( days=7): # si hace una semana q no se actualiza, pasar el intervalo a semanal interval = 7 update_next = hoy + datetime.timedelta(days=interval) elif interval == 7 and update_next <= hoy: # ...actualizacion semanal serie_actualizada = update(path, p_dialog, i, t, serie, overwrite) if not serie_actualizada: if update_last <= hoy - datetime.timedelta(days=14): # si hace 2 semanas q no se actualiza, pasar el intervalo a mensual interval = 30 update_next += datetime.timedelta(days=interval) elif interval == 30 and update_next <= hoy: # ...actualizacion mensual serie_actualizada = update(path, p_dialog, i, t, serie, overwrite) if not serie_actualizada: update_next += datetime.timedelta(days=interval) if serie_actualizada: update_last = hoy update_next = hoy + datetime.timedelta(days=interval) head_nfo, serie = videolibrarytools.read_nfo( tvshow_file) #Vuelve a leer el.nfo, que ha sido modificado if interval != int(serie.active) or update_next.strftime( '%Y-%m-%d' ) != serie.update_next or update_last.strftime( '%Y-%m-%d') != serie.update_last: serie.update_last = update_last.strftime('%Y-%m-%d') if update_next > hoy: serie.update_next = update_next.strftime('%Y-%m-%d') serie.active = interval serie.channel = "videolibrary" serie.action = "get_seasons" filetools.write(tvshow_file, head_nfo + serie.tojson()) if serie_actualizada: if config.get_setting("search_new_content", "videolibrary") == 0: # Actualizamos la videoteca de Kodi: Buscar contenido en la carpeta de la serie if config.is_xbmc(): from platformcode import xbmc_videolibrary xbmc_videolibrary.update( folder=filetools.basename(path)) else: update_when_finished = True if estado_verify_playcount_series: #Si se ha cambiado algún playcount, ... estado = config.set_setting( "verify_playcount", True, "videolibrary" ) #... actualizamos la opción de Videolibrary if config.get_setting( "search_new_content", "videolibrary") == 1 and update_when_finished: # Actualizamos la videoteca de Kodi: Buscar contenido en todas las series if config.is_xbmc(): from platformcode import xbmc_videolibrary xbmc_videolibrary.update() p_dialog.close() else: logger.info( "No actualiza la videoteca, está desactivado en la configuración de alfa" ) except Exception, ex: logger.error("Se ha producido un error al actualizar las series") template = "An exception of type %s occured. Arguments:\n%r" message = template % (type(ex).__name__, ex.args) logger.error(message) if p_dialog: p_dialog.close()
def listado(item): logger.info() itemlist = [] item.category = categoria #logger.debug(item) curr_page = 1 # Página inicial last_page = 99999 # Última página inicial if item.curr_page: curr_page = int( item.curr_page) # Si viene de una pasada anterior, lo usamos del item.curr_page # ... y lo borramos if item.last_page: last_page = int( item.last_page) # Si viene de una pasada anterior, lo usamos del item.last_page # ... y lo borramos cnt_tot = 40 # Poner el num. máximo de items por página cnt_title = 0 # Contador de líneas insertadas en Itemlist inicio = time.time( ) # Controlaremos que el proceso no exceda de un tiempo razonable fin = inicio + 5 # Después de este tiempo pintamos (segundos) timeout_search = timeout # Timeout para descargas if item.extra == 'search': timeout_search = timeout * 2 # Timeout un poco más largo para las búsquedas if timeout_search < 5: timeout_search = 5 # Timeout un poco más largo para las búsquedas #Sistema de paginado para evitar páginas vacías o semi-vacías en casos de búsquedas con series con muchos episodios title_lista = [ ] # Guarda la lista de series que ya están en Itemlist, para no duplicar lineas if item.title_lista: # Si viene de una pasada anterior, la lista ya estará guardada title_lista.extend( item.title_lista) # Se usa la lista de páginas anteriores en Item del item.title_lista # ... limpiamos if not item.extra2: # Si viene de Catálogo o de Alfabeto item.extra2 = '' next_page_url = item.url #Máximo num. de líneas permitidas por TMDB. Máx de 10 segundos por Itemlist para no degradar el rendimiento while cnt_title < cnt_tot * 0.5 and curr_page <= last_page and fin > time.time( ): # Descarga la página data = '' try: data = re.sub( r"\n|\r|\t|\s{2}|(<!--.*?-->)| ", "", httptools.downloadpage(next_page_url, timeout=timeout_search).data) #data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") except: pass curr_page += 1 #Apunto ya a la página siguiente if not data: #Si la web está caída salimos sin dar error logger.error( "ERROR 01: LISTADO: La Web no responde o ha cambiado de URL: " + item.url + " / DATA: " + data) itemlist.append( item.clone( action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log' )) break #si no hay más datos, algo no funciona, pintamos lo que tenemos #Patrón para todo, menos para Series completas, incluido búsquedas en cualquier caso patron = '<td class="vertThseccion"><img src="([^"]+)"[^>]+><a href="([^"]+)"\s*title="([^"]+)"\s*>[^<]+<\/a><\/td><td>.*?(\d+)?<\/td><td>([^<]+)?<\/td><td>([^<]+)?<\/td><\/tr>' #Si son series completas, ponemos un patrón especializado if item.extra == 'series': patron = '<(td)><a href="([^"]+)"\s*title="([^"]+)"\s*><[^>]+src="[^"]+\/(\d{4})[^"]+"[^>]+>(?:(\d+))?\s*(?:(\d+))?<\/a>' matches = re.compile(patron, re.DOTALL).findall(data) if not matches and not '<p>Lo sentimos, pero que esta buscando algo que no esta aqui. </p>' in data and not item.extra2 and not '<h2>Sin resultados</h2> in data': #error item = generictools.web_intervenida( item, data) #Verificamos que no haya sido clausurada if item.intervencion: #Sí ha sido clausurada judicialmente item, itemlist = generictools.post_tmdb_episodios( item, itemlist) #Llamamos al método para el pintado del error return itemlist #Salimos logger.error( "ERROR 02: LISTADO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) itemlist.append( item.clone( action='', title=item.channel.capitalize() + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. Reportar el error con el log' )) break #si no hay más datos, algo no funciona, pintamos lo que tenemos #logger.debug("PATRON: " + patron) #logger.debug(matches) #logger.debug(data) #Buscamos la próxima y la última página patron_last = "<div class='pagination'>.*?<a href='([^']+\/page\/(\d+)[^']+)'\s*>(?:»)?(?:\d+)?<\/a><\/div>" if last_page == 99999: #Si es el valor inicial, buscamos last page try: next_page_url, last_page = scrapertools.find_single_match( data, patron_last) #cargamos la url y la última página last_page = int(last_page) except: #Si no lo encuentra, lo ponemos a 1 last_page = 1 #logger.error('ERROR 03: LISTADO: Al obtener la paginación: ' + patron_last + ' / ' + next_page_url + ' / ' + str(last_page)) #logger.debug('curr_page: ' + str(curr_page) + '/ last_page: ' + str(last_page)) if last_page > 1: next_page_url = re.sub(r'\/page\/\d+\/', '/page/%s/' % curr_page, next_page_url) next_page_url = next_page_url.replace('&', '&') else: next_page_url = item.url #logger.debug('curr_page: ' + str(curr_page) + '/ last_page: ' + str(last_page) + '/ next_page_url: ' + next_page_url) #Empezamos el procesado de matches for scrapedlanguage, scrapedurl, scrapedtitle, year, scrapedcategory, scrapedquality in matches: title = scrapedtitle url = scrapedurl.replace('&', '&') title = title.replace("á", "a").replace("é", "e").replace("í", "i")\ .replace("ó", "o").replace("ú", "u").replace("ü", "u")\ .replace("�", "ñ").replace("ñ", "ñ").replace("’", "'")\ .replace("&", "&") #cnt_title += 1 item_local = item.clone() #Creamos copia de Item para trabajar if item_local.tipo: #... y limpiamos del item_local.tipo if item_local.totalItems: del item_local.totalItems if item_local.category: del item_local.category if item_local.intervencion: del item_local.intervencion if item_local.viewmode: del item_local.viewmode item_local.extra2 = True del item_local.extra2 item_local.text_bold = True del item_local.text_bold item_local.text_color = True del item_local.text_color title_subs = [] #creamos una lista para guardar info importante item_local.language = [] #creamos lista para los idiomas item_local.quality = scrapedquality #iniciamos calidad item_local.thumbnail = '' item_local.url = url.replace('&', '&').replace( '.io/', sufix).replace('.com/', sufix) #guardamos la url final item_local.context = "['buscar_trailer']" item_local.contentType = "movie" #por defecto, son películas item_local.action = "findvideos" #Analizamos el formato de series if '/series' in scrapedurl or item_local.extra == 'series' or 'series' in scrapedcategory: item_local.extra = 'series' item_local.contentType = "tvshow" item_local.action = "episodios" item_local.season_colapse = True #Muestra las series agrupadas por temporadas #Detectamos idiomas if "1.png" in scrapedlanguage: item_local.language += ['CAST'] if "512.png" in scrapedlanguage or 'latino' in title.lower(): item_local.language += ['LAT'] if ("1.png" not in scrapedlanguage and "512.png" not in scrapedlanguage ) or "eng" in title.lower() or "sub" in title.lower(): item_local.language += ['VOSE'] if '-3d' in scrapedurl: title = title.replace('3D', '').replace('3d', '') item_local.quality += ' 3D' #Detectamos el año item_local.infoLabels['year'] = '-' if year: try: year = int(year) if year >= 1970 and year <= 2040: item_local.infoLabels["year"] = year except: pass #Detectamos info importante a guardar para después de TMDB if "extendida" in title.lower() or "extended" in title.lower( ) or "v.e." in title.lower() or "v e " in title.lower(): title_subs += ["[V. Extendida]"] title = title.replace("Version Extendida", "").replace( "(Version Extendida)", "").replace("V. Extendida", "").replace("VExtendida", "").replace( "V Extendida", "").replace("V.Extendida", "").replace( "V Extendida", "").replace("V.E.", "").replace("V E ", "") if scrapertools.find_single_match(title, '[m|M].*?serie'): title = re.sub(r'[m|M]iniserie', '', title) title_subs += ["Miniserie"] if scrapertools.find_single_match(title, '[s|S]aga'): title = re.sub(r'[s|S]aga', '', title) title_subs += ["Saga"] if scrapertools.find_single_match(title, '[c|C]olecc'): title = re.sub(r'[c|C]olecc...', '', title) title_subs += ["Colección"] #Empezamos a limpiar el título en varias pasadas patron = '\s?-?\s?(line)?\s?-\s?$' regex = re.compile(patron, re.I) title = regex.sub("", title) title = re.sub(r'\(\d{4}\s*?\)', '', title) title = re.sub(r'\[\d{4}\s*?\]', '', title) title = re.sub(r'[s|S]erie', '', title) title = re.sub(r'- $', '', title) title = re.sub(r'\d+[M|m|G|g][B|b]', '', title) #Limpiamos el título de la basura innecesaria title = re.sub( r'(?i)TV|Online|Spanish|Torrent|en Espa\xc3\xb1ol|Español|Latino|Subtitulado|Blurayrip|Bluray rip|\[.*?\]|R2 Pal|\xe3\x80\x90 Descargar Torrent \xe3\x80\x91|Completa|Temporada|Descargar|Torren|\(iso\)|\(dvd.*?\)|(?:\d+\s*)?\d{3,4}p.*?$|extended|(?:\d+\s*)?bdrip.*?$|\(.*?\).*?$|iso$|unrated|\[.*?$|\d{4}$', '', title) #Obtenemos temporada y episodio si se trata de Episodios if item_local.contentType == "episode": patron = '(\d+)[x|X](\d+)' try: item_local.contentSeason, item_local.contentEpisodeNumber = scrapertools.find_single_match( title, patron) except: item_local.contentSeason = 1 item_local.contentEpisodeNumber = 0 #Si son eisodios múltiples, lo extraemos patron1 = '\d+[x|X]\d+.?(?:y|Y|al|Al)?.?\d+[x|X](\d+)' epi_rango = scrapertools.find_single_match(title, patron1) if epi_rango: item_local.infoLabels[ 'episodio_titulo'] = 'al %s' % epi_rango title = re.sub(patron1, '', title) else: title = re.sub(patron, '', title) #Terminamos de limpiar el título title = re.sub(r'\??\s?\d*?\&.*', '', title) title = re.sub(r'[\(|\[]\s+[\)|\]]', '', title) title = title.replace('()', '').replace('[]', '').strip().lower().title() item_local.from_title = title.strip().lower().title( ) #Guardamos esta etiqueta para posible desambiguación de título #Salvamos el título según el tipo de contenido if item_local.contentType == "movie": item_local.contentTitle = title else: item_local.contentSerieName = title.strip().lower().title() item_local.title = title.strip().lower().title() item_local.quality = item_local.quality.strip() #Guarda la variable temporal que almacena la info adicional del título a ser restaurada después de TMDB item_local.title_subs = title_subs #Salvamos y borramos el número de temporadas porque TMDB a veces hace tonterias. Lo pasamos como serie completa if item_local.contentSeason and (item_local.contentType == "season" or item_local.contentType == "tvshow"): item_local.contentSeason_save = item_local.contentSeason del item_local.infoLabels['season'] #Ahora se filtra por idioma, si procede, y se pinta lo que vale if config.get_setting( 'filter_languages', channel) > 0: #Si hay idioma seleccionado, se filtra itemlist = filtertools.get_link(itemlist, item_local, list_language) else: itemlist.append(item_local.clone()) #Si no, pintar pantalla cnt_title = len(itemlist) #Contador de líneas añadidas #logger.debug(item_local) #Pasamos a TMDB la lista completa Itemlist tmdb.set_infoLabels(itemlist, __modo_grafico__) #Llamamos al método para el maquillaje de los títulos obtenidos desde TMDB item, itemlist = generictools.post_tmdb_listado(item, itemlist) # Si es necesario añadir paginacion if curr_page <= last_page and last_page > 1: if last_page: title = '%s de %s' % (curr_page - 1, last_page) else: title = '%s' % curr_page - 1 itemlist.append( Item(channel=item.channel, action="listado", title=">> Página siguiente " + title, title_lista=title_lista, url=next_page_url, extra=item.extra, extra2=item.extra2, last_page=str(last_page), curr_page=str(curr_page))) return itemlist
from channels import autoplay, filtertools from core import scrapertools, servertools, httptools, tmdb from core.item import Item from platformcode import config, logger host = "http://fastsubita.com" IDIOMAS = {'Italiano': 'IT'} list_language = IDIOMAS.values() list_servers = [ 'verystream', 'openload', 'speedvideo', 'wstream', 'flashx', 'vidoza', 'vidtome' ] list_quality = ['default'] __comprueba_enlaces__ = config.get_setting('comprueba_enlaces', 'fastsubita') __comprueba_enlaces_num__ = config.get_setting('comprueba_enlaces_num', 'fastsubita') headers = [ ['Host', 'fastsubita.com'], [ 'User-Agent', 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0' ], [ 'Accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' ], ['Accept-Language', 'en-US,en;q=0.5'], ['Accept-Encoding', 'gzip, deflate'], ['Referer', host], ['DNT', '1'], ['Connection', 'keep-alive'], ['Upgrade-Insecure-Requests', '1'],
def findvideos(item): logger.info() itemlist = [] itemlist_t = [] #Itemlist total de enlaces itemlist_f = [] #Itemlist de enlaces filtrados if not item.language: item.language = ['CAST'] #Castellano por defecto matches = [] subtitles = [] item.category = categoria #logger.debug(item) if item.extra != 'episodios': #Bajamos los datos de la página data = '' patron = '<div class="secciones"><h1>[^<]+<\/h1><br\s*\/><br\s*\/><div class="fichimagen">\s*<img class="carat" src="([^"]+)"' try: data = re.sub( r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data) #data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") except: pass if not data: logger.error( "ERROR 01: FINDVIDEOS: La Web no responde o la URL es erronea: " + item.url) itemlist.append( item.clone( action='', title=item.channel.capitalize() + ': ERROR 01: FINDVIDEOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log', folder=False)) if item.emergency_urls and not item.videolibray_emergency_urls: #Hay urls de emergencia? matches = item.emergency_urls[ 1] #Restauramos matches de vídeos subtitles = item.emergency_urls[ 2] #Restauramos matches de subtítulos item.armagedon = True #Marcamos la situación como catastrófica else: if item.videolibray_emergency_urls: #Si es llamado desde creación de Videoteca... return item #Devolvemos el Item de la llamada else: return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos if not item.armagedon: #Extraemos el thumb if not item.thumbnail: item.thumbnail = scrapertools.find_single_match( data, patron) #guardamos thumb si no existe #Extraemos quality, audio, year, country, size, scrapedlanguage patron = '<\/script><\/div><ul>(?:<li><label>Fecha de estreno <\/label>[^<]+<\/li>)?(?:<li><label>Genero <\/label>[^<]+<\/li>)?(?:<li><label>Calidad <\/label>([^<]+)<\/li>)?(?:<li><label>Audio <\/label>([^<]+)<\/li>)?(?:<li><label>Fecha <\/label>.*?(\d+)<\/li>)?(?:<li><label>Pais de Origen <\/label>([^<]+)<\/li>)?(?:<li><label>Tamaño <\/label>([^<]+)<\/li>)?(<li> Idioma[^<]+<img src=.*?<br \/><\/li>)?' try: quality = '' audio = '' year = '' country = '' size = '' scrapedlanguage = '' quality, audio, year, country, size, scrapedlanguage = scrapertools.find_single_match( data, patron) except: pass if quality: item.quality = quality if audio: item.quality += ' %s' % audio.strip() if not item.infoLabels['year'] and year: item.infoLabels['year'] = year size = size.replace('GB', 'G·B').replace('Gb', 'G·b').replace('MB', 'M·B')\ .replace('Mb', 'M·b').replace('.', ',').replace('G B', 'G·B').replace('M B', 'M·B') if size: item.quality += ' [%s]' % size if size: item.title = re.sub( r'\s*\[\d+,?\d*?\s\w\s*[b|B]\]', '', item.title) #Quitamos size de título, si lo traía language = [] matches_lang = re.compile('(\d+.png)', re.DOTALL).findall(scrapedlanguage) for lang in matches_lang: if "1.png" in lang and not 'CAST' in language: language += ['CAST'] if "512.png" in lang and not 'LAT' in language: language += ['LAT'] if ("1.png" not in lang and "512.png" not in lang) and not 'VOSE' in language: language += ['VOSE'] if language: item.language = language #Extraemos los enlaces .torrent #Modalidad de varios archivos patron = '<div class="fichadescargat"><\/div><div class="table-responsive"[^>]+>.*?<\/thead><tbody>(.*?)<\/tbody><\/table><\/div>' if scrapertools.find_single_match(data, patron): data_torrents = scrapertools.find_single_match(data, patron) patron = '<tr><td>.*?<\/td><td><a href="([^"]+)"[^>]+><[^>]+><\/a><\/td><\/tr>' #Modalidad de un archivo else: data_torrents = data patron = '<div class="fichasubtitulos">.*?<\/div><\/li><\/ul>.*?<a href="([^"]+)"' matches = re.compile(patron, re.DOTALL).findall(data_torrents) if not matches: #error logger.error( "ERROR 02: FINDVIDEOS: No hay enlaces o ha cambiado la estructura de la Web " + " / PATRON: " + patron + data) itemlist.append( item.clone( action='', title=item.channel.capitalize() + ': ERROR 02: FINDVIDEOS: No hay enlaces o ha cambiado la estructura de la Web. Verificar en la Web esto último y reportar el error con el log', folder=False)) if item.emergency_urls and not item.videolibray_emergency_urls: #Hay urls de emergencia? matches = item.emergency_urls[ 1] #Restauramos matches de vídeos subtitles = item.emergency_urls[ 2] #Restauramos matches de subtítulos item.armagedon = True #Marcamos la situación como catastrófica else: if item.videolibray_emergency_urls: #Si es llamado desde creación de Videoteca... return item #Devolvemos el Item de la llamada else: return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos else: #SERIES: ya viene con las urls data = item.url #inicio data por compatibilidad matches = [item.url] #inicio matches por compatibilidad #Extraemos las urls de los subtítulos (Platformtools usa item.subtitle como sub-titulo por defecto) patron = '<div class="fichasubtitulos">\s*<label class="fichsub">\s*<a href="([^"]+)">Subtitulos\s*<\/a>\s*<\/label>' if scrapertools.find_single_match(data, patron) or item.subtitle: if item.extra == 'episodios': #Si viene de Series, ya tengo la primera url subtitle = item.subtitle del item.subtitle else: subtitle = scrapertools.find_single_match(data, patron).replace( '&', '&').replace('.io/', sufix).replace('.com/', sufix) try: data_subtitle = re.sub( r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(subtitle, timeout=timeout).data) except: pass if not data_subtitle: if item.emergency_urls and not item.videolibray_emergency_urls: #Hay urls de emergencia? matches = item.emergency_urls[ 1] #Restauramos matches de vídeos subtitles = item.emergency_urls[ 2] #Restauramos matches de subtítulos item.armagedon = True #Marcamos la situación como catastrófica else: patron = '<tbody>(<tr class="fichserietabla_b">.*?<\/tr>)<\/tbody>' #salvamos el bloque data_subtitle = scrapertools.find_single_match( data_subtitle, patron) patron = '<tr class="fichserietabla_b">.*?<a href="([^"]+)"' subtitles = re.compile(patron, re.DOTALL).findall( data_subtitle) #Creamos una lista con todos los sub-títulos if subtitles: item.subtitle = [] for subtitle in subtitles: subtitle = subtitle.replace('&', '&').replace( '.io/', sufix).replace('.com/', sufix) item.subtitle.append(subtitle) #logger.debug("PATRON: " + patron) #logger.debug(matches) #logger.debug(subtitles) #logger.debug(data) #Si es un lookup para cargar las urls de emergencia en la Videoteca... if item.videolibray_emergency_urls: item.emergency_urls = [] #Iniciamos emergency_urls item.emergency_urls.append( []) #Reservamos el espacio para los .torrents locales item.emergency_urls.append( matches) #Salvamnos matches de los vídeos... item.emergency_urls.append( subtitles) #Salvamnos matches de los subtítulos #Llamamos al método para crear el título general del vídeo, con toda la información obtenida de TMDB if not item.videolibray_emergency_urls: item, itemlist = generictools.post_tmdb_findvideos(item, itemlist) #Ahora tratamos los enlaces .torrent for scrapedurl in matches: #leemos los torrents con la diferentes calidades #Generamos una copia de Item para trabajar sobre ella item_local = item.clone() item_local.url = scrapedurl.replace('&', '&').replace( '.io/', sufix).replace('.com/', sufix) if item.videolibray_emergency_urls: item.emergency_urls[0].append( scrapedurl) #guardamos la url y pasamos a la siguiente continue if item.emergency_urls and not item.videolibray_emergency_urls: item_local.torrent_alt = item.emergency_urls[0][ 0] #Guardamos la url del .Torrent ALTERNATIVA if item.armagedon: item_local.url = item.emergency_urls[0][ 0] #... ponemos la emergencia como primaria del item.emergency_urls[0][0] #Una vez tratado lo limpiamos #Buscamos si ya tiene tamaño, si no, los buscamos en el archivo .torrent size = scrapertools.find_single_match( item_local.quality, '\s*\[(\d+,?\d*?\s\w\s*[b|B])\]') if not size and not item.armagedon: size = generictools.get_torrent_size( scrapedurl) #Buscamos el tamaño en el .torrent if size: logger.error(size) size = size.replace('GB', 'G·B').replace('Gb', 'G·b').replace('MB', 'M·B')\ .replace('Mb', 'M·b').replace('.', ',').replace('G B', 'G·B').replace('M B', 'M·B') item_local.title = re.sub( r'\s*\[\d+,?\d*?\s\w\s*[b|B]\]', '', item_local.title) #Quitamos size de título, si lo traía item_local.quality = re.sub( r'\s*\[\d+,?\d*?\s\w\s*[b|B]\]', '', item_local.quality) #Quitamos size de calidad, si lo traía item_local.torrent_info += '%s' % size #Agregamos size if not item.unify: item_local.torrent_info = '[%s]' % item_local.torrent_info.strip( ).strip(',') if item.armagedon: #Si es catastrófico, lo marcamos item_local.quality = '[/COLOR][COLOR hotpink][E] [COLOR limegreen]%s' % item_local.quality #Ahora pintamos el link del Torrent item_local.title = '[[COLOR yellow]?[/COLOR]] [COLOR yellow][Torrent][/COLOR] ' \ + '[COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR] %s' % \ (item_local.quality, str(item_local.language), \ item_local.torrent_info) #Preparamos título de Torrent #Preparamos título y calidad, quitamos etiquetas vacías item_local.title = re.sub(r'\s?\[COLOR \w+\]\[\[?\s?\]?\]\[\/COLOR\]', '', item_local.title) item_local.title = re.sub(r'\s?\[COLOR \w+\]\s?\[\/COLOR\]', '', item_local.title) item_local.title = item_local.title.replace("--", "").replace( "[]", "").replace("()", "").replace("(/)", "").replace("[/]", "").strip() item_local.quality = re.sub( r'\s?\[COLOR \w+\]\[\[?\s?\]?\]\[\/COLOR\]', '', item_local.quality) item_local.quality = re.sub(r'\s?\[COLOR \w+\]\s?\[\/COLOR\]', '', item_local.quality) item_local.quality = item_local.quality.replace("--", "").replace( "[]", "").replace("()", "").replace("(/)", "").replace("[/]", "").replace(".", ",").strip() item_local.alive = "??" #Calidad del link sin verificar item_local.action = "play" #Visualizar vídeo item_local.server = "torrent" #Seridor Torrent itemlist_t.append( item_local.clone()) #Pintar pantalla, si no se filtran idiomas # Requerido para FilterTools if config.get_setting( 'filter_languages', channel) > 0: #Si hay idioma seleccionado, se filtra itemlist_f = filtertools.get_link( itemlist_f, item_local, list_language) #Pintar pantalla, si no está vacío #logger.debug("TORRENT: " + scrapedurl + " / title gen/torr: " + item.title + " / " + item_local.title + " / calidad: " + item_local.quality + " / content: " + item_local.contentTitle + " / " + item_local.contentSerieName) #logger.debug(item_local) if item.videolibray_emergency_urls: #Si ya hemos guardado todas las urls... return item #... nos vamos if len(itemlist_f) > 0: #Si hay entradas filtradas... itemlist.extend(itemlist_f) #Pintamos pantalla filtrada else: if config.get_setting('filter_languages', channel) > 0 and len( itemlist_t) > 0: #Si no hay entradas filtradas ... thumb_separador = get_thumb( "next.png") #... pintamos todo con aviso itemlist.append( Item( channel=item.channel, url=host, title= "[COLOR red][B]NO hay elementos con el idioma seleccionado[/B][/COLOR]", thumbnail=thumb_separador, folder=False)) itemlist.extend( itemlist_t) #Pintar pantalla con todo si no hay filtrado # Requerido para AutoPlay autoplay.start(itemlist, item) #Lanzamos Autoplay return itemlist
# -*- coding: utf-8 -*- import re import urllib from core import httptools from core import scrapertools from core import servertools from core.item import Item from platformcode import config, logger from channelselector import get_thumb __modo_grafico__ = config.get_setting("modo_grafico", "descargasmix") __perfil__ = config.get_setting("perfil", "descargasmix") # Fijar perfil de color perfil = [['0xFFFFE6CC', '0xFFFFCE9C', '0xFF994D00'], ['0xFFA5F6AF', '0xFF5FDA6D', '0xFF11811E'], ['0xFF58D3F7', '0xFF2E9AFE', '0xFF2E64FE']] color1, color2, color3 = perfil[__perfil__] host = config.get_setting("host", "descargasmix") def mainlist(item): logger.info() itemlist = [] item.text_color = color1 # Resetear host y comprobacion de error en https (por si se actualiza Kodi) config.set_setting("url_error", False, "descargasmix") host = config.set_setting("host", "https://ddmix.net", "descargasmix") host_check = get_data(host, True)
def mark_season_as_watched_on_kodi(item, value=1): """ marca toda la temporada como vista o no vista en la libreria de Kodi @type item: item @param item: elemento a marcar @type value: int @param value: >0 para visto, 0 para no visto """ logger.info() # logger.debug("item:\n" + item.tostring('\n')) # Solo podemos marcar la temporada como vista en la BBDD de Kodi si la BBDD es local, # en caso de compartir BBDD esta funcionalidad no funcionara if config.get_setting("db_mode", "videolibrary"): return if value == 0: value = 'Null' request_season = '' if item.contentSeason: request_season = ' and c12= %s' % item.contentSeason request_episode = '' if item.contentSeason and item.contentEpisodeNumber: season_episode = '%sx%s.strm' % (str( item.contentSeason), str(item.contentEpisodeNumber).zfill(2)) request_episode = ' and strFileName= "%s"' % season_episode if item.video_path: path = item.video_path else: path = item.path if item.contentType == 'movie': video_path = filetools.join(config.get_videolibrary_path(), config.get_setting("folder_movies")) view = 'movie' else: video_path = filetools.join(config.get_videolibrary_path(), config.get_setting("folder_tvshows")) view = 'episode' item_path1 = "%" + path.replace("\\\\", "\\").replace(video_path, "") if item_path1[:-1] != "\\": item_path1 += "\\" item_path2 = item_path1.replace("\\", "/") sql = 'update files set playCount= %s where idFile in ' \ '(select idfile from %s_view where (strPath like "%s" or strPath like "%s")%s%s)' % \ (value, view, item_path1, item_path2, request_season, request_episode) nun_records, records = execute_sql_kodi(sql) if not nun_records: return # Lanzamos un scan de la Videoteca de Kodi contra un directorio vacío para forzar el refresco de los widgets de pelis y series payload = { "jsonrpc": "2.0", "method": "VideoLibrary.Scan", "id": 1, "params": { "directory": filetools.join(config.get_runtime_path(), 'tools') } } while xbmc.getCondVisibility('Library.IsScanningVideo()'): return # Ya está actualizando try: data = get_data(payload) """ # Recargamos el Skin para que actualice los widgets. Dejamos un tiempo para que termine la actualización xbmc.executebuiltin('ReloadSkin()') time.sleep(1) """ except: pass
import os import re import time from threading import Thread from channelselector import get_thumb from core import channeltools from core import scrapertools from core.item import Item from platformcode import config, logger from platformcode import platformtools from core import jsontools THUMBNAILS = {'0': 'posters', '1': 'banners', '2': 'squares'} __perfil__ = config.get_setting('perfil', "news") # Fijar perfil de color perfil = [['0xFF0B7B92', '0xFF89FDFB', '0xFFACD5D4'], ['0xFFB31313', '0xFFFF9000', '0xFFFFEE82'], ['0xFF891180', '0xFFCB22D7', '0xFFEEA1EB'], ['0xFFA5DEE5', '0xFFE0F9B5', '0xFFFEFDCA'], ['0xFFF23557', '0xFF22B2DA', '0xFFF0D43A']] #color1, color2, color3 = ["white", "white", "white"] color1, color2, color3 = perfil[__perfil__] list_newest = [] list_newest_tourl = [] channels_id_name = {}
def get_videos_watched_on_kodi(item, value=1, list_videos=False): """ Obtiene la lista de videos vistos o no vistos en la libreria de Kodi @type item: item @param item: elemento a obtener @type value: int @param value: >0 para visto, 0 para no visto @type list_videos: bool @param list_videos: True: devuelve la lista obtenida en la query @type Return: bool si list_videos=False @param Return: True si list_videos=False y todos tiene el estado "value". Si list_videos=True, devuelve lista de vídeos """ logger.info() # logger.debug("item:\n" + item.tostring('\n')) # Solo podemos obtener los vídeos como vistos en la BBDD de Kodi si la BBDD es local, # en caso de compartir BBDD esta funcionalidad no funcionara if config.get_setting("db_mode", "videolibrary"): return request_season = '' if item.contentSeason: request_season = ' and c12= %s' % item.contentSeason if item.video_path: path = item.video_path else: path = item.path if item.contentType == 'movie': video_path = filetools.join(config.get_videolibrary_path(), config.get_setting("folder_movies")) view = 'movie' else: video_path = filetools.join(config.get_videolibrary_path(), config.get_setting("folder_tvshows")) view = 'episode' tvshows_path = filetools.join(config.get_videolibrary_path(), config.get_setting("folder_tvshows")) item_path1 = "%" + path.replace("\\\\", "\\").replace(tvshows_path, "") if item_path1[:-1] != "\\": item_path1 += "\\" item_path2 = item_path1.replace("\\", "/") sql = 'select strFileName, playCount from %s_view where (strPath like "%s" or strPath like "%s")' % ( view, item_path1, item_path2) nun_records, records = execute_sql_kodi(sql, silent=True) if not nun_records: if list_videos: return {} else: return False records = filetools.decode(records, trans_none=0) records = dict(records) if list_videos: return records for path, mark in list(records.items()): if mark != value: return False return True
from core import tmdb from core.item import Item from platformcode import config, logger from channelselector import get_thumb from channels import autoplay from channels import filtertools IDIOMAS = {'Latino': 'LAT', 'Castellano': 'CAST', 'Vo': 'VO', 'Vose': 'VOSE'} list_language = IDIOMAS.values() list_quality = [] list_servers = [ 'openload', 'powvideo', 'rapidvideo', 'streamango', 'streamcloud', 'flashx', 'gamovideo', 'streamplay' ] __modo_grafico__ = config.get_setting('modo_grafico', 'gnula_biz') __perfil__ = int(config.get_setting('perfil', "gnula_biz")) __menu_info__ = config.get_setting('menu_info', 'gnula_biz') __comprueba_enlaces__ = config.get_setting('comprueba_enlaces', 'gnula_biz') __comprueba_enlaces_num__ = config.get_setting('comprueba_enlaces_num', 'gnula_biz') # Fijar perfil de color perfil = [ ['0xFFFFE6CC', '0xFFFFCE9C', '0xFF994D00', '0xFFFE2E2E', '0xFF088A08'], ['0xFFA5F6AF', '0xFF5FDA6D', '0xFF11811E', '0xFFFE2E2E', '0xFF088A08'], ['0xFF58D3F7', '0xFF2E9AFE', '0xFF2E64FE', '0xFFFE2E2E', '0xFF088A08'] ] if __perfil__ < 3: color1, color2, color3, color4, color5 = perfil[__perfil__]
def episodios(item): logger.info() itemlist = [] infoLabels = item.infoLabels data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url).data) data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") calidad = item.quality pattern = '<ul class="%s">(.*?)</ul>' % "pagination" # item.pattern pagination = scrapertools.find_single_match(data, pattern) if pagination: pattern = '<li><a href="([^"]+)">Last<\/a>' full_url = scrapertools.find_single_match(pagination, pattern) url, last_page = scrapertools.find_single_match( full_url, r'(.*?\/pg\/)(\d+)') list_pages = [item.url] for x in range(2, int(last_page) + 1): response = httptools.downloadpage('%s%s' % (url, x)) if response.sucess: list_pages.append("%s%s" % (url, x)) else: list_pages = [item.url] for index, page in enumerate(list_pages): data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(page).data) data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") data = data.replace( "chapters", "buscar-list") #Compatibilidad con mispelisy.series.com pattern = '<ul class="%s">(.*?)</ul>' % "buscar-list" # item.pattern if scrapertools.find_single_match(data, pattern): data = scrapertools.get_match(data, pattern) else: logger.debug(item) logger.debug("data: " + data) return itemlist if "pelisyseries.com" in host: pattern = '<li[^>]*><div class.*?src="(?P<thumb>[^"]+)?".*?<a class.*?href="(?P<url>[^"]+).*?<h3[^>]+>(?P<info>.*?)?<\/h3>.*?<\/li>' else: pattern = '<li[^>]*><a href="(?P<url>[^"]+).*?<img.*?src="(?P<thumb>[^"]+)?".*?<h2[^>]+>(?P<info>.*?)?<\/h2>' matches = re.compile(pattern, re.DOTALL).findall(data) #logger.debug("patron: " + pattern) #logger.debug(matches) season = "1" for url, thumb, info in matches: if "pelisyseries.com" in host: interm = url url = thumb thumb = interm if "<span" in info: # new style pattern = ".*?[^>]+>.*?Temporada\s*(?P<season>\d+)?.*?Capitulo(?:s)?\s*(?P<episode>\d+)?" \ "(?:.*?(?P<episode2>\d+)?)<.+?<span[^>]+>(?P<lang>.*?)?<\/span>\s*Calidad\s*<span[^>]+>" \ "[\[]\s*(?P<quality>.*?)?\s*[\]]<\/span>" if "Especial" in info: # Capitulos Especiales pattern = ".*?[^>]+>.*?Temporada.*?\[.*?(?P<season>\d+).*?\].*?Capitulo.*?\[\s*(?P<episode>\d+).*?\]?(?:.*?(?P<episode2>\d+)?)<.+?<span[^>]+>(?P<lang>.*?)?<\/span>\s*Calidad\s*<span[^>]+>[\[]\s*(?P<quality>.*?)?\s*[\]]<\/span>" if not scrapertools.find_single_match( info, pattern ): #en caso de error de formato, creo uno básico logger.debug("patron episodioNEW: " + pattern) logger.debug(info) info = '><strong>%sTemporada %s Capitulo 0</strong> - <span >Español Castellano</span> Calidad <span >[%s]</span>' % ( item.contentTitle, season, item.infoLabels['quality']) r = re.compile(pattern) match = [m.groupdict() for m in r.finditer(info)][0] if match['season'] is None: match['season'] = season if match['episode'] is None: match['episode'] = "0" if match['quality']: item.quality = match['quality'] if match["episode2"]: multi = True title = "%s (%sx%s-%s) [%s]" % ( item.show, match["season"], str( match["episode"]).zfill(2), str( match["episode2"]).zfill(2), match["lang"]) if not config.get_setting("unify") and match[ "quality"]: #Si Titulos Inteligentes NO seleccionados: title = "%s[%s]" % (title, match["quality"]) else: multi = False title = "%s (%sx%s) [%s]" % ( item.show, match["season"], str( match["episode"]).zfill(2), match["lang"]) if not config.get_setting("unify") and match[ "quality"]: #Si Titulos Inteligentes NO seleccionados: title = "%s[%s]" % (title, match["quality"]) else: # old style if scrapertools.find_single_match(info, '\[\d{3}\]'): info = re.sub(r'\[(\d{3}\])', r'[Cap.\1', info) elif scrapertools.find_single_match(info, '\[Cap.\d{2}_\d{2}\]'): info = re.sub(r'\[Cap.(\d{2})_(\d{2})\]', r'[Cap.1\1_1\2]', info) elif scrapertools.find_single_match(info, '\[Cap.([A-Za-z]+)\]'): info = re.sub(r'\[Cap.([A-Za-z]+)\]', '[Cap.100]', info) if scrapertools.find_single_match(info, '\[Cap.\d{2,3}'): pattern = "\[(?P<quality>.*?)\].*?\[Cap.(?P<season>\d).*?(?P<episode>\d{2})(?:_(?P<season2>\d+)" \ "(?P<episode2>\d{2}))?.*?\].*?(?:\[(?P<lang>.*?)\])?" elif scrapertools.find_single_match(info, 'Cap.\d{2,3}'): pattern = ".*?Temp.*?\s(?P<quality>.*?)\s.*?Cap.(?P<season>\d).*?(?P<episode>\d{2})(?:_(?P<season2>\d+)(?P<episode2>\d{2}))?.*?\s(?P<lang>.*)?" if not scrapertools.find_single_match( info, pattern ): #en caso de error de formato, creo uno básico logger.debug("patron episodioOLD: " + pattern) logger.debug(info) info = '%s [%s][Cap.%s00][Español]' % ( item.contentTitle, item.infoLabels['quality'], season) r = re.compile(pattern) match = [m.groupdict() for m in r.finditer(info)][0] str_lang = "" if match['quality']: item.quality = match['quality'] if match["lang"] is not None: str_lang = "[%s]" % match["lang"] item.quality = "%s %s" % (item.quality, match['lang']) if match["season2"] and match["episode2"]: multi = True if match["season"] == match["season2"]: title = "%s (%sx%s-%s) %s" % ( item.show, match["season"], match["episode"], match["episode2"], str_lang) if not config.get_setting("unify") and match[ "quality"]: #Si Titulos Inteligentes NO seleccionados: title = "%s[%s]" % (title, match["quality"]) else: title = "%s (%sx%s-%sx%s) %s" % ( item.show, match["season"], match["episode"], match["season2"], match["episode2"], str_lang) if not config.get_setting("unify") and match[ "quality"]: #Si Titulos Inteligentes NO seleccionados: title = "%s[%s]" % (title, match["quality"]) else: title = "%s (%sx%s) %s" % (item.show, match["season"], match["episode"], str_lang) if not config.get_setting("unify") and match[ "quality"]: #Si Titulos Inteligentes NO seleccionados: title = "%s[%s]" % (title, match["quality"]) multi = False season = match['season'] episode = match['episode'] logger.debug("title: " + title + " / url: " + url + " / calidad: " + item.quality + " / multi: " + str(multi) + " / Season: " + str(season) + " / EpisodeNumber: " + str(episode)) itemlist.append( Item(channel=item.channel, action="findvideos", title=title, url=url, thumbnail=thumb, quality=item.quality, multi=multi, contentSeason=season, contentEpisodeNumber=episode, infoLabels=infoLabels)) # order list #tmdb.set_infoLabels(itemlist, True) tmdb.set_infoLabels_itemlist(itemlist, seekTmdb=True) if len(itemlist) > 1: itemlist = sorted( itemlist, key=lambda it: (int(it.contentSeason), int(it.contentEpisodeNumber))) if config.get_videolibrary_support() and len(itemlist) > 0: itemlist.append( item.clone(title="Añadir esta serie a la videoteca", action="add_serie_to_library", extra="episodios", quality=calidad)) return itemlist