540 lines
22 KiB
Python
540 lines
22 KiB
Python
# -*- coding: utf-8 -*-
|
|
# ------------------------------------------------------------
|
|
# XBMC Launcher (xbmc / kodi)
|
|
# ------------------------------------------------------------
|
|
|
|
import os
|
|
import sys
|
|
|
|
from specials import resolverdns
|
|
import urllib2
|
|
|
|
from core import channeltools
|
|
from core import scrapertools
|
|
from core import servertools
|
|
from core import trakt_tools
|
|
from core import videolibrarytools
|
|
from core.item import Item
|
|
from platformcode import config, logger
|
|
from platformcode import platformtools
|
|
from platformcode.logger import WebErrorException
|
|
|
|
|
|
|
|
def start():
|
|
""" Primera funcion que se ejecuta al entrar en el plugin.
|
|
Dentro de esta funcion deberian ir todas las llamadas a las
|
|
funciones que deseamos que se ejecuten nada mas abrir el plugin.
|
|
"""
|
|
logger.info()
|
|
#config.set_setting('show_once', True)
|
|
# Test if all the required directories are created
|
|
config.verify_directories_created()
|
|
|
|
# controlla se l'utente ha qualche problema di connessione
|
|
# se lo ha: non lo fa entrare nell'addon
|
|
# se ha problemi di DNS avvia ma lascia entrare
|
|
# se tutto ok: entra nell'addon
|
|
from specials.checkhost import test_conn
|
|
import threading
|
|
threading.Thread(target=test_conn, args=(True, True, True, [], [], True)).start()
|
|
# check_adsl = test_conn(is_exit = True, check_dns = True, view_msg = True,
|
|
# lst_urls = [], lst_site_check_dns = [], in_addon = True)
|
|
|
|
|
|
def run(item=None):
|
|
logger.info()
|
|
if not item:
|
|
# Extract item from sys.argv
|
|
if sys.argv[2]:
|
|
item = Item().fromurl(sys.argv[2])
|
|
|
|
# If no item, this is mainlist
|
|
else:
|
|
if config.get_setting("start_page"):
|
|
|
|
if not config.get_setting("custom_start"):
|
|
dictCategory = {
|
|
config.get_localized_string(70137): 'peliculas',
|
|
config.get_localized_string(30123): 'series',
|
|
config.get_localized_string(30124): 'anime',
|
|
config.get_localized_string(70018): 'infantiles',
|
|
config.get_localized_string(60513): 'documentales',
|
|
config.get_localized_string(70013): 'terror',
|
|
config.get_localized_string(70014): 'castellano',
|
|
config.get_localized_string(59976): 'latino',
|
|
config.get_localized_string(70171): 'torrent',
|
|
}
|
|
if not config.get_setting("category") in dictCategory.keys():
|
|
config.set_setting('category', config.get_localized_string(70137))
|
|
category = dictCategory[config.get_setting("category")]
|
|
item = Item(channel="news", action="novedades", extra=category, mode = 'silent')
|
|
else:
|
|
from specials import side_menu
|
|
item= Item()
|
|
item = side_menu.check_user_home(item)
|
|
item.start = True
|
|
else:
|
|
item = Item(channel="channelselector", action="getmainlist", viewmode="movie")
|
|
if not config.get_setting('show_once'):
|
|
if not config.dev_mode():
|
|
from platformcode import updater
|
|
updater.calcCurrHash()
|
|
from platformcode import xbmc_videolibrary
|
|
xbmc_videolibrary.ask_set_content(1, config.get_setting('videolibrary_kodi_force'))
|
|
config.set_setting('show_once', True)
|
|
|
|
logger.info(item.tostring())
|
|
|
|
try:
|
|
# If item has no action, stops here
|
|
if item.action == "":
|
|
logger.info("Item sin accion")
|
|
return
|
|
|
|
# Action for main menu in channelselector
|
|
elif item.action == "getmainlist":
|
|
import channelselector
|
|
|
|
itemlist = channelselector.getmainlist()
|
|
|
|
platformtools.render_items(itemlist, item)
|
|
|
|
# Action for channel types on channelselector: movies, series, etc.
|
|
elif item.action == "getchanneltypes":
|
|
import channelselector
|
|
itemlist = channelselector.getchanneltypes()
|
|
|
|
platformtools.render_items(itemlist, item)
|
|
|
|
# Action for channel listing on channelselector
|
|
elif item.action == "filterchannels":
|
|
import channelselector
|
|
itemlist = channelselector.filterchannels(item.channel_type)
|
|
|
|
platformtools.render_items(itemlist, item)
|
|
|
|
# Special action for playing a video from the library
|
|
elif item.action == "play_from_library":
|
|
play_from_library(item)
|
|
return
|
|
|
|
elif item.action == "keymap":
|
|
from platformcode import keymaptools
|
|
if item.open:
|
|
return keymaptools.open_shortcut_menu()
|
|
else:
|
|
return keymaptools.set_key()
|
|
|
|
elif item.action == "delete_key":
|
|
from platformcode import keymaptools
|
|
return keymaptools.delete_key()
|
|
|
|
elif item.action == "script":
|
|
from core import tmdb
|
|
if tmdb.drop_bd():
|
|
platformtools.dialog_notification(config.get_localized_string(20000), config.get_localized_string(60011), time=2000, sound=False)
|
|
elif item.action == "itemInfo":
|
|
import base64
|
|
platformtools.dialog_textviewer('Item info', item.parent)
|
|
elif item.action == "open_browser":
|
|
import webbrowser
|
|
if not webbrowser.open(item.url):
|
|
import xbmc
|
|
if xbmc.getCondVisibility('system.platform.linux') and xbmc.getCondVisibility('system.platform.android'): # android
|
|
xbmc.executebuiltin('StartAndroidActivity("", "android.intent.action.VIEW", "", "%s")' % (item.url))
|
|
else:
|
|
short = urllib2.urlopen(
|
|
'https://u.nu/api.php?action=shorturl&format=simple&url=' + item.url).read()
|
|
platformtools.dialog_ok(config.get_localized_string(20000),
|
|
config.get_localized_string(70740) % short)
|
|
# Action in certain channel specified in "action" and "channel" parameters
|
|
else:
|
|
# Entry point for a channel is the "mainlist" action, so here we check parental control
|
|
if item.action == "mainlist":
|
|
#updater.checkforupdates() beta version checking for update, still disabled
|
|
|
|
# Parental control
|
|
# If it is an adult channel, and user has configured pin, asks for it
|
|
if channeltools.is_adult(item.channel) and config.get_setting("adult_request_password"):
|
|
tecleado = platformtools.dialog_input("", config.get_localized_string(60334), True)
|
|
if tecleado is None or tecleado != config.get_setting("adult_password"):
|
|
return
|
|
# # Actualiza el canal individual
|
|
# if (item.action == "mainlist" and item.channel != "channelselector" and
|
|
# config.get_setting("check_for_channel_updates") == True):
|
|
# from core import updater
|
|
# updater.update_channel(item.channel)
|
|
|
|
# Checks if channel exists
|
|
if os.path.isfile(os.path.join(config.get_runtime_path(), 'channels', item.channel + ".py")):
|
|
CHANNELS = 'channels'
|
|
elif os.path.isfile(os.path.join(config.get_runtime_path(), 'channels', 'porn', item.channel + ".py")):
|
|
CHANNELS = 'channels.porn'
|
|
else:
|
|
CHANNELS ='specials'
|
|
|
|
if CHANNELS != 'channels.porn':
|
|
channel_file = os.path.join(config.get_runtime_path(), CHANNELS, item.channel + ".py")
|
|
else:
|
|
channel_file = os.path.join(config.get_runtime_path(), 'channels', 'porn', item.channel + ".py")
|
|
|
|
logger.info("channel_file= " + channel_file + ' - ' + CHANNELS +' - ' + item.channel)
|
|
|
|
channel = None
|
|
|
|
if os.path.exists(channel_file):
|
|
try:
|
|
channel = __import__(CHANNELS + item.channel, None, None, [CHANNELS + item.channel])
|
|
except ImportError:
|
|
importer = "import " + CHANNELS + "." + item.channel + " as channel "
|
|
|
|
exec(importer)
|
|
|
|
logger.info("Running channel %s | %s" % (channel.__name__, channel.__file__))
|
|
|
|
# Special play action
|
|
if item.action == "play":
|
|
#define la info para trakt
|
|
try:
|
|
trakt_tools.set_trakt_info(item)
|
|
except:
|
|
pass
|
|
logger.info("item.action=%s" % item.action.upper())
|
|
# logger.debug("item_toPlay: " + "\n" + item.tostring('\n'))
|
|
|
|
# First checks if channel has a "play" function
|
|
if hasattr(channel, 'play'):
|
|
logger.info("Executing channel 'play' method")
|
|
itemlist = channel.play(item)
|
|
b_favourite = item.isFavourite
|
|
# Play should return a list of playable URLS
|
|
if len(itemlist) > 0 and isinstance(itemlist[0], Item):
|
|
item = itemlist[0]
|
|
if b_favourite:
|
|
item.isFavourite = True
|
|
platformtools.play_video(item)
|
|
|
|
# Permitir varias calidades desde play en el canal
|
|
elif len(itemlist) > 0 and isinstance(itemlist[0], list):
|
|
item.video_urls = itemlist
|
|
platformtools.play_video(item)
|
|
|
|
# If not, shows user an error message
|
|
else:
|
|
platformtools.dialog_ok(config.get_localized_string(20000), config.get_localized_string(60339))
|
|
|
|
# If player don't have a "play" function, not uses the standard play from platformtools
|
|
else:
|
|
logger.info("Executing core 'play' method")
|
|
platformtools.play_video(item)
|
|
|
|
# Special action for findvideos, where the plugin looks for known urls
|
|
elif item.action == "findvideos":
|
|
|
|
# First checks if channel has a "findvideos" function
|
|
if hasattr(channel, 'findvideos'):
|
|
itemlist = getattr(channel, item.action)(item)
|
|
itemlist = servertools.filter_servers(itemlist)
|
|
|
|
# If not, uses the generic findvideos function
|
|
else:
|
|
logger.info("No channel 'findvideos' method, "
|
|
"executing core method")
|
|
itemlist = servertools.find_video_items(item)
|
|
|
|
if config.get_setting("max_links", "videolibrary") != 0:
|
|
itemlist = limit_itemlist(itemlist)
|
|
|
|
from platformcode import subtitletools
|
|
subtitletools.saveSubtitleName(item)
|
|
|
|
platformtools.render_items(itemlist, item)
|
|
|
|
# Special action for adding a movie to the library
|
|
elif item.action == "add_pelicula_to_library":
|
|
videolibrarytools.add_movie(item)
|
|
|
|
# Special action for adding a serie to the library
|
|
elif item.action == "add_serie_to_library":
|
|
videolibrarytools.add_tvshow(item, channel)
|
|
|
|
# Special action for downloading all episodes from a serie
|
|
elif item.action == "download_all_episodes":
|
|
from specials import downloads
|
|
item.action = item.extra
|
|
del item.extra
|
|
downloads.save_download(item)
|
|
|
|
# Special action for searching, first asks for the words then call the "search" function
|
|
elif item.action == "search":
|
|
logger.info("item.action=%s" % item.action.upper())
|
|
|
|
last_search = ""
|
|
last_search_active = config.get_setting("last_search", "search")
|
|
if last_search_active:
|
|
try:
|
|
current_saved_searches_list = list(config.get_setting("saved_searches_list", "search"))
|
|
last_search = current_saved_searches_list[0]
|
|
except:
|
|
pass
|
|
|
|
tecleado = platformtools.dialog_input(last_search)
|
|
if tecleado is not None:
|
|
if last_search_active and not tecleado.startswith("http"):
|
|
from specials import search
|
|
search.save_search(tecleado)
|
|
|
|
if 'search' in dir(channel):
|
|
itemlist = channel.search(item, tecleado)
|
|
else:
|
|
from core import support
|
|
itemlist = support.search(channel, item, tecleado)
|
|
else:
|
|
return
|
|
|
|
platformtools.render_items(itemlist, item)
|
|
|
|
# For all other actions
|
|
else:
|
|
# import web_pdb; web_pdb.set_trace()
|
|
logger.info("Executing channel '%s' method" % item.action)
|
|
itemlist = getattr(channel, item.action)(item)
|
|
if config.get_setting('trakt_sync'):
|
|
token_auth = config.get_setting("token_trakt", "trakt")
|
|
if not token_auth:
|
|
trakt_tools.auth_trakt()
|
|
else:
|
|
import xbmc
|
|
if not xbmc.getCondVisibility('System.HasAddon(script.trakt)') and config.get_setting(
|
|
'install_trakt'):
|
|
trakt_tools.ask_install_script()
|
|
itemlist = trakt_tools.trakt_check(itemlist)
|
|
else:
|
|
config.set_setting('install_trakt', True)
|
|
|
|
platformtools.render_items(itemlist, item)
|
|
|
|
except urllib2.URLError, e:
|
|
import traceback
|
|
logger.error(traceback.format_exc())
|
|
|
|
# Grab inner and third party errors
|
|
if hasattr(e, 'reason'):
|
|
logger.error("Razon del error, codigo: %s | Razon: %s" % (str(e.reason[0]), str(e.reason[1])))
|
|
texto = config.get_localized_string(30050) # "No se puede conectar con el sitio web"
|
|
platformtools.dialog_ok(config.get_localized_string(20000), texto)
|
|
|
|
# Grab server response errors
|
|
elif hasattr(e, 'code'):
|
|
logger.error("Codigo de error HTTP : %d" % e.code)
|
|
# "El sitio web no funciona correctamente (error http %d)"
|
|
platformtools.dialog_ok(config.get_localized_string(20000), config.get_localized_string(30051) % e.code)
|
|
except WebErrorException, e:
|
|
import traceback
|
|
logger.error(traceback.format_exc())
|
|
|
|
patron = 'File "' + os.path.join(config.get_runtime_path(), CHANNELS, "").replace("\\", "\\\\") + '([^.]+)\.py"'
|
|
canal = scrapertools.find_single_match(traceback.format_exc(), patron)
|
|
|
|
platformtools.dialog_ok(
|
|
config.get_localized_string(59985) + canal,
|
|
config.get_localized_string(60013) %(e))
|
|
except:
|
|
import traceback
|
|
logger.error(traceback.format_exc())
|
|
|
|
patron = 'File "' + os.path.join(config.get_runtime_path(), "channels", "").replace("\\", "\\\\") + '([^.]+)\.py"'
|
|
canal = scrapertools.find_single_match(traceback.format_exc(), patron)
|
|
|
|
try:
|
|
import xbmc
|
|
if config.get_platform(True)['num_version'] < 14:
|
|
log_name = "xbmc.log"
|
|
else:
|
|
log_name = "kodi.log"
|
|
log_message = config.get_localized_string(50004) + xbmc.translatePath("special://logpath") + log_name
|
|
except:
|
|
log_message = ""
|
|
|
|
if canal:
|
|
if item.url:
|
|
if platformtools.dialog_yesno(config.get_localized_string(60087) % canal, config.get_localized_string(60014),
|
|
log_message, nolabel='ok', yeslabel=config.get_localized_string(70739)):
|
|
run(Item(action="open_browser", url=item.url))
|
|
else:
|
|
platformtools.dialog_ok(config.get_localized_string(60087) % canal,
|
|
config.get_localized_string(60014),
|
|
log_message)
|
|
else:
|
|
platformtools.dialog_ok(
|
|
config.get_localized_string(60038),
|
|
config.get_localized_string(60015),
|
|
log_message)
|
|
|
|
|
|
|
|
def reorder_itemlist(itemlist):
|
|
logger.info()
|
|
# logger.debug("Inlet itemlist size: %i" % len(itemlist))
|
|
|
|
new_list = []
|
|
mod_list = []
|
|
not_mod_list = []
|
|
|
|
modified = 0
|
|
not_modified = 0
|
|
|
|
to_change = [[config.get_localized_string(60335), '[V]'],
|
|
[config.get_localized_string(60336), '[D]']]
|
|
|
|
for item in itemlist:
|
|
old_title = unicode(item.title, "utf8").lower().encode("utf8")
|
|
for before, after in to_change:
|
|
if before in item.title:
|
|
item.title = item.title.replace(before, after)
|
|
break
|
|
|
|
new_title = unicode(item.title, "utf8").lower().encode("utf8")
|
|
if old_title != new_title:
|
|
mod_list.append(item)
|
|
modified += 1
|
|
else:
|
|
not_mod_list.append(item)
|
|
not_modified += 1
|
|
|
|
# logger.debug("OLD: %s | NEW: %s" % (old_title, new_title))
|
|
|
|
new_list.extend(mod_list)
|
|
new_list.extend(not_mod_list)
|
|
|
|
logger.info("Titulos modificados:%i | No modificados:%i" % (modified, not_modified))
|
|
|
|
if len(new_list) == 0:
|
|
new_list = itemlist
|
|
|
|
# logger.debug("Outlet itemlist size: %i" % len(new_list))
|
|
return new_list
|
|
|
|
|
|
def limit_itemlist(itemlist):
|
|
logger.info()
|
|
# logger.debug("Inlet itemlist size: %i" % len(itemlist))
|
|
|
|
try:
|
|
opt = config.get_setting("max_links", "videolibrary")
|
|
if opt == 0:
|
|
new_list = itemlist
|
|
else:
|
|
i_max = 30 * opt
|
|
new_list = itemlist[:i_max]
|
|
|
|
# logger.debug("Outlet itemlist size: %i" % len(new_list))
|
|
return new_list
|
|
except:
|
|
return itemlist
|
|
|
|
|
|
def play_from_library(item):
|
|
"""
|
|
Los .strm al reproducirlos desde kodi, este espera que sea un archivo "reproducible" asi que no puede contener
|
|
más items, como mucho se puede colocar un dialogo de seleccion.
|
|
Esto lo solucionamos "engañando a kodi" y haciendole creer que se ha reproducido algo, asi despues mediante
|
|
"Container.Update()" cargamos el strm como si un item desde dentro del addon se tratara, quitando todas
|
|
las limitaciones y permitiendo reproducir mediante la funcion general sin tener que crear nuevos métodos para
|
|
la videoteca.
|
|
@type item: item
|
|
@param item: elemento con información
|
|
"""
|
|
logger.info()
|
|
#logger.debug("item: \n" + item.tostring('\n'))
|
|
|
|
import xbmcgui
|
|
import xbmcplugin
|
|
import xbmc
|
|
from time import sleep
|
|
|
|
# Intentamos reproducir una imagen (esto no hace nada y ademas no da error)
|
|
xbmcplugin.setResolvedUrl(int(sys.argv[1]), True,
|
|
xbmcgui.ListItem(
|
|
path=os.path.join(config.get_runtime_path(), "resources", "kod.mp4")))
|
|
|
|
# Por si acaso la imagen hiciera (en futuras versiones) le damos a stop para detener la reproduccion
|
|
# sleep(0.5) ### Si no se pone esto se bloquea Kodi
|
|
xbmc.Player().stop()
|
|
|
|
# modificamos el action (actualmente la videoteca necesita "findvideos" ya que es donde se buscan las fuentes
|
|
item.action = "findvideos"
|
|
|
|
window_type = config.get_setting("window_type", "videolibrary")
|
|
|
|
# y volvemos a lanzar kodi
|
|
if xbmc.getCondVisibility('Window.IsMedia') and not window_type == 1:
|
|
# Ventana convencional
|
|
xbmc.executebuiltin("Container.Update(" + sys.argv[0] + "?" + item.tourl() + ")")
|
|
|
|
else:
|
|
# Ventana emergente
|
|
from specials import videolibrary
|
|
p_dialog = platformtools.dialog_progress_bg(config.get_localized_string(20000), config.get_localized_string(70004))
|
|
p_dialog.update(0, '')
|
|
|
|
itemlist = videolibrary.findvideos(item)
|
|
|
|
|
|
while platformtools.is_playing():
|
|
# Ventana convencional
|
|
sleep(5)
|
|
p_dialog.update(50, '')
|
|
|
|
'''# Se filtran los enlaces segun la lista negra
|
|
if config.get_setting('filter_servers', "servers"):
|
|
itemlist = servertools.filter_servers(itemlist)'''
|
|
|
|
# Se limita la cantidad de enlaces a mostrar
|
|
if config.get_setting("max_links", "videolibrary") != 0:
|
|
itemlist = limit_itemlist(itemlist)
|
|
|
|
# Se "limpia" ligeramente la lista de enlaces
|
|
if config.get_setting("replace_VD", "videolibrary") == 1:
|
|
itemlist = reorder_itemlist(itemlist)
|
|
|
|
|
|
import time
|
|
p_dialog.update(100, '')
|
|
time.sleep(0.5)
|
|
p_dialog.close()
|
|
|
|
|
|
if len(itemlist) > 0:
|
|
while not xbmc.Monitor().abortRequested():
|
|
# El usuario elige el mirror
|
|
opciones = []
|
|
for item in itemlist:
|
|
opciones.append(item.title)
|
|
|
|
# Se abre la ventana de seleccion
|
|
if (item.contentSerieName != "" and
|
|
item.contentSeason != "" and
|
|
item.contentEpisodeNumber != ""):
|
|
cabecera = ("%s - %sx%s -- %s" %
|
|
(item.contentSerieName,
|
|
item.contentSeason,
|
|
item.contentEpisodeNumber,
|
|
config.get_localized_string(30163)))
|
|
else:
|
|
cabecera = config.get_localized_string(30163)
|
|
|
|
seleccion = platformtools.dialog_select(cabecera, opciones)
|
|
|
|
if seleccion == -1:
|
|
return
|
|
else:
|
|
item = videolibrary.play(itemlist[seleccion])[0]
|
|
item.play_from = 'window'
|
|
platformtools.play_video(item)
|
|
|
|
from specials import autoplay
|
|
if (platformtools.is_playing() and item.action) or item.server == 'torrent' or autoplay.is_active(item.contentChannel):
|
|
break
|