Revert "Created branch develop"

This commit is contained in:
Alfa
2017-08-13 11:21:50 +02:00
committed by GitHub
parent 8000a6fd25
commit e549d644a9
395 changed files with 1849 additions and 10246 deletions

View File

@@ -1,12 +0,0 @@
# -*- coding: utf-8 -*-
import os
import sys
# Appends the main plugin dir to the PYTHONPATH if an internal package cannot be imported.
# Examples: In Plex Media Server all modules are under "Code.*" package, and in Enigma2 under "Plugins.Extensions.*"
try:
# from core import logger
import core
except:
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")))

View File

@@ -1,393 +0,0 @@
# -*- coding: utf-8 -*-
# ------------------------------------------------------------
# Parámetros de configuración (mediaserver)
# ------------------------------------------------------------
import os
import re
import threading
PLATFORM_NAME = "mediaserver"
PLUGIN_NAME = "alfa"
settings_dic = {}
settings_types = {}
adult_setting = {}
def get_platform(full_version=False):
# full_version solo es util en xbmc/kodi
ret = {
'num_version': 1.0,
'name_version': PLATFORM_NAME,
'video_db': "",
'plaform': PLATFORM_NAME
}
if full_version:
return ret
else:
return PLATFORM_NAME
def is_xbmc():
return False
def get_videolibrary_support():
return True
def get_system_platform():
""" fonction: pour recuperer la platform que xbmc tourne """
platform = "unknown"
if sys.platform == "linux" or sys.platform == "linux2":
platform = "linux"
elif sys.platform == "darwin":
platform = "osx"
elif sys.platform == "win32":
platform = "windows"
return platform
def open_settings():
Opciones = []
from xml.dom import minidom
settings = open(menufilepath, 'rb').read()
xmldoc = minidom.parseString(settings)
for category in xmldoc.getElementsByTagName("category"):
for setting in category.getElementsByTagName("setting"):
Opciones.append(dict(setting.attributes.items() + [(u"category", category.getAttribute("label")),
(u"value", get_setting(setting.getAttribute("id")))]))
from platformcode import platformtools
global adult_setting
adult_password = get_setting('adult_password')
if not adult_password:
adult_password = set_setting('adult_password', '0000')
adult_mode = get_setting('adult_mode')
adult_request_password = get_setting('adult_request_password')
platformtools.open_settings(Opciones)
# Hemos accedido a la seccion de Canales para adultos
if get_setting('adult_aux_intro_password'):
# La contraseña de acceso es correcta
if get_setting('adult_aux_intro_password') == adult_password:
# Cambio de contraseña
if get_setting('adult_aux_new_password1'):
if get_setting('adult_aux_new_password1') == get_setting('adult_aux_new_password2'):
set_setting('adult_password', get_setting('adult_aux_new_password1'))
else:
platformtools.dialog_ok("Canales para adultos",
"Los campos 'Nueva contraseña' y 'Confirmar nueva contraseña' no coinciden.",
"Entre de nuevo en 'Preferencias' para cambiar la contraseña")
# Fijar adult_pin
adult_pin = ""
if get_setting("adult_request_password") == True:
adult_pin = get_setting("adult_password")
set_setting("adult_pin", adult_pin)
# Solo esta sesion:
id = threading.current_thread().name
if get_setting("adult_mode") == 2:
adult_setting[id] = True
set_setting("adult_mode", "0")
else:
adult_setting = {}
else:
platformtools.dialog_ok("Canales para adultos", "La contraseña no es correcta.",
"Los cambios realizados en esta sección no se guardaran.")
# Deshacer cambios
set_setting("adult_mode", adult_mode)
set_setting("adult_request_password", adult_request_password)
# Borramos settings auxiliares
set_setting('adult_aux_intro_password', '')
set_setting('adult_aux_new_password1', '')
set_setting('adult_aux_new_password2', '')
def get_setting(name, channel="", server=""):
"""
Retorna el valor de configuracion del parametro solicitado.
Devuelve el valor del parametro 'name' en la configuracion global o en la configuracion propia del canal 'channel'.
Si se especifica el nombre del canal busca en la ruta \addon_data\plugin.video.alfa\settings_channels el
archivo channel_data.json y lee el valor del parametro 'name'. Si el archivo channel_data.json no existe busca en la
carpeta channels el archivo channel.xml y crea un archivo channel_data.json antes de retornar el valor solicitado.
Si el parametro 'name' no existe en channel_data.json lo busca en la configuracion global y si ahi tampoco existe
devuelve un str vacio.
Parametros:
name -- nombre del parametro
channel [opcional] -- nombre del canal
Retorna:
value -- El valor del parametro 'name'
"""
# Specific channel setting
if channel:
# logger.info("config.get_setting reading channel setting '"+name+"' from channel json")
from core import channeltools
value = channeltools.get_channel_setting(name, channel)
# logger.info("config.get_setting -> '"+repr(value)+"'")
return value
elif server:
# logger.info("config.get_setting reading server setting '"+name+"' from server json")
from core import servertools
value = servertools.get_server_setting(name, server)
# logger.info("config.get_setting -> '"+repr(value)+"'")
return value
# Global setting
else:
# logger.info("config.get_setting reading main setting '"+name+"'")
global settings_dic
value = settings_dic.get(name, "")
if name == "adult_mode":
global adult_setting
id = threading.current_thread().name
if adult_setting.get(id) == True:
value = "2"
# hack para devolver el tipo correspondiente
global settings_types
if settings_types.get(name) in ['enum', 'number']:
value = int(value)
elif settings_types.get(name) == 'bool':
value = value == 'true'
elif not settings_types.has_key(name):
try:
t = eval(value)
value = t[0](t[1])
except:
value = None
return value
def set_setting(name, value, channel="", server=""):
"""
Fija el valor de configuracion del parametro indicado.
Establece 'value' como el valor del parametro 'name' en la configuracion global o en la configuracion propia del
canal 'channel'.
Devuelve el valor cambiado o None si la asignacion no se ha podido completar.
Si se especifica el nombre del canal busca en la ruta \addon_data\plugin.video.alfa\settings_channels el
archivo channel_data.json y establece el parametro 'name' al valor indicado por 'value'. Si el archivo
channel_data.json no existe busca en la carpeta channels el archivo channel.xml y crea un archivo channel_data.json
antes de modificar el parametro 'name'.
Si el parametro 'name' no existe lo añade, con su valor, al archivo correspondiente.
Parametros:
name -- nombre del parametro
value -- valor del parametro
channel [opcional] -- nombre del canal
Retorna:
'value' en caso de que se haya podido fijar el valor y None en caso contrario
"""
if channel:
from core import channeltools
return channeltools.set_channel_setting(name, value, channel)
elif server:
from core import servertools
return servertools.set_server_setting(name, value, server)
else:
global settings_dic
global settings_types
if settings_types.get(name) == 'bool':
if value:
new_value = "true"
else:
new_value = "false"
elif settings_types.get(name):
new_value = str(value)
else:
if isinstance(value, basestring):
new_value = "(%s, %s)" % (type(value).__name__, repr(value))
else:
new_value = "(%s, %s)" % (type(value).__name__, value)
settings_dic[name] = new_value
from xml.dom import minidom
# Crea un Nuevo XML vacio
new_settings = minidom.getDOMImplementation().createDocument(None, "settings", None)
new_settings_root = new_settings.documentElement
for key in settings_dic:
nodo = new_settings.createElement("setting")
nodo.setAttribute("value", settings_dic[key])
nodo.setAttribute("id", key)
new_settings_root.appendChild(nodo)
fichero = open(configfilepath, "w")
fichero.write(new_settings.toprettyxml(encoding='utf-8'))
fichero.close()
return value
def get_localized_string(code):
translationsfile = open(TRANSLATION_FILE_PATH, "r")
translations = translationsfile.read()
translationsfile.close()
cadenas = re.findall('<string id="%s">([^<]+)<' % code, translations)
if len(cadenas) > 0:
dev = cadenas[0]
else:
dev = "%d" % code
try:
dev = dev.encode("utf-8")
except:
pass
return dev
def get_videolibrary_path():
value = get_setting("videolibrarypath")
if value == "":
verify_directories_created()
value = get_setting("videolibrarypath")
return value
def get_temp_file(filename):
import tempfile
return os.path.join(tempfile.gettempdir(), filename)
def get_runtime_path():
return os.getcwd()
def get_data_path():
dev = os.path.join(os.path.expanduser("~"), ".alfa")
# Crea el directorio si no existe
if not os.path.exists(dev):
os.makedirs(dev)
return dev
def get_cookie_data():
import os
ficherocookies = os.path.join(get_data_path(), 'cookies.dat')
cookiedatafile = open(ficherocookies, 'r')
cookiedata = cookiedatafile.read()
cookiedatafile.close()
return cookiedata
# Test if all the required directories are created
def verify_directories_created():
from platformcode import logger
from core import filetools
config_paths = [["videolibrarypath", "library"],
["downloadpath", "downloads"],
["downloadlistpath", "downloads/list"],
["bookmarkpath", "favorites"],
["settings_path", "settings_channels"]]
for path, default in config_paths:
saved_path = get_setting(path)
if not saved_path:
saved_path = filetools.join(get_data_path(), *default.split("/"))
set_setting(path, saved_path)
if not filetools.exists(saved_path):
logger.debug("Creating %s: %s" % (path, saved_path))
filetools.mkdir(saved_path)
def get_local_ip():
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(('8.8.8.8', 53)) # connecting to a UDP address doesn't send packets
myip = s.getsockname()[0]
return myip
def load_settings():
global settings_dic
global settings_types
defaults = {}
from xml.etree import ElementTree
encontrado = False
# Lee el archivo XML (si existe)
if os.path.exists(configfilepath):
settings = open(configfilepath, 'rb').read()
root = ElementTree.fromstring(settings)
for target in root.findall("setting"):
settings_dic[target.get("id")] = target.get("value")
defaultsettings = open(menufilepath, 'rb').read()
root = ElementTree.fromstring(defaultsettings)
for category in root.findall("category"):
for target in category.findall("setting"):
if target.get("id"):
defaults[target.get("id")] = target.get("default")
settings_types[target.get("id")] = target.get("type")
for key in defaults:
if not key in settings_dic:
settings_dic[key] = defaults[key]
set_settings(settings_dic)
def set_settings(JsonRespuesta):
for Ajuste in JsonRespuesta:
settings_dic[Ajuste] = JsonRespuesta[Ajuste].encode("utf8")
from xml.dom import minidom
# Crea un Nuevo XML vacio
new_settings = minidom.getDOMImplementation().createDocument(None, "settings", None)
new_settings_root = new_settings.documentElement
for key in settings_dic:
nodo = new_settings.createElement("setting")
nodo.setAttribute("value", settings_dic[key])
nodo.setAttribute("id", key)
new_settings_root.appendChild(nodo)
fichero = open(configfilepath, "w")
fichero.write(new_settings.toprettyxml(encoding='utf-8'))
fichero.close()
# Fichero de configuración
menufilepath = os.path.join(get_runtime_path(), "resources", "settings.xml")
configfilepath = os.path.join(get_data_path(), "settings.xml")
if not os.path.exists(get_data_path()): os.mkdir(get_data_path())
# Literales
TRANSLATION_FILE_PATH = os.path.join(get_runtime_path(), "resources", "language", "Spanish", "strings.xml")
load_settings()

View File

@@ -1,41 +0,0 @@
# -*- coding: utf-8 -*-
# ------------------------------------------------------------
# Módulo para acciones en el cliente HTML
# ------------------------------------------------------------
import os
from inspect import isclass
from controller import Controller
from platformcode import logger
def load_controllers():
controllers = []
path = os.path.split(__file__)[0]
for fname in os.listdir(path):
mod, ext = os.path.splitext(fname)
fname = os.path.join(path, fname)
if os.path.isfile(fname) and ext == '.py' and not mod.startswith('_'):
try:
exec "import " + mod + " as controller"
except:
import traceback
logger.error(traceback.format_exc())
for c in dir(controller):
cls = getattr(controller, c)
if not c.startswith('_') and isclass(cls) and issubclass(cls, Controller) and Controller != cls:
controllers.append(cls)
return controllers
controllers = load_controllers()
def find_controller(url):
result = []
for c in controllers:
if c().match(url):
return c

View File

@@ -1,129 +0,0 @@
# -*- coding: utf-8 -*-
# ------------------------------------------------------------
# Mediaserver Base controller
# ------------------------------------------------------------
import threading
from platformcode import config, platformtools
class Controller(object):
pattern = ""
name = None
def __init__(self, handler=None, ID=None):
self.handler = handler
self.id = ID
if not self.id:
self.id = threading.current_thread().name
if self.handler:
self.platformtools = Platformtools()
self.host = "http://%s:%s" % (config.get_local_ip(), config.get_setting("server.port"))
def __setattr__(self, name, value):
super(Controller, self).__setattr__(name, value)
if name == "platformtools":
platformtools.controllers[self.id] = self.platformtools
def __del__(self):
from platformcode import platformtools
if self.id in platformtools.controllers:
del platformtools.controllers[self.id]
def run(self, path):
pass
def match(self, path):
if self.pattern.findall(path):
return True
else:
return False
class Platformtools(object):
def dialog_ok(self, heading, line1, line2="", line3=""):
pass
def dialog_notification(self, heading, message, icon=0, time=5000, sound=True):
pass
def dialog_yesno(self, heading, line1, line2="", line3="", nolabel="No", yeslabel="Si", autoclose=""):
return True
def dialog_select(self, heading, list):
pass
def dialog_progress(self, heading, line1, line2="", line3=""):
class Dialog(object):
def __init__(self, heading, line1, line2, line3, PObject):
self.PObject = PObject
self.closed = False
self.heading = heading
text = line1
if line2: text += "\n" + line2
if line3: text += "\n" + line3
def iscanceled(self):
return self.closed
def update(self, percent, line1, line2="", line3=""):
pass
def close(self):
self.closed = True
return Dialog(heading, line1, line2, line3, None)
def dialog_progress_bg(self, heading, message=""):
class Dialog(object):
def __init__(self, heading, message, PObject):
self.PObject = PObject
self.closed = False
self.heading = heading
def isFinished(self):
return not self.closed
def update(self, percent=0, heading="", message=""):
pass
def close(self):
self.closed = True
return Dialog(heading, message, None)
def dialog_input(self, default="", heading="", hidden=False):
return default
def dialog_numeric(self, type, heading, default=""):
return None
def itemlist_refresh(self):
pass
def itemlist_update(self, item):
pass
def render_items(self, itemlist, parentitem):
pass
def is_playing(self):
return False
def play_video(self, item):
pass
def show_channel_settings(self, list_controls=None, dict_values=None, caption="", callback=None, item=None,
custom_button=None, channelpath=None):
pass
def show_video_info(self, data, caption="Información del vídeo", callback=None, item=None):
pass
def show_recaptcha(self, key, url):
pass

View File

@@ -1,104 +0,0 @@
# -*- coding: utf-8 -*-
# ------------------------------------------------------------
# Controlador para acceso a archivos locales
# ------------------------------------------------------------
import os
import re
import time
from controller import Controller
from platformcode import config, logger
class fileserver(Controller):
pattern = re.compile("^/(?:media/.*?)?(?:local/.*?)?$")
def run(self, path):
if path == "/":
f = open(os.path.join(config.get_runtime_path(), "platformcode", "template", "page.html"), "rb")
self.handler.send_response(200)
self.handler.send_header('Content-type', 'text/html')
self.handler.end_headers()
respuesta = f.read()
respuesta = respuesta.replace("{$WSPORT}", str(config.get_setting("websocket.port")))
self.handler.wfile.write(respuesta)
f.close()
elif path.startswith("/local/"):
import base64
import urllib
Path = path.replace("/local/", "").split("/")[0]
Path = base64.b64decode(urllib.unquote_plus(Path))
Size = int(os.path.getsize(Path.decode("utf8")))
f = open(Path.decode("utf8"), "rb")
if not self.handler.headers.get("range") == None:
if "=" in str(self.handler.headers.get("range")) and "-" in str(self.handler.headers.get("range")):
Inicio = int(self.handler.headers.get("range").split("=")[1].split("-")[0])
if self.handler.headers.get("range").split("=")[1].split("-")[1] <> "":
Fin = int(self.handler.headers.get("range").split("=")[1].split("-")[1])
else:
Fin = Size - 1
else:
Inicio = 0
Fin = Size - 1
if not Fin > Inicio: Fin = Size - 1
if self.handler.headers.get("range") == None:
logger.info("-------------------------------------------------------")
logger.info("Solicitando archivo local: " + Path)
logger.info("-------------------------------------------------------")
self.handler.send_response(200)
self.handler.send_header("Content-Disposition", "attachment; filename=video.mp4")
self.handler.send_header('Accept-Ranges', 'bytes')
self.handler.send_header('Content-Length', str(Size))
self.handler.send_header("Connection", "close")
self.handler.end_headers()
while True:
time.sleep(0.2)
buffer = f.read(1024 * 250)
if not buffer:
break
self.handler.wfile.write(buffer)
self.handler.wfile.close()
f.close()
else:
logger.info("-------------------------------------------------------")
logger.info("Solicitando archivo local: " + Path)
logger.info("Rango: " + str(Inicio) + "-" + str(Fin) + "/" + str(Size))
logger.info("-------------------------------------------------------")
f.seek(Inicio)
self.handler.send_response(206)
self.handler.send_header("Content-Disposition", "attachment; filename=video.mp4")
self.handler.send_header('Accept-Ranges', 'bytes')
self.handler.send_header('Content-Length', str(Fin - Inicio))
self.handler.send_header('Content-Range', str(Inicio) + "-" + str(Fin) + "/" + str(Size))
self.handler.send_header("Connection", "close")
self.handler.end_headers()
while True:
time.sleep(0.2)
buffer = f.read(1024 * 250)
if not buffer:
break
self.handler.wfile.write(buffer)
self.handler.wfile.close()
f.close()
elif path.startswith("/media/"):
file = os.path.join(config.get_runtime_path(), "platformcode", "template", path[7:])
from mimetypes import MimeTypes
mime = MimeTypes()
mime_type = mime.guess_type(file)
try:
mim = mime_type[0]
except:
mim = ""
f = open(file, "rb")
self.handler.send_response(200)
self.handler.send_header('Content-type', mim)
self.handler.end_headers()
self.handler.wfile.write(f.read())
f.close()

View File

@@ -1,788 +0,0 @@
# -*- coding: utf-8 -*-
# ------------------------------------------------------------
# Controlador para HTML
# ------------------------------------------------------------
import json
import os
import re
import threading
import time
import channelselector
from controller import Controller
from controller import Platformtools
from platformcode import config
from core import versiontools
from core.item import Item
from core.tmdb import Tmdb
from platformcode import launcher, logger
class html(Controller):
pattern = re.compile("##")
name = "HTML"
def __init__(self, handler=None, ID=None):
super(html, self).__init__(handler, ID)
self.platformtools = platform(self)
self.data = {}
if self.handler:
self.client_ip = handler.client.getpeername()[0]
self.send_message({"action": "connect",
"data": {"version": "Alfa %s" % versiontools.get_current_plugin_version_tag(),
"date": versiontools.get_current_plugin_date()}})
t = threading.Thread(target=launcher.start, name=ID)
t.setDaemon(True)
t.start()
def run(self, path):
if path:
item = Item().fromurl(path)
else:
item = Item(channel="channelselector", action="mainlist", viewmode="banner")
launcher.run(item)
def get_data(self, id):
while not "id" in self.data or not self.data["id"] == id:
time.sleep(0.1)
data = self.data["result"]
self.data = {}
return data
def send_message(self, data):
import random
ID = "%032x" % (random.getrandbits(128))
data["id"] = ID
self.handler.sendMessage(json.dumps(data))
return ID
class platform(Platformtools):
def __init__(self, controller):
self.controller = controller
self.handler = controller.handler
self.get_data = controller.get_data
self.send_message = controller.send_message
def render_items(self, itemlist, parent_item):
"""
Función encargada de mostrar el itemlist, se pasa como parametros el itemlist y el item del que procede
@type itemlist: list
@param itemlist: lista de elementos a mostrar
@type parent_item: item
@param parent_item: elemento padre
"""
# Si el itemlist no es un list salimos
if not type(itemlist) == list:
JsonData = {}
JsonData["action"] = "HideLoading"
JsonData["data"] = {}
self.send_message(JsonData)
return
# Si no hay ningun item, mostramos un aviso
if not len(itemlist):
itemlist.append(Item(title="No hay elementos que mostrar"))
if parent_item.channel == "channelselector" and not parent_item.action == "filterchannels":
parent_item.viewmode = "banner"
elif parent_item.channel == "channelselector" and parent_item.action == "filterchannels":
parent_item.viewmode = "channel"
if not parent_item.viewmode:
parent_item.viewmode = "list"
# Item Atrás
if not (parent_item.channel == "channelselector" and parent_item.action == "mainlist") and not \
itemlist[0].action == "go_back":
if parent_item.viewmode in ["banner", "channel"]:
itemlist.insert(0, Item(title="Atrás", action="go_back",
thumbnail=channelselector.get_thumb("back.png", "banner_")))
else:
itemlist.insert(0, Item(title="Atrás", action="go_back",
thumbnail=channelselector.get_thumb("back.png")))
JsonData = {}
JsonData["action"] = "EndItems"
JsonData["data"] = {}
JsonData["data"]["itemlist"] = []
JsonData["data"]["viewmode"] = parent_item.viewmode
JsonData["data"]["category"] = parent_item.category.capitalize()
JsonData["data"]["host"] = self.controller.host
# Recorremos el itemlist
for item in itemlist:
if not item.thumbnail and item.action == "search": item.thumbnail = channelselector.get_thumb("search.png")
if not item.thumbnail and item.folder == True: item.thumbnail = channelselector.get_thumb("folder.png", "banner")
if not item.thumbnail and item.folder == False: item.thumbnail = channelselector.get_thumb("nofolder.png")
if "http://media.xxxxx/" in item.thumbnail and not item.thumbnail.startswith(
"http://media.xxxxxxxx/thumb_"):
if parent_item.viewmode in ["banner", "channel"]:
item.thumbnail = channelselector.get_thumbnail_path("banner") + os.path.basename(item.thumbnail)
else:
item.thumbnail = channelselector.get_thumbnail_path() + os.path.basename(item.thumbnail)
# Estas imagenes no estan en banner, asi que si queremos banner, para que no se vean mal las quitamos
elif parent_item.viewmode in ["banner", "channel"] and item.thumbnail.startswith(
"http://media.xxxxx/thumb_"):
item.thumbnail = ""
# Si el item no contiene categoria,le ponemos la del item padre
if item.category == "":
item.category = parent_item.category
# Si el item no contiene fanart,le ponemos la del item padre
if item.fanart == "":
item.fanart = parent_item.fanart
title = item.title.replace(item.title.lstrip(), "").replace(" ", "&nbsp;") + item.title.lstrip()
# Formatear titulo
if item.text_color:
title = '[COLOR %s]%s[/COLOR]' % (item.text_color, title)
if item.text_bold:
title = '[B]%s[/B]' % title
if item.text_italic:
title = '[I]%s[/I]' % title
title = self.kodi_labels_to_html(title)
# Añade headers a las imagenes si estan en un servidor con cloudflare
from core import httptools
item.thumbnail = httptools.get_url_headers(item.thumbnail)
item.fanart = httptools.get_url_headers(item.fanart)
JsonItem = {}
JsonItem["title"] = title
JsonItem["thumbnail"] = item.thumbnail
JsonItem["fanart"] = item.fanart
JsonItem["plot"] = item.plot
JsonItem["action"] = item.action
JsonItem["url"] = item.tourl()
JsonItem["context"] = []
if not item.action == "go_back":
for Comando in self.set_context_commands(item, parent_item):
JsonItem["context"].append({"title": Comando[0], "url": Comando[1]})
JsonData["data"]["itemlist"].append(JsonItem)
ID = self.send_message(JsonData)
self.get_data(ID)
def set_context_commands(self, item, parent_item):
"""
Función para generar los menus contextuales.
1. Partiendo de los datos de item.context
a. Metodo antiguo item.context tipo str separando las opciones por "|" (ejemplo: item.context = "1|2|3")
(solo predefinidos)
b. Metodo list: item.context es un list con las diferentes opciones del menu:
- Predefinidos: Se cargara una opcion predefinida con un nombre.
item.context = ["1","2","3"]
- dict(): Se cargara el item actual modificando los campos que se incluyan en el dict() en caso de
modificar los campos channel y action estos serán guardados en from_channel y from_action.
item.context = [{"title":"Nombre del menu", "action": "action del menu", "channel",
"channel del menu"}, {...}]
2. Añadiendo opciones segun criterios
Se pueden añadir opciones al menu contextual a items que cumplan ciertas condiciones
3. Añadiendo opciones a todos los items
Se pueden añadir opciones al menu contextual para todos los items
@param item: elemento que contiene los menu contextuales
@type item: item
@param parent_item:
@type parent_item: item
"""
context_commands = []
# Creamos un list con las diferentes opciones incluidas en item.context
if type(item.context) == str:
context = item.context.split("|")
elif type(item.context) == list:
context = item.context
else:
context = []
# Opciones segun item.context
for command in context:
# Predefinidos
if type(command) == str:
if command == "buscar_trailer":
context_commands.append(("Buscar Trailer",
item.clone(channel="trailertools", action="buscartrailer",
contextual=True).tourl()))
# Formato dict
if type(command) == dict:
# Los parametros del dict, se sobreescriben al nuevo context_item en caso de sobreescribir "action" y
# "channel", los datos originales se guardan en "from_action" y "from_channel"
if "action" in command:
command["from_action"] = item.action
if "channel" in command:
command["from_channel"] = item.channel
context_commands.append(
(command["title"], item.clone(**command).tourl()))
# Opciones segun criterios
# Ir al Menu Principal (channel.mainlist)
if parent_item.channel not in ["news",
"channelselector"] and item.action != "mainlist" and parent_item.action != "mainlist":
context_commands.append(("Ir al Menu Principal", Item(channel=item.channel, action="mainlist").tourl()))
# Añadir a Favoritos
if item.channel not in ["favorites", "videolibrary", "help", "setting",
""] and not parent_item.channel == "favorites":
context_commands.append((config.get_localized_string(30155),
item.clone(channel="favorites", action="addFavourite", from_channel=item.channel,
from_action=item.action).tourl()))
# Añadimos opción contextual para Añadir la serie completa a la videoteca
if item.channel != "videolibrary" and item.action in ["episodios", "get_episodios"] \
and (item.contentSerieName or item.show):
context_commands.append(("Añadir Serie a Videoteca",
item.clone(action="add_serie_to_library", from_action=item.action).tourl()))
# Añadir Pelicula a videoteca
if item.channel != "videolibrary" and item.action in ["detail", "findvideos"] \
and item.contentType == 'movie':
context_commands.append(("Añadir Pelicula a Videoteca",
item.clone(action="add_pelicula_to_library", from_action=item.action).tourl()))
# Descargar pelicula
if item.contentType == "movie" and not item.channel == "downloads":
context_commands.append(("Descargar Pelicula",
item.clone(channel="downloads", action="save_download", from_channel=item.channel,
from_action=item.action).tourl()))
# Descargar serie
if item.contentType == "tvshow" and not item.channel == "downloads":
context_commands.append(("Descargar Serie",
item.clone(channel="downloads", action="save_download", from_channel=item.channel,
from_action=item.action).tourl()))
# Descargar episodio
if item.contentType == "episode" and not item.channel == "downloads":
context_commands.append(("Descargar Episodio",
item.clone(channel="downloads", action="save_download", from_channel=item.channel,
from_action=item.action).tourl()))
# Descargar temporada
if item.contentType == "season" and not item.channel == "downloads":
context_commands.append(("Descargar Temporada",
item.clone(channel="downloads", action="save_download", from_channel=item.channel,
from_action=item.action).tourl()))
# Abrir configuración
if parent_item.channel not in ["setting", "news", "search"]:
context_commands.append(("Abrir Configuración", Item(channel="setting", action="mainlist").tourl()))
return sorted(context_commands, key=lambda comand: comand[0])
def dialog_ok(self, heading, line1, line2="", line3=""):
text = line1
if line2: text += "\n" + line2
if line3: text += "\n" + line3
text = self.kodi_labels_to_html(text)
JsonData = {}
JsonData["action"] = "Alert"
JsonData["data"] = {}
JsonData["data"]["title"] = heading
JsonData["data"]["text"] = unicode(text, "utf8", "ignore").encode("utf8")
ID = self.send_message(JsonData)
self.get_data(ID)
def dialog_notification(self, heading, message, icon=0, time=5000, sound=True):
JsonData = {}
JsonData["action"] = "notification"
JsonData["data"] = {}
JsonData["data"]["title"] = self.kodi_labels_to_html(heading)
JsonData["data"]["text"] = self.kodi_labels_to_html(message)
JsonData["data"]["icon"] = icon
JsonData["data"]["sound"] = sound
JsonData["data"]["time"] = time
self.send_message(JsonData)
return
def dialog_yesno(self, heading, line1, line2="", line3="", nolabel="No", yeslabel="Si", autoclose=""):
text = line1
if line2: text += "\n" + line2
if line3: text += "\n" + line3
text = self.kodi_labels_to_html(text)
heading = self.kodi_labels_to_html(heading)
JsonData = {}
JsonData["action"] = "AlertYesNo"
JsonData["data"] = {}
JsonData["data"]["title"] = heading
JsonData["data"]["text"] = text
ID = self.send_message(JsonData)
response = self.get_data(ID)
return response
def dialog_select(self, heading, list):
JsonData = {}
heading = self.kodi_labels_to_html(heading)
JsonData["action"] = "List"
JsonData["data"] = {}
JsonData["data"]["title"] = heading
JsonData["data"]["list"] = []
for Elemento in list:
JsonData["data"]["list"].append(self.kodi_labels_to_html(Elemento))
ID = self.send_message(JsonData)
response = self.get_data(ID)
return response
def dialog_progress(self, heading, line1, line2="", line3=""):
class Dialog(object):
def __init__(self, heading, line1, line2, line3, platformtools):
self.platformtools = platformtools
self.closed = False
self.heading = self.platformtools.kodi_labels_to_html(heading)
text = line1
if line2: text += "\n" + line2
if line3: text += "\n" + line3
text = self.platformtools.kodi_labels_to_html(text)
JsonData = {}
JsonData["action"] = "Progress"
JsonData["data"] = {}
JsonData["data"]["title"] = heading
JsonData["data"]["text"] = text
JsonData["data"]["percent"] = 0
ID = self.platformtools.send_message(JsonData)
self.platformtools.get_data(ID)
def iscanceled(self):
JsonData = {}
JsonData["action"] = "ProgressIsCanceled"
JsonData["data"] = {}
ID = self.platformtools.send_message(JsonData)
response = self.platformtools.get_data(ID)
return response
def update(self, percent, line1, line2="", line3=""):
text = line1
if line2: text += "\n" + line2
if line3: text += "\n" + line3
text = self.platformtools.kodi_labels_to_html(text)
JsonData = {}
JsonData["action"] = "ProgressUpdate"
JsonData["data"] = {}
JsonData["data"]["title"] = self.heading
JsonData["data"]["text"] = text
JsonData["data"]["percent"] = percent
self.platformtools.send_message(JsonData)
def close(self):
JsonData = {}
JsonData["action"] = "ProgressClose"
JsonData["data"] = {}
ID = self.platformtools.send_message(JsonData)
self.platformtools.get_data(ID)
self.closed = True
return Dialog(heading, line1, line2, line3, self)
def dialog_progress_bg(self, heading, message=""):
class Dialog(object):
def __init__(self, heading, message, platformtools):
self.platformtools = platformtools
self.closed = False
self.heading = self.platformtools.kodi_labels_to_html(heading)
message = self.platformtools.kodi_labels_to_html(message)
JsonData = {}
JsonData["action"] = "ProgressBG"
JsonData["data"] = {}
JsonData["data"]["title"] = heading
JsonData["data"]["text"] = message
JsonData["data"]["percent"] = 0
ID = self.platformtools.send_message(JsonData)
self.platformtools.get_data(ID)
def isFinished(self):
return not self.closed
def update(self, percent=0, heading="", message=""):
JsonData = {}
JsonData["action"] = "ProgressBGUpdate"
JsonData["data"] = {}
JsonData["data"]["title"] = self.platformtools.kodi_labels_to_html(heading)
JsonData["data"]["text"] = self.platformtools.kodi_labels_to_html(message)
JsonData["data"]["percent"] = percent
self.platformtools.send_message(JsonData)
def close(self):
JsonData = {}
JsonData["action"] = "ProgressBGClose"
JsonData["data"] = {}
ID = self.platformtools.send_message(JsonData)
self.platformtools.get_data(ID)
self.closed = True
return Dialog(heading, message, self)
def dialog_input(self, default="", heading="", hidden=False):
JsonData = {}
JsonData["action"] = "Keyboard"
JsonData["data"] = {}
JsonData["data"]["title"] = self.kodi_labels_to_html(heading)
JsonData["data"]["text"] = default
JsonData["data"]["password"] = hidden
ID = self.send_message(JsonData)
response = self.get_data(ID)
return response
def dialog_numeric(self, type, heading, default=""):
return self.dialog_input("", heading, False)
def itemlist_refresh(self):
JsonData = {}
JsonData["action"] = "Refresh"
JsonData["data"] = {}
ID = self.send_message(JsonData)
self.get_data(ID)
def itemlist_update(self, item):
JsonData = {}
JsonData["action"] = "Update"
JsonData["data"] = {}
JsonData["data"]["url"] = item.tourl()
ID = self.send_message(JsonData)
self.get_data(ID)
def is_playing(self):
JsonData = {}
JsonData["action"] = "isPlaying"
JsonData["data"] = {}
ID = self.send_message(JsonData)
response = self.get_data(ID)
return response
def play_video(self, item):
if item.contentTitle:
title = item.contentTitle
elif item.fulltitle:
title = item.fulltitle
else:
title = item.title
if item.contentPlot:
plot = item.contentPlot
else:
plot = item.plot
if item.server == "torrent":
self.play_torrent(item)
else:
JsonData = {}
JsonData["action"] = "Play"
JsonData["data"] = {}
JsonData["data"]["title"] = title
JsonData["data"]["plot"] = plot
JsonData["data"]["video_url"] = item.video_url
JsonData["data"]["url"] = item.url
JsonData["data"]["host"] = self.controller.host
ID = self.send_message(JsonData)
self.get_data(ID)
def play_torrent(self, item):
import time
import os
played = False
# Importamos el cliente
from btserver import Client
# Iniciamos el cliente:
c = Client(url=item.url, is_playing_fnc=self.is_playing, wait_time=None, timeout=5,
temp_path=os.path.join(config.get_data_path(), "torrent"))
# Mostramos el progreso
progreso = self.dialog_progress("Alfa - Torrent", "Iniciando...")
# Mientras el progreso no sea cancelado ni el cliente cerrado
while not progreso.iscanceled() and not c.closed:
try:
# Obtenemos el estado del torrent
s = c.status
# Montamos las tres lineas con la info del torrent
txt = '%.2f%% de %.1fMB %s | %.1f kB/s' % \
(s.progress_file, s.file_size, s.str_state, s._download_rate)
txt2 = 'S: %d(%d) P: %d(%d) | DHT:%s (%d) | Trakers: %d' % \
(
s.num_seeds, s.num_complete, s.num_peers, s.num_incomplete, s.dht_state, s.dht_nodes,
s.trackers)
txt3 = 'Origen Peers TRK: %d DHT: %d PEX: %d LSD %d ' % \
(s.trk_peers, s.dht_peers, s.pex_peers, s.lsd_peers)
progreso.update(s.buffer, txt, txt2, txt3)
time.sleep(1)
# Si el buffer se ha llenado y la reproduccion no ha sido iniciada, se inicia
if s.buffer == 100 and not played:
# Cerramos el progreso
progreso.close()
# Obtenemos el playlist del torrent
item.video_url = c.get_play_list()
item.server = "directo"
self.play_video(item)
# Marcamos como reproducido para que no se vuelva a iniciar
played = True
# Y esperamos a que el reproductor se cierre
while self.is_playing():
time.sleep(1)
# Cuando este cerrado, Volvemos a mostrar el dialogo
progreso = self.dialog_progress("Alfa - Torrent", "Iniciando...")
except:
import traceback
logger.info(traceback.format_exc())
break
progreso.update(100, "Terminando y eliminando datos", " ", " ")
# Detenemos el cliente
if not c.closed:
c.stop()
# Y cerramos el progreso
progreso.close()
return
def open_settings(self, items):
from platformcode import config
JsonData = {}
JsonData["action"] = "OpenConfig"
JsonData["data"] = {}
JsonData["data"]["title"] = "Opciones"
JsonData["data"]["items"] = []
for item in items:
if item.get('option') == 'hidden':
item['hidden'] = True
for key in item:
if key in ["lvalues", "label", "category"]:
try:
ops = item[key].split("|")
for x, op in enumerate(ops):
ops[x] = config.get_localized_string(int(ops[x]))
item[key] = "|".join(ops)
except:
pass
JsonData["data"]["items"].append(item)
ID = self.send_message(JsonData)
response = self.get_data(ID)
if response:
from platformcode import config
config.set_settings(response)
JsonData = {}
JsonData["action"] = "HideLoading"
JsonData["data"] = {}
self.send_message(JsonData)
def show_channel_settings(self, list_controls=None, dict_values=None, caption="", callback=None, item=None,
custom_button=None, channelpath=None):
from platformcode import config
from core import channeltools
from core import servertools
import inspect
if not os.path.isdir(os.path.join(config.get_data_path(), "settings_channels")):
os.mkdir(os.path.join(config.get_data_path(), "settings_channels"))
title = caption
if type(custom_button) == dict:
custom_button = {"label": custom_button.get("label", ""),
"function": custom_button.get("function", ""),
"visible": bool(custom_button.get("visible", True)),
"close": bool(custom_button.get("close", False))}
else:
custom_button = None
# Obtenemos el canal desde donde se ha echo la llamada y cargamos los settings disponibles para ese canal
if not channelpath:
channelpath = inspect.currentframe().f_back.f_back.f_code.co_filename
channelname = os.path.basename(channelpath).replace(".py", "")
ch_type = os.path.basename(os.path.dirname(channelpath))
# Si no tenemos list_controls, hay que sacarlos del json del canal
if not list_controls:
# Si la ruta del canal esta en la carpeta "channels", obtenemos los controles y valores mediante chaneltools
if os.path.join(config.get_runtime_path(), "channels") in channelpath:
# La llamada se hace desde un canal
list_controls, default_values = channeltools.get_channel_controls_settings(channelname)
kwargs = {"channel": channelname}
# Si la ruta del canal esta en la carpeta "servers", obtenemos los controles y valores mediante servertools
elif os.path.join(config.get_runtime_path(), "servers") in channelpath:
# La llamada se hace desde un server
list_controls, default_values = servertools.get_server_controls_settings(channelname)
kwargs = {"server": channelname}
# En caso contrario salimos
else:
return None
# Si no se pasan dict_values, creamos un dict en blanco
if dict_values == None:
dict_values = {}
# Ponemos el titulo
if caption == "":
caption = str(config.get_localized_string(30100)) + " -- " + channelname.capitalize()
elif caption.startswith('@') and unicode(caption[1:]).isnumeric():
caption = config.get_localized_string(int(caption[1:]))
JsonData = {}
JsonData["action"] = "OpenConfig"
JsonData["data"] = {}
JsonData["data"]["title"] = self.kodi_labels_to_html(caption)
JsonData["data"]["custom_button"] = custom_button
JsonData["data"]["items"] = []
# Añadir controles
for c in list_controls:
if not "default" in c: c["default"] = ""
if not "color" in c: c["color"] = "auto"
if not "label" in c: continue
# Obtenemos el valor
if not c["id"] in dict_values:
if not callback:
c["value"] = config.get_setting(c["id"], **kwargs)
else:
c["value"] = c["default"]
dict_values[c["id"]] = c["value"]
else:
c["value"] = dict_values[c["id"]]
# Translation
if c['label'].startswith('@') and unicode(c['label'][1:]).isnumeric():
c['label'] = str(config.get_localized_string(c['label'][1:]))
if c["label"].endswith(":"): c["label"] = c["label"][:-1]
if c['type'] == 'list':
lvalues = []
for li in c['lvalues']:
if li.startswith('@') and unicode(li[1:]).isnumeric():
lvalues.append(str(config.get_localized_string(li[1:])))
else:
lvalues.append(li)
c['lvalues'] = lvalues
c["label"] = self.kodi_labels_to_html(c["label"])
JsonData["data"]["items"].append(c)
ID = self.send_message(JsonData)
close = False
while True:
data = self.get_data(ID)
if type(data) == dict:
JsonData["action"] = "HideLoading"
JsonData["data"] = {}
self.send_message(JsonData)
for v in data:
if data[v] == "true": data[v] = True
if data[v] == "false": data[v] = False
if unicode(data[v]).isnumeric(): data[v] = int(data[v])
if callback and '.' in callback:
package, callback = callback.rsplit('.', 1)
else:
package = '%s.%s' % (ch_type, channelname)
cb_channel = None
try:
cb_channel = __import__(package, None, None, [package])
except ImportError:
logger.error('Imposible importar %s' % package)
if callback:
# Si existe una funcion callback la invocamos ...
return getattr(cb_channel, callback)(item, data)
else:
# si no, probamos si en el canal existe una funcion 'cb_validate_config' ...
try:
return getattr(cb_channel, 'cb_validate_config')(item, data)
except AttributeError:
# ... si tampoco existe 'cb_validate_config'...
for v in data:
config.set_setting(v, data[v], **kwargs)
elif data == "custom_button":
if '.' in callback:
package, callback = callback.rsplit('.', 1)
else:
package = '%s.%s' % (ch_type, channelname)
try:
cb_channel = __import__(package, None, None, [package])
except ImportError:
logger.error('Imposible importar %s' % package)
else:
return_value = getattr(cb_channel, custom_button['function'])(item, dict_values)
if custom_button["close"] == True:
return return_value
else:
JsonData["action"] = "custom_button"
JsonData["data"] = {}
JsonData["data"]["values"] = dict_values
JsonData["data"]["return_value"] = return_value
ID = self.send_message(JsonData)
elif data == False:
return None
def show_video_info(self, data, caption="", item=None, scraper=Tmdb):
from platformcode import html_info_window
return html_info_window.InfoWindow().start(self, data, caption, item, scraper)
def show_recaptcha(self, key, url):
from platformcode import html_recaptcha
return html_recaptcha.recaptcha().start(self, key, url)
def kodi_labels_to_html(self, text):
text = re.sub(r"(?:\[I\])(.*?)(?:\[/I\])", r"<i>\1</i>", text)
text = re.sub(r"(?:\[B\])(.*?)(?:\[/B\])", r"<b>\1</b>", text)
text = re.sub(r"(?:\[COLOR (?:0x)?([0-f]{2})([0-f]{2})([0-f]{2})([0-f]{2})\])(.*?)(?:\[/COLOR\])",
lambda m: "<span style='color: rgba(%s,%s,%s,%s)'>%s</span>" % (
int(m.group(2), 16), int(m.group(3), 16), int(m.group(4), 16), int(m.group(1), 16) / 255.0,
m.group(5)), text)
text = re.sub(r"(?:\[COLOR (?:0x)?([0-f]{2})([0-f]{2})([0-f]{2})\])(.*?)(?:\[/COLOR\])",
r"<span style='color: #\1\2\3'>\4</span>", text)
text = re.sub(r"(?:\[COLOR (?:0x)?([a-z|A-Z]+)\])(.*?)(?:\[/COLOR\])", r"<span style='color: \1'>\2</span>",
text)
return text

View File

@@ -1,188 +0,0 @@
# -*- coding: utf-8 -*-
# ------------------------------------------------------------
# Controlador para RSS
# ------------------------------------------------------------
import json
import random
import re
import threading
import time
from controller import Controller
from controller import Platformtools
from core.item import Item
class jsonserver(Controller):
pattern = re.compile("^/json")
data = {}
def __init__(self, handler=None):
super(jsonserver, self).__init__(handler)
self.platformtools = platformtools(self)
def extract_item(self, path):
if path == "/json" or path == "/json/":
item = Item(channel="channelselector", action="mainlist")
else:
item = Item().fromurl(path.replace("/json/", ""))
return item
def run(self, path):
item = self.extract_item(path)
from platformcode import launcher
launcher.run(item)
def set_data(self, data):
self.data = data
def get_data(self, id):
if "id" in self.data and self.data["id"] == id:
data = self.data["result"]
else:
data = None
return data
def send_data(self, data, headers={}, response=200):
headers.setdefault("content-type", "application/json")
headers.setdefault("connection", "close")
self.handler.send_response(response)
for header in headers:
self.handler.send_header(header, headers[header])
self.handler.end_headers()
self.handler.wfile.write(data)
class platformtools(Platformtools):
def __init__(self, controller):
self.controller = controller
self.handler = controller.handler
def render_items(self, itemlist, parentitem):
JSONResponse = {}
JSONResponse["title"] = parentitem.title
JSONResponse["date"] = time.strftime("%x")
JSONResponse["time"] = time.strftime("%X")
JSONResponse["count"] = len(itemlist)
JSONResponse["list"] = []
for item in itemlist:
JSONItem = {}
JSONItem["title"] = item.title
JSONItem["url"] = "http://" + self.controller.host + "/json/" + item.tourl()
if item.thumbnail: JSONItem["thumbnail"] = item.thumbnail
if item.plot: JSONItem["plot"] = item.plot
JSONResponse["list"].append(JSONItem)
self.controller.send_data(json.dumps(JSONResponse, indent=4, sort_keys=True))
def dialog_select(self, heading, list):
ID = "%032x" % (random.getrandbits(128))
response = '<?xml version="1.0" encoding="UTF-8" ?>\n'
response += '<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">\n'
response += '<channel>\n'
response += '<link>/rss</link>\n'
response += '<title>' + heading + '</title>\n'
for option in list:
response += '<item>\n'
response += '<title>' + option + '</title>\n'
response += '<image>%s</image>\n'
response += '<link>http://' + self.controller.host + '/data/' + threading.current_thread().name + '/' + ID + '/' + str(
list.index(option)) + '</link>\n'
response += '</item>\n\n'
response += '</channel>\n'
response += '</rss>\n'
self.controller.send_data(response)
self.handler.server.shutdown_request(self.handler.request)
while not self.controller.get_data(ID):
continue
return int(self.controller.get_data(ID))
def dialog_ok(self, heading, line1, line2="", line3=""):
text = line1
if line2: text += "\n" + line2
if line3: text += "\n" + line3
ID = "%032x" % (random.getrandbits(128))
response = '<?xml version="1.0" encoding="UTF-8" ?>\n'
response += '<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">\n'
response += '<channel>\n'
response += '<link>/rss</link>\n'
response += '<title>' + heading + '</title>\n'
response += '<item>\n'
response += '<title>' + text + '</title>\n'
response += '<image>%s</image>\n'
response += '<link></link>\n'
response += '</item>\n\n'
response += '<item>\n'
response += '<title>Si</title>\n'
response += '<image>%s</image>\n'
response += '<link>http://' + self.controller.host + '/data/' + threading.current_thread().name + '/' + ID + '/1</link>\n'
response += '</item>\n\n'
response += '<item>\n'
response += '</channel>\n'
response += '</rss>\n'
self.controller.send_data(response)
self.handler.server.shutdown_request(self.handler.request)
while not self.controller.get_data(ID):
continue
def dialog_yesno(self, heading, line1, line2="", line3=""):
text = line1
if line2: text += "\n" + line2
if line3: text += "\n" + line3
ID = "%032x" % (random.getrandbits(128))
response = '<?xml version="1.0" encoding="UTF-8" ?>\n'
response += '<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">\n'
response += '<channel>\n'
response += '<link>/rss</link>\n'
response += '<title>' + heading + '</title>\n'
response += '<item>\n'
response += '<title>' + text + '</title>\n'
response += '<image>%s</image>\n'
response += '<link></link>\n'
response += '</item>\n\n'
response += '<item>\n'
response += '<title>Si</title>\n'
response += '<image>%s</image>\n'
response += '<link>http://' + self.controller.host + '/data/' + threading.current_thread().name + '/' + ID + '/1</link>\n'
response += '</item>\n\n'
response += '<item>\n'
response += '<title>No</title>\n'
response += '<image>%s</image>\n'
response += '<link>http://' + self.controller.host + '/data/' + threading.current_thread().name + '/' + ID + '/0</link>\n'
response += '</item>\n\n'
response += '</channel>\n'
response += '</rss>\n'
self.controller.send_data(response)
self.handler.server.shutdown_request(self.handler.request)
while not self.controller.get_data(ID):
continue
return bool(int(self.controller.get_data(ID)))
def dialog_notification(self, heading, message, icon=0, time=5000, sound=True):
# No disponible por ahora, muestra un dialog_ok
self.dialog_ok(heading, message)
def play_video(self, item):
response = '<?xml version="1.0" encoding="UTF-8" ?>\n'
response += '<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">\n'
response += '<channel>\n'
response += '<link>/rss</link>\n'
response += '<title>' + item.title + '</title>\n'
response += '<item>\n'
response += '<title>' + item.title + '</title>\n'
response += '<image>%s</image>\n'
response += '<link>' + item.video_url + '</link>\n'
response += '</item>\n\n'
response += '</channel>\n'
response += '</rss>\n'
self.controller.send_data(response)

View File

@@ -1,58 +0,0 @@
# -*- coding: utf-8 -*-
# ------------------------------------------------------------
# Controlador para acceso indirecto a ficheros remotos
# ------------------------------------------------------------
import base64
import re
import urllib
import urllib2
from controller import Controller
class proxy(Controller):
pattern = re.compile("^/proxy/")
def run(self, path):
url = path.replace("/proxy/", "").split("/")[0]
url = base64.b64decode(urllib.unquote_plus(url))
request_headers = self.handler.headers.dict
if "host" in request_headers: request_headers.pop("host")
if "referer" in request_headers: request_headers.pop("referer")
if "cookie" in request_headers: request_headers.pop("cookie")
if "|" in url:
url_headers = dict(
[[header.split("=")[0].lower(), urllib.unquote_plus("=".join(header.split("=")[1:]))] for header in
url.split("|")[1].split("&")])
url = url.split("|")[0]
request_headers.update(url_headers)
req = urllib2.Request(url, headers=request_headers)
opener = urllib2.build_opener(urllib2.HTTPHandler(debuglevel=0))
try:
h = opener.open(req)
except urllib2.HTTPError, e:
h = e
except:
self.handler.send_response("503")
self.handler.wfile.close()
h.close()
self.handler.send_response(h.getcode())
for header in h.info():
self.handler.send_header(header, h.info()[header])
self.handler.end_headers()
blocksize = 1024
bloqueleido = h.read(blocksize)
while len(bloqueleido) > 0:
self.handler.wfile.write(bloqueleido)
bloqueleido = h.read(blocksize)
self.handler.wfile.close()
h.close()

View File

@@ -1,199 +0,0 @@
# -*- coding: utf-8 -*-
# ------------------------------------------------------------
# Controlador para RSS
# ------------------------------------------------------------
import random
import re
import threading
from controller import Controller
from controller import Platformtools
from core.item import Item
class rss(Controller):
pattern = re.compile("^/rss")
data = {}
def __init__(self, handler=None, ):
super(rss, self).__init__(handler)
self.platformtools = platformtools(self)
def extract_item(self, path):
if path == "/rss" or path == "/rss/":
item = Item(channel="channelselector", action="mainlist")
else:
item = Item().fromurl(path.replace("/rss/", ""))
return item
def run(self, path):
item = self.extract_item(path)
from platformcode import launcher
launcher.run(item)
def set_data(self, data):
self.data = data
def get_data(self, id):
if "id" in self.data and self.data["id"] == id:
data = self.data["result"]
else:
data = None
return data
def send_data(self, data, headers={}, response=200):
headers.setdefault("content-type", "application/rss+xml")
headers.setdefault("connection", "close")
self.handler.send_response(response)
for header in headers:
self.handler.send_header(header, headers[header])
self.handler.end_headers()
self.handler.wfile.write(data)
class platformtools(Platformtools):
def __init__(self, controller):
self.controller = controller
self.handler = controller.handler
def create_rss(self, itemlist):
resp = '<?xml version="1.0" encoding="UTF-8" ?>\n'
resp += '<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">\n'
resp += '<channel>\n'
resp += '<link>http://' + self.controller.host + '/rss</link>\n'
resp += '<title>Menú Principal</title>\n'
for item in itemlist:
resp += '<item>\n'
resp += '<title>' + item.title + '</title>\n'
resp += '<image>' + item.thumbnail + '</image>\n'
resp += '<link>' + self.controller.host + '/rss/' + item.tourl() + '</link>\n'
resp += '</item>\n\n'
resp += '</channel>\n'
resp += '</rss>\n'
return resp
def render_items(self, itemlist, parentitem):
new_itemlist = []
for item in itemlist:
# if item.action == "search": continue
# if item.channel=="search": continue
# if item.channel=="setting": continue
# if item.channel=="help": continue
new_itemlist.append(item)
response = self.create_rss(new_itemlist)
self.controller.send_data(response)
def dialog_select(self, heading, list):
ID = "%032x" % (random.getrandbits(128))
response = '<?xml version="1.0" encoding="UTF-8" ?>\n'
response += '<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">\n'
response += '<channel>\n'
response += '<link>/rss</link>\n'
response += '<title>' + heading + '</title>\n'
for option in list:
response += '<item>\n'
response += '<title>' + option + '</title>\n'
response += '<image>%s</image>\n'
response += '<link>http://' + self.controller.host + '/data/' + threading.current_thread().name + '/' + ID + '/' + str(
list.index(option)) + '</link>\n'
response += '</item>\n\n'
response += '</channel>\n'
response += '</rss>\n'
self.controller.send_data(response)
self.handler.server.shutdown_request(self.handler.request)
while not self.controller.get_data(ID):
continue
return int(self.controller.get_data(ID))
def dialog_ok(self, heading, line1, line2="", line3=""):
text = line1
if line2: text += "\n" + line2
if line3: text += "\n" + line3
ID = "%032x" % (random.getrandbits(128))
response = '<?xml version="1.0" encoding="UTF-8" ?>\n'
response += '<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">\n'
response += '<channel>\n'
response += '<link>/rss</link>\n'
response += '<title>' + heading + '</title>\n'
response += '<item>\n'
response += '<title>' + text + '</title>\n'
response += '<image>%s</image>\n'
response += '<link></link>\n'
response += '</item>\n\n'
response += '<item>\n'
response += '<title>Si</title>\n'
response += '<image>%s</image>\n'
response += '<link>http://' + self.controller.host + '/data/' + threading.current_thread().name + '/' + ID + '/1</link>\n'
response += '</item>\n\n'
response += '<item>\n'
response += '</channel>\n'
response += '</rss>\n'
self.controller.send_data(response)
self.handler.server.shutdown_request(self.handler.request)
while not self.controller.get_data(ID):
continue
def dialog_yesno(self, heading, line1, line2="", line3=""):
text = line1
if line2: text += "\n" + line2
if line3: text += "\n" + line3
ID = "%032x" % (random.getrandbits(128))
response = '<?xml version="1.0" encoding="UTF-8" ?>\n'
response += '<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">\n'
response += '<channel>\n'
response += '<link>/rss</link>\n'
response += '<title>' + heading + '</title>\n'
response += '<item>\n'
response += '<title>' + text + '</title>\n'
response += '<image>%s</image>\n'
response += '<link></link>\n'
response += '</item>\n\n'
response += '<item>\n'
response += '<title>Si</title>\n'
response += '<image>%s</image>\n'
response += '<link>http://' + self.controller.host + '/data/' + threading.current_thread().name + '/' + ID + '/1</link>\n'
response += '</item>\n\n'
response += '<item>\n'
response += '<title>No</title>\n'
response += '<image>%s</image>\n'
response += '<link>http://' + self.controller.host + '/data/' + threading.current_thread().name + '/' + ID + '/0</link>\n'
response += '</item>\n\n'
response += '</channel>\n'
response += '</rss>\n'
self.controller.send_data(response)
self.handler.server.shutdown_request(self.handler.request)
while not self.controller.get_data(ID):
continue
return bool(int(self.controller.get_data(ID)))
def dialog_notification(self, heading, message, icon=0, time=5000, sound=True):
# No disponible por ahora, muestra un dialog_ok
self.dialog_ok(heading, message)
def play_video(self, item):
response = '<?xml version="1.0" encoding="UTF-8" ?>\n'
response += '<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">\n'
response += '<channel>\n'
response += '<link>/rss</link>\n'
response += '<title>' + item.title + '</title>\n'
response += '<item>\n'
response += '<title>' + item.title + '</title>\n'
response += '<image>%s</image>\n'
response += '<link>' + item.video_url + '</link>\n'
response += '</item>\n\n'
response += '</channel>\n'
response += '</rss>\n'
self.controller.send_data(response)

View File

@@ -1,173 +0,0 @@
# -*- coding: utf-8 -*-
from core.tmdb import Tmdb
from platformcode import logger
class InfoWindow(object):
otmdb = None
item_title = ""
item_serie = ""
item_temporada = 0
item_episodio = 0
result = {}
@staticmethod
def get_language(lng):
# Cambiamos el formato del Idioma
languages = {
'aa': 'Afar', 'ab': 'Abkhazian', 'af': 'Afrikaans', 'ak': 'Akan', 'sq': 'Albanian', 'am': 'Amharic',
'ar': 'Arabic', 'an': 'Aragonese', 'as': 'Assamese', 'av': 'Avaric', 'ae': 'Avestan',
'ay': 'Aymara', 'az': 'Azerbaijani', 'ba': 'Bashkir', 'bm': 'Bambara', 'eu': 'Basque',
'be': 'Belarusian', 'bn': 'Bengali', 'bh': 'Bihari languages', 'bi': 'Bislama',
'bo': 'Tibetan', 'bs': 'Bosnian', 'br': 'Breton', 'bg': 'Bulgarian', 'my': 'Burmese',
'ca': 'Catalan; Valencian', 'cs': 'Czech', 'ch': 'Chamorro', 'ce': 'Chechen', 'zh': 'Chinese',
'cu': 'Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church Slavonic',
'cv': 'Chuvash', 'kw': 'Cornish', 'co': 'Corsican', 'cr': 'Cree', 'cy': 'Welsh',
'da': 'Danish', 'de': 'German', 'dv': 'Divehi; Dhivehi; Maldivian', 'nl': 'Dutch; Flemish',
'dz': 'Dzongkha', 'en': 'English', 'eo': 'Esperanto',
'et': 'Estonian', 'ee': 'Ewe', 'fo': 'Faroese', 'fa': 'Persian', 'fj': 'Fijian',
'fi': 'Finnish', 'fr': 'French', 'fy': 'Western Frisian', 'ff': 'Fulah',
'Ga': 'Georgian', 'gd': 'Gaelic; Scottish Gaelic', 'ga': 'Irish', 'gl': 'Galician',
'gv': 'Manx', 'el': 'Greek, Modern (1453-)', 'gn': 'Guarani', 'gu': 'Gujarati',
'ht': 'Haitian; Haitian Creole', 'ha': 'Hausa', 'he': 'Hebrew', 'hz': 'Herero', 'hi': 'Hindi',
'ho': 'Hiri Motu', 'hr': 'Croatian', 'hu': 'Hungarian', 'hy': 'Armenian', 'ig': 'Igbo',
'is': 'Icelandic', 'io': 'Ido', 'ii': 'Sichuan Yi; Nuosu', 'iu': 'Inuktitut',
'ie': 'Interlingue; Occidental', 'ia': 'Interlingua (International Auxiliary Language Association)',
'id': 'Indonesian', 'ik': 'Inupiaq', 'it': 'Italian', 'jv': 'Javanese',
'ja': 'Japanese', 'kl': 'Kalaallisut; Greenlandic', 'kn': 'Kannada', 'ks': 'Kashmiri',
'ka': 'Georgian', 'kr': 'Kanuri', 'kk': 'Kazakh', 'km': 'Central Khmer', 'ki': 'Kikuyu; Gikuyu',
'rw': 'Kinyarwanda', 'ky': 'Kirghiz; Kyrgyz', 'kv': 'Komi', 'kg': 'Kongo', 'ko': 'Korean',
'kj': 'Kuanyama; Kwanyama', 'ku': 'Kurdish', 'lo': 'Lao', 'la': 'Latin', 'lv': 'Latvian',
'li': 'Limburgan; Limburger; Limburgish', 'ln': 'Lingala', 'lt': 'Lithuanian',
'lb': 'Luxembourgish; Letzeburgesch', 'lu': 'Luba-Katanga', 'lg': 'Ganda', 'mk': 'Macedonian',
'mh': 'Marshallese', 'ml': 'Malayalam', 'mi': 'Maori', 'mr': 'Marathi', 'ms': 'Malay', 'Mi': 'Micmac',
'mg': 'Malagasy', 'mt': 'Maltese', 'mn': 'Mongolian', 'na': 'Nauru',
'nv': 'Navajo; Navaho', 'nr': 'Ndebele, South; South Ndebele', 'nd': 'Ndebele, North; North Ndebele',
'ng': 'Ndonga', 'ne': 'Nepali', 'nn': 'Norwegian Nynorsk; Nynorsk, Norwegian',
'nb': 'Bokmål, Norwegian; Norwegian Bokmål', 'no': 'Norwegian', 'oc': 'Occitan (post 1500)',
'oj': 'Ojibwa', 'or': 'Oriya', 'om': 'Oromo', 'os': 'Ossetian; Ossetic', 'pa': 'Panjabi; Punjabi',
'pi': 'Pali', 'pl': 'Polish', 'pt': 'Portuguese', 'ps': 'Pushto; Pashto', 'qu': 'Quechua',
'ro': 'Romanian; Moldavian; Moldovan', 'rn': 'Rundi', 'ru': 'Russian', 'sg': 'Sango', 'rm': 'Romansh',
'sa': 'Sanskrit', 'si': 'Sinhala; Sinhalese', 'sk': 'Slovak', 'sl': 'Slovenian', 'se': 'Northern Sami',
'sm': 'Samoan', 'sn': 'Shona', 'sd': 'Sindhi', 'so': 'Somali', 'st': 'Sotho, Southern', 'es': 'Spanish',
'sc': 'Sardinian', 'sr': 'Serbian', 'ss': 'Swati', 'su': 'Sundanese', 'sw': 'Swahili', 'sv': 'Swedish',
'ty': 'Tahitian', 'ta': 'Tamil', 'tt': 'Tatar', 'te': 'Telugu', 'tg': 'Tajik', 'tl': 'Tagalog',
'th': 'Thai', 'ti': 'Tigrinya', 'to': 'Tonga (Tonga Islands)', 'tn': 'Tswana', 'ts': 'Tsonga',
'tk': 'Turkmen', 'tr': 'Turkish', 'tw': 'Twi', 'ug': 'Uighur; Uyghur', 'uk': 'Ukrainian',
'ur': 'Urdu', 'uz': 'Uzbek', 've': 'Venda', 'vi': 'Vietnamese', 'vo': 'Volapük',
'wa': 'Walloon', 'wo': 'Wolof', 'xh': 'Xhosa', 'yi': 'Yiddish', 'yo': 'Yoruba', 'za': 'Zhuang; Chuang',
'zu': 'Zulu'}
return languages.get(lng, lng)
def get_scraper_data(self, data_in):
self.otmdb = None
# logger.debug(str(data_in))
if self.listData:
# Datos comunes a todos los listados
infoLabels = self.scraper().get_infoLabels(origen=data_in)
if "original_language" in infoLabels:
infoLabels["language"] = self.get_language(infoLabels["original_language"])
if "vote_average" in data_in and "vote_count" in data_in:
infoLabels["puntuacion"] = str(data_in["vote_average"]) + "/10 (" + str(data_in["vote_count"]) + ")"
self.result = infoLabels
def start(self, handler, data, caption="Información del vídeo", item=None, scraper=Tmdb):
# Capturamos los parametros
self.caption = caption
self.item = item
self.indexList = -1
self.listData = []
self.handler = handler
self.scraper = scraper
logger.debug(data)
if type(data) == list:
self.listData = data
self.indexList = 0
data = self.listData[self.indexList]
self.get_scraper_data(data)
ID = self.update_window()
return self.onClick(ID)
def update_window(self):
JsonData = {}
JsonData["action"] = "OpenInfo"
JsonData["data"] = {}
JsonData["data"]["buttons"] = len(self.listData) > 0
JsonData["data"]["previous"] = self.indexList > 0
JsonData["data"]["next"] = self.indexList + 1 < len(self.listData)
JsonData["data"]["count"] = "(%s/%s)" % (self.indexList + 1, len(self.listData))
JsonData["data"]["title"] = self.caption
JsonData["data"]["fanart"] = self.result.get("fanart", "")
JsonData["data"]["thumbnail"] = self.result.get("thumbnail", "")
JsonData["data"]["lines"] = []
if self.result.get("mediatype", "movie") == "movie":
JsonData["data"]["lines"].append({"title": "Título:", "text": self.result.get("title", "N/A")})
JsonData["data"]["lines"].append(
{"title": "Título Original:", "text": self.result.get("originaltitle", "N/A")})
JsonData["data"]["lines"].append({"title": "Idioma Original:", "text": self.result.get("language", "N/A")})
JsonData["data"]["lines"].append({"title": "Puntuación:", "text": self.result.get("puntuacion", "N/A")})
JsonData["data"]["lines"].append({"title": "Lanzamiento:", "text": self.result.get("release_date", "N/A")})
JsonData["data"]["lines"].append({"title": "Generos:", "text": self.result.get("genre", "N/A")})
JsonData["data"]["lines"].append({"title": "", "text": ""})
else:
JsonData["data"]["lines"].append({"title": "Serie:", "text": self.result.get("title", "N/A")})
JsonData["data"]["lines"].append({"title": "Idioma Original:", "text": self.result.get("language", "N/A")})
JsonData["data"]["lines"].append({"title": "Puntuación:", "text": self.result.get("puntuacion", "N/A")})
JsonData["data"]["lines"].append({"title": "Generos:", "text": self.result.get("genre", "N/A")})
if self.result.get("season"):
JsonData["data"]["lines"].append(
{"title": "Titulo temporada:", "text": self.result.get("temporada_nombre", "N/A")})
JsonData["data"]["lines"].append({"title": "Temporada:",
"text": self.result.get("season", "N/A") + " de " + self.result.get(
"seasons", "N/A")})
JsonData["data"]["lines"].append({"title": "", "text": ""})
if self.result.get("episode"):
JsonData["data"]["lines"].append({"title": "Titulo:", "text": self.result.get("episode_title", "N/A")})
JsonData["data"]["lines"].append({"title": "Episodio:",
"text": self.result.get("episode", "N/A") + " de " + self.result.get(
"episodes", "N/A")})
JsonData["data"]["lines"].append({"title": "Emisión:", "text": self.result.get("date", "N/A")})
if self.result.get("plot"):
JsonData["data"]["lines"].append({"title": "Sinopsis:", "text": self.result["plot"]})
else:
JsonData["data"]["lines"].append({"title": "", "text": ""})
ID = self.handler.send_message(JsonData)
return ID
def onClick(self, ID):
while True:
response = self.handler.get_data(ID)
if response == "ok":
return self.listData[self.indexList]
elif response == "close":
return None
elif response == "next" and self.indexList < len(self.listData) - 1:
self.indexList += 1
self.get_scraper_data(self.listData[self.indexList])
ID = self.update_window()
elif response == "previous" and self.indexList > 0:
self.indexList -= 1
self.get_scraper_data(self.listData[self.indexList])
ID = self.update_window()

View File

@@ -1,79 +0,0 @@
# -*- coding: utf-8 -*-
from core import httptools
from core import scrapertools
from platformcode import platformtools, logger
class recaptcha(object):
def start(self, handler, key, referer):
self.handler = handler
self.referer = referer
self.key = key
self.headers = {'Referer': self.referer}
api_js = httptools.downloadpage("http://www.google.com/recaptcha/api.js?hl=es").data
version = scrapertools.find_single_match(api_js, 'po.src = \'(.*?)\';').split("/")[5]
self.url = "https://www.google.com/recaptcha/api/fallback?k=%s&hl=es&v=%s&t=2&ff=true" % (self.key, version)
ID = self.update_window()
return self.onClick(ID)
def update_window(self):
data = httptools.downloadpage(self.url, headers=self.headers).data
self.message = scrapertools.find_single_match(data,
'<div class="rc-imageselect-desc-no-canonical">(.*?)(?:</label>|</div>)')
self.token = scrapertools.find_single_match(data, 'name="c" value="([^"]+)"')
self.image = "https://www.google.com/recaptcha/api2/payload?k=%s&c=%s" % (self.key, self.token)
self.result = {}
JsonData = {}
JsonData["action"] = "recaptcha"
JsonData["data"] = {}
JsonData["data"]["title"] = "reCaptcha"
JsonData["data"]["image"] = self.image
JsonData["data"]["message"] = self.message
JsonData["data"]["selected"] = [int(k) for k in range(9) if self.result.get(k, False) == True]
JsonData["data"]["unselected"] = [int(k) for k in range(9) if self.result.get(k, False) == False]
ID = self.handler.send_message(JsonData)
return ID
def onClick(self, ID):
while True:
response = self.handler.get_data(ID)
if type(response) == int:
self.result[response] = not self.result.get(response, False)
JsonData = {}
JsonData["action"] = "recaptcha_select"
JsonData["data"] = {}
JsonData["data"]["selected"] = [int(k) for k in range(9) if self.result.get(k, False) == True]
JsonData["data"]["unselected"] = [int(k) for k in range(9) if self.result.get(k, False) == False]
self.handler.send_message(JsonData)
elif response == "refresh":
ID = self.update_window()
continue
elif response == True:
post = "c=%s" % self.token
for r in sorted([k for k, v in self.result.items() if v == True]):
post += "&response=%s" % r
logger.info(post)
logger.info(self.result)
data = httptools.downloadpage(self.url, post, headers=self.headers).data
result = scrapertools.find_single_match(data, '<div class="fbc-verification-token">.*?>([^<]+)<')
if result:
platformtools.dialog_notification("Captcha Correcto", "La verificación ha concluido")
JsonData = {}
JsonData["action"] = "ShowLoading"
self.handler.send_message(JsonData)
return result
else:
ID = self.update_window()
else:
return

View File

@@ -1,523 +0,0 @@
# -*- coding: utf-8 -*-
# ------------------------------------------------------------
# Mediaserver Launcher
# ------------------------------------------------------------
import os
import sys
from core import channeltools
from core import servertools
from core import videolibrarytools
from core.item import Item
from platformcode import config, platformtools, logger
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()
# Test if all the required directories are created
config.verify_directories_created()
import videolibrary_service
videolibrary_service.start()
def run(item):
itemlist = []
# Muestra el item en el log:
PrintItems(item)
# Control Parental, comprueba si es adulto o no
if item.action == "mainlist":
# Parental control
if channeltools.is_adult(item.channel) and config.get_setting("adult_pin") != "":
tecleado = platformtools.dialog_input("", "Contraseña para canales de adultos", True)
if tecleado is None or tecleado != config.get_setting("adult_pin"):
platformtools.render_items(None, item)
return
# Importa el canal para el item, todo item debe tener un canal, sino sale de la función
if item.channel: channelmodule = ImportarCanal(item)
# If item has no action, stops here
if item.action == "":
logger.info("Item sin accion")
itemlist = None
# Action Play, para mostrar el menú con las opciones de reproduccion.
elif item.action == "play":
logger.info("play")
# Si el canal tiene una acción "play" tiene prioridad
if hasattr(channelmodule, 'play'):
logger.info("executing channel 'play' method")
itemlist = channelmodule.play(item)
b_favourite = item.isFavourite
if len(itemlist) > 0 and isinstance(itemlist[0], Item):
item = itemlist[0]
if b_favourite:
item.isFavourite = True
play_menu(item)
elif len(itemlist) > 0 and isinstance(itemlist[0], list):
item.video_urls = itemlist
play_menu(item)
else:
platformtools.dialog_ok("plugin", "No hay nada para reproducir")
else:
logger.info("no channel 'play' method, executing core method")
play_menu(item)
itemlist = None
# Action Search, para mostrar el teclado y lanzar la busqueda con el texto indicado.
elif item.action == "search":
logger.info("search")
tecleado = platformtools.dialog_input()
if tecleado:
itemlist = channelmodule.search(item, tecleado)
else:
itemlist = []
elif item.channel == "channelselector":
import channelselector
if item.action == "mainlist":
itemlist = channelselector.getmainlist("banner_")
# if config.get_setting("check_for_plugin_updates"):
# logger.info("channelselector.mainlist Verificar actualizaciones activado")
#
# from core import updater
# try:
# version = updater.checkforupdates()
#
# if version:
# platformtools.dialog_ok("Versión " + version + " disponible",
# "Ya puedes descargar la nueva versión del plugin\ndesde el listado principal")
# itemlist.insert(0, Item(title="Actualizar Alfa a la versión " + version, version=version,
# channel="updater", action="update",
# thumbnail=os.path.join(config.get_runtime_path(), "resources", "images",
# "banner", "thumb_update.png")))
# except:
# platformtools.dialog_ok("No se puede conectar", "No ha sido posible comprobar",
# "si hay actualizaciones")
# logger.info("Fallo al verificar la actualización")
#
# else:
# logger.info("Verificar actualizaciones desactivado")
if item.action == "getchanneltypes":
itemlist = channelselector.getchanneltypes("banner_")
if item.action == "filterchannels":
itemlist = channelselector.filterchannels(item.channel_type, "banner_")
# Todas las demas las intenta ejecturaren el siguiente orden:
# 1. En el canal
# 2. En el launcher
# 3. Si no existe en el canal ni en el launcher guarda un error en el log
else:
# Si existe la funcion en el canal la ejecuta
if hasattr(channelmodule, item.action):
logger.info("Ejectuando accion: " + item.channel + "." + item.action + "(item)")
exec "itemlist = channelmodule." + item.action + "(item)"
# Si existe la funcion en el launcher la ejecuta
elif hasattr(sys.modules[__name__], item.action):
logger.info("Ejectuando accion: " + item.action + "(item)")
exec "itemlist =" + item.action + "(item)"
# Si no existe devuelve un error
else:
logger.info(
"No se ha encontrado la accion [" + item.action + "] en el canal [" + item.channel + "] ni en el launcher")
# Llegados a este punto ya tenemos que tener el itemlist con los resultados correspondientes
# Pueden darse 3 escenarios distintos:
# 1. la función ha generado resultados y estan en el itemlist
# 2. la función no ha generado resultados y por tanto el itemlist contiene 0 items, itemlist = []
# 3. la función realiza alguna accion con la cual no se generan nuevos items, en ese caso el resultado deve ser: itemlist = None para que no modifique el listado
# A partir de aquí ya se ha ejecutado la funcion en el lugar adecuado, si queremos realizar alguna acción sobre los resultados, este es el lugar.
# Filtrado de Servers
if item.action == "findvideos":
itemlist = servertools.filter_servers(itemlist)
# Si la accion no ha devuelto ningún resultado, añade un item con el texto "No hay elementos para mostrar"
if type(itemlist) == list:
if len(itemlist) == 0:
from channelselector import get_thumb
itemlist = [Item(title="No hay elementos para mostrar", thumbnail=get_thumb("error.png"))]
# Imprime en el log el resultado
PrintItems(itemlist)
# Muestra los resultados en pantalla
platformtools.render_items(itemlist, item)
def ImportarCanal(item):
channel = item.channel
channelmodule = ""
if os.path.exists(os.path.join(config.get_runtime_path(), "channels", channel + ".py")):
exec "from channels import " + channel + " as channelmodule"
elif os.path.exists(os.path.join(config.get_runtime_path(), "core", channel + ".py")):
exec "from core import " + channel + " as channelmodule"
elif os.path.exists(os.path.join(config.get_runtime_path(), channel + ".py")):
exec "import " + channel + " as channelmodule"
return channelmodule
def PrintItems(itemlist):
if type(itemlist) == list:
if len(itemlist) > 0:
logger.info("Items devueltos")
logger.info("-----------------------------------------------------------------------")
for item in itemlist:
logger.info(item.tostring())
logger.info("-----------------------------------------------------------------------")
else:
item = itemlist
logger.info("-----------------------------------------------------------------------")
logger.info(item.tostring())
logger.info("-----------------------------------------------------------------------")
def findvideos(item):
logger.info()
itemlist = servertools.find_video_items(item)
return itemlist
def add_pelicula_to_library(item):
videolibrarytools.add_movie(item)
def add_serie_to_library(item):
channel = ImportarCanal(item)
videolibrarytools.add_tvshow(item, channel)
def download_all_episodes(item, first_episode="", preferred_server="vidspot", filter_language=""):
logger.info("show=" + item.show)
channel = ImportarCanal(item)
show_title = item.show
# Obtiene el listado desde el que se llamó
action = item.extra
# Esta marca es porque el item tiene algo más aparte en el atributo "extra"
if "###" in item.extra:
action = item.extra.split("###")[0]
item.extra = item.extra.split("###")[1]
exec "episode_itemlist = channel." + action + "(item)"
# Ordena los episodios para que funcione el filtro de first_episode
episode_itemlist = sorted(episode_itemlist, key=lambda Item: Item.title)
from core import downloadtools
from core import scrapertools
best_server = preferred_server
worst_server = "moevideos"
# Para cada episodio
if first_episode == "":
empezar = True
else:
empezar = False
for episode_item in episode_itemlist:
try:
logger.info("episode=" + episode_item.title)
episode_title = scrapertools.get_match(episode_item.title, "(\d+x\d+)")
logger.info("episode=" + episode_title)
except:
import traceback
logger.error(traceback.format_exc())
continue
if first_episode != "" and episode_title == first_episode:
empezar = True
if episodio_ya_descargado(show_title, episode_title):
continue
if not empezar:
continue
# Extrae los mirrors
try:
mirrors_itemlist = channel.findvideos(episode_item)
except:
mirrors_itemlist = servertools.find_video_items(episode_item)
print mirrors_itemlist
descargado = False
new_mirror_itemlist_1 = []
new_mirror_itemlist_2 = []
new_mirror_itemlist_3 = []
new_mirror_itemlist_4 = []
new_mirror_itemlist_5 = []
new_mirror_itemlist_6 = []
for mirror_item in mirrors_itemlist:
# Si está en español va al principio, si no va al final
if "(Español)" in mirror_item.title:
if best_server in mirror_item.title.lower():
new_mirror_itemlist_1.append(mirror_item)
else:
new_mirror_itemlist_2.append(mirror_item)
elif "(Latino)" in mirror_item.title:
if best_server in mirror_item.title.lower():
new_mirror_itemlist_3.append(mirror_item)
else:
new_mirror_itemlist_4.append(mirror_item)
elif "(VOS)" in mirror_item.title:
if best_server in mirror_item.title.lower():
new_mirror_itemlist_3.append(mirror_item)
else:
new_mirror_itemlist_4.append(mirror_item)
else:
if best_server in mirror_item.title.lower():
new_mirror_itemlist_5.append(mirror_item)
else:
new_mirror_itemlist_6.append(mirror_item)
mirrors_itemlist = new_mirror_itemlist_1 + new_mirror_itemlist_2 + new_mirror_itemlist_3 + new_mirror_itemlist_4 + new_mirror_itemlist_5 + new_mirror_itemlist_6
for mirror_item in mirrors_itemlist:
logger.info("mirror=" + mirror_item.title)
if "(Español)" in mirror_item.title:
idioma = "(Español)"
codigo_idioma = "es"
elif "(Latino)" in mirror_item.title:
idioma = "(Latino)"
codigo_idioma = "lat"
elif "(VOS)" in mirror_item.title:
idioma = "(VOS)"
codigo_idioma = "vos"
elif "(VO)" in mirror_item.title:
idioma = "(VO)"
codigo_idioma = "vo"
else:
idioma = "(Desconocido)"
codigo_idioma = "desconocido"
logger.info("filter_language=#" + filter_language + "#, codigo_idioma=#" + codigo_idioma + "#")
if filter_language == "" or (filter_language != "" and filter_language == codigo_idioma):
logger.info("downloading mirror")
else:
logger.info("language " + codigo_idioma + " filtered, skipping")
continue
if hasattr(channel, 'play'):
video_items = channel.play(mirror_item)
else:
video_items = [mirror_item]
if len(video_items) > 0:
video_item = video_items[0]
# Comprueba que esté disponible
video_urls, puedes, motivo = servertools.resolve_video_urls_for_playing(video_item.server,
video_item.url,
video_password="",
muestra_dialogo=False)
# Lo añade a la lista de descargas
if puedes:
logger.info("downloading mirror started...")
# El vídeo de más calidad es el último
mediaurl = video_urls[len(video_urls) - 1][1]
devuelve = downloadtools.downloadbest(video_urls,
show_title + " " + episode_title + " " + idioma + " [" + video_item.server + "]",
continuar=False)
if devuelve == 0:
logger.info("download ok")
descargado = True
break
elif devuelve == -1:
try:
platformtools.dialog_ok("plugin", "Descarga abortada")
except:
pass
return
else:
logger.info("download error, try another mirror")
continue
else:
logger.info("downloading mirror not available... trying next")
if not descargado:
logger.info("EPISODIO NO DESCARGADO " + episode_title)
def add_to_favorites(item):
# Proviene del menu contextual:
if "item_action" in item:
item.action = item.item_action
del item.item_action
item.context = []
from channels import favorites
from core import downloadtools
if not item.fulltitle: item.fulltitle = item.title
title = platformtools.dialog_input(
default=downloadtools.limpia_nombre_excepto_1(item.fulltitle) + " [" + item.channel + "]")
if title is not None:
item.title = title
favorites.addFavourite(item)
platformtools.dialog_ok("Alfa", config.get_localized_string(
30102) + "\n" + item.title + "\n" + config.get_localized_string(30108))
return
def remove_from_favorites(item):
from channels import favorites
# En "extra" está el nombre del fichero en favoritos
favorites.delFavourite(item.extra)
platformtools.dialog_ok("Alfa",
config.get_localized_string(30102) + "\n" + item.title + "\n" + config.get_localized_string(
30105))
platformtools.itemlist_refresh()
return
def download(item):
from channels import downloads
if item.contentType == "list" or item.contentType == "tvshow":
item.contentType = "video"
item.play_menu = True
downloads.save_download(item)
return
def add_to_library(item):
if "item_action" in item:
item.action = item.item_action
del item.item_action
if not item.fulltitle == "":
item.title = item.fulltitle
videolibrarytools.savelibrary(item)
platformtools.dialog_ok("Alfa",
config.get_localized_string(30101) + "\n" + item.title + "\n" + config.get_localized_string(
30135))
return
def delete_file(item):
os.remove(item.url)
platformtools.itemlist_refresh()
return
def search_trailer(item):
config.set_setting("subtitulo", False)
item.channel = "trailertools"
item.action = "buscartrailer"
item.contextual = True
run(item)
return
# Crea la lista de opciones para el menu de reproduccion
def check_video_options(item, video_urls):
itemlist = []
# Opciones Reproducir
playable = (len(video_urls) > 0)
for video_url in video_urls:
itemlist.append(
item.clone(option=config.get_localized_string(30151) + " " + video_url[0], video_url=video_url[1],
action="play_video"))
if item.server == "local":
itemlist.append(item.clone(option=config.get_localized_string(30164), action="delete_file"))
if not item.server == "local" and playable:
itemlist.append(item.clone(option=config.get_localized_string(30153), action="download", video_urls=video_urls))
if item.channel == "favorites":
itemlist.append(item.clone(option=config.get_localized_string(30154), action="remove_from_favorites"))
if not item.channel == "favorites" and playable:
itemlist.append(
item.clone(option=config.get_localized_string(30155), action="add_to_favorites", item_action=item.action))
if not item.strmfile and playable and item.contentType == "movie":
itemlist.append(
item.clone(option=config.get_localized_string(30161), action="add_to_library", item_action=item.action))
if not item.channel in ["Trailer", "ecarteleratrailers"] and playable:
itemlist.append(item.clone(option=config.get_localized_string(30162), action="search_trailer"))
return itemlist
# play_menu, abre el menu con las opciones para reproducir
def play_menu(item):
if item.server == "": item.server = "directo"
if item.video_urls:
video_urls, puedes, motivo = item.video_urls, True, ""
else:
video_urls, puedes, motivo = servertools.resolve_video_urls_for_playing(item.server, item.url, item.password,
True)
if not "strmfile" in item: item.strmfile = False
# TODO: unificar show y Serie ya que se usan indistintamente.
if not "Serie" in item: item.Serie = item.show
if item.server == "": item.server = "directo"
opciones = check_video_options(item, video_urls)
if not puedes:
if item.server != "directo":
motivo = motivo.replace("<br/>", "\n")
platformtools.dialog_ok("No puedes ver ese vídeo porque...", motivo + "\n" + item.url)
else:
platformtools.dialog_ok("No puedes ver ese vídeo porque...",
"El servidor donde está alojado no está\nsoportado en Alfa todavía\n" + item.url)
if len(opciones) == 0:
return
default_action = config.get_setting("default_action")
logger.info("default_action=%s" % (default_action))
# Si la accion por defecto es "Preguntar", pregunta
if default_action == 0:
seleccion = platformtools.dialog_select(config.get_localized_string(30163),
[opcion.option for opcion in opciones])
elif default_action == 1:
seleccion = 0
elif default_action == 2:
seleccion = len(video_urls) - 1
elif default_action == 3:
seleccion = seleccion
else:
seleccion = 0
if seleccion > -1:
logger.info("seleccion=%d" % seleccion)
logger.info("seleccion=%s" % opciones[seleccion].option)
selecteditem = opciones[seleccion]
del selecteditem.option
run(opciones[seleccion])
return
# play_video, Llama a la función especifica de la plataforma para reproducir
def play_video(item):
platformtools.play_video(item)

View File

@@ -1,48 +0,0 @@
# -*- coding: utf-8 -*-
# ------------------------------------------------------------
# logger for mediaserver
# ------------------------------------------------------------
import logging
import logging.config
import os
import config
class ExtendedLogger(logging.Logger):
def findCaller(self):
f = logging.currentframe().f_back.f_back
rv = "(unknown file)", 0, "(unknown function)"
while hasattr(f, "f_code"):
co = f.f_code
filename = os.path.normcase(co.co_filename)
if "logger" in filename: # This line is modified.
f = f.f_back
continue
filename = filename + " " + co.co_name
rv = (filename, f.f_lineno, co.co_name)
break
return rv
logging.setLoggerClass(ExtendedLogger)
logging.basicConfig(level=logging.DEBUG,
format='%(levelname)-5s %(asctime)s [%(filename)-40s] %(message)s',
datefmt="%d/%m/%y-%H:%M:%S",
filename=os.path.join(config.get_data_path(), "alfa.log"),
filemode='w')
logger_object = logging.getLogger("mediaserver")
def info(texto=""):
if config.get_setting("debug"):
logger_object.info(unicode(str(texto), "utf-8", "ignore").replace("\n", "\n" + " " * 67))
def debug(texto=""):
if config.get_setting("debug"):
logger_object.debug(unicode(str(texto), "utf-8", "ignore").replace("\n", "\n" + " " * 67))
def error(texto=""):
logger_object.error(unicode(str(texto), "utf-8", "ignore").replace("\n", "\n" + " " * 67))

View File

@@ -1,107 +0,0 @@
# -*- coding: utf-8 -*-
# ------------------------------------------------------------
# platformtools
# ------------------------------------------------------------
# Herramientas responsables de adaptar los diferentes
# cuadros de dialogo a una plataforma en concreto,
# en este caso Mediserver.
# version 1.3
# ------------------------------------------------------------
import threading
controllers = {}
def dialog_ok(*args, **kwargs):
id = threading.current_thread().name
return controllers[id].dialog_ok(*args, **kwargs)
def dialog_notification(*args, **kwargs):
id = threading.current_thread().name
return controllers[id].dialog_notification(*args, **kwargs)
def dialog_yesno(*args, **kwargs):
id = threading.current_thread().name
return controllers[id].dialog_yesno(*args, **kwargs)
def dialog_select(*args, **kwargs):
id = threading.current_thread().name
return controllers[id].dialog_select(*args, **kwargs)
def dialog_progress(*args, **kwargs):
id = threading.current_thread().name
return controllers[id].dialog_progress(*args, **kwargs)
def dialog_progress_bg(*args, **kwargs):
id = threading.current_thread().name
return controllers[id].dialog_progress_bg(*args, **kwargs)
def dialog_input(*args, **kwargs):
id = threading.current_thread().name
return controllers[id].dialog_input(*args, **kwargs)
def dialog_numeric(*args, **kwargs):
id = threading.current_thread().name
return controllers[id].dialog_numeric(*args, **kwargs)
def itemlist_refresh(*args, **kwargs):
id = threading.current_thread().name
return controllers[id].itemlist_refresh(*args, **kwargs)
def itemlist_update(*args, **kwargs):
id = threading.current_thread().name
return controllers[id].itemlist_update(*args, **kwargs)
def render_items(*args, **kwargs):
id = threading.current_thread().name
return controllers[id].render_items(*args, **kwargs)
def is_playing(*args, **kwargs):
id = threading.current_thread().name
return controllers[id].is_playing(*args, **kwargs)
def play_video(*args, **kwargs):
id = threading.current_thread().name
return controllers[id].play_video(*args, **kwargs)
def stop_video(*args, **kwargs):
# id = threading.current_thread().name
# return controllers[id].play_video(*args, **kwargs)
return False
def open_settings(*args, **kwargs):
id = threading.current_thread().name
return controllers[id].open_settings(*args, **kwargs)
def show_channel_settings(*args, **kwargs):
id = threading.current_thread().name
return controllers[id].show_channel_settings(*args, **kwargs)
def show_video_info(*args, **kwargs):
id = threading.current_thread().name
return controllers[id].show_video_info(*args, **kwargs)
def show_recaptcha(*args, **kwargs):
id = threading.current_thread().name
return controllers[id].show_recaptcha(*args, **kwargs)
def torrent_client_installed(show_tuple=False):
return []

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

View File

@@ -1,7 +0,0 @@
<li onmousemove="focus_element(this.getElementsByTagName('input')[0])">
<div class="control">
<span class="name" style='color:%item_color'>%item_label</span>
<input class="checkbox" onchange="evaluate_controls(this)" onfocus="this.parentNode.className='control control_focused'" onblur="this.parentNode.className='control'" type="checkbox" id="%item_id" %item_value>
<label class="checkbox"><i></i></label>
</div>
</li>

View File

@@ -1 +0,0 @@
<a class="control_button" href="javascript:void(0)"onmouseover="focus_element(this)" onclick="change_category('%item_category')">%item_label</a>

View File

@@ -1 +0,0 @@
<ul class="settings_list" style="display:none" id="%item_id">%item_value</ul>

View File

@@ -1,5 +0,0 @@
<li>
<div>
<span class="name" style='color:%item_color'>%item_label</span>
</div>
</li>

View File

@@ -1,7 +0,0 @@
<li onmousemove="focus_element(this.getElementsByTagName('select')[0])">
<div class="control">
<span class="name" style='color:%item_color'>%item_label</span>
<select class="list" onchange="evaluate_controls(this)" name="%item_type" onfocus="this.parentNode.className='control control_focused'" onblur="this.parentNode.className='control'" id="%item_id">%item_values</select>
<label class="list"><i></i></label>
</div>
</li>

View File

@@ -1,4 +0,0 @@
<li>
<div class="separator">
</div>
</li>

View File

@@ -1,7 +0,0 @@
<li onmousemove="focus_element(this.getElementsByTagName('input')[0])">
<div class="control">
<span class="name" style='color:%item_color'>%item_label</span>
<input class="text" onchange="evaluate_controls(this)" onkeyup="evaluate_controls(this)" onfocus="this.parentNode.className='control control_focused'" onblur="this.parentNode.className='control'" onkeypress="%keypress" type="%item_type" id="%item_id" value="%item_value">
<label class="text"><i></i></label>
</div>
</li>

View File

@@ -1,10 +0,0 @@
<li class="item_banner">
<a class="item %item_class" onblur="unload_info(this)" oncontextmenu="dialog.menu('Menu','%menu_items');return false" onfocus="focused_item=this;load_info(this, 'banner')" onmouseover="focus_element(this)" href="javascript:void(0)" onclick="send_request('%item_url')">
<img class="thumbnail" onerror="this.style.visibility='hidden'">
<h3 class="label">%item_title</h3>
<label class="thumbnail">%item_thumbnail</label>
<label class="plot">%item_plot</label>
<label class="fanart">%item_fanart</label>
</a>
%item_menu
</li>

View File

@@ -1,10 +0,0 @@
<li class="item_channel">
<a class="item %item_class" onblur="unload_info(this)" oncontextmenu="dialog.menu('Menu','%menu_items');return false" onfocus="focused_item=this;load_info(this, 'channel')" onmouseover="focus_element(this)" href="javascript:void(0)" onclick="send_request('%item_url')">
<h3 class="label">%item_title</h3>
<img class="thumbnail" onerror="this.style.visibility='hidden'" onload="this.parentNode.children[0].style.visibility='hidden'">
<label class="thumbnail">%item_thumbnail</label>
<label class="plot">%item_plot</label>
<label class="fanart">%item_fanart</label>
</a>
%item_menu
</li>

View File

@@ -1,10 +0,0 @@
<li class="item_list">
<a class="item %item_class" onblur="unload_info(this)" oncontextmenu="dialog.menu('Menu','%menu_items');return false" onfocus="focused_item=this;load_info(this, 'list')" onmouseover="focus_element(this)" href="javascript:void(0)" onclick="send_request('%item_url')">
<h3 class="label">%item_title</h3>
<img class="thumbnail" onerror="image_error(this)">
<label class="thumbnail">%item_thumbnail</label>
<label class="plot">%item_plot</label>
<label class="fanart">%item_fanart</label>
</a>
%item_menu
</li>

View File

@@ -1 +0,0 @@
<a class="item_menu" href="javascript:void(0)" onmouseover="focus_element(this)" onclick="focused_item=this;dialog.menu('Menu','%menu_items')"></a>

View File

@@ -1,10 +0,0 @@
<li class="item_movie">
<a class="item %item_class" onblur="unload_info(this)" oncontextmenu="dialog.menu('Menu','%menu_items');return false" onfocus="focused_item=this;load_info(this, 'movie')" onmouseover="focus_element(this)" href="javascript:void(0)" onclick="send_request('%item_url')">
<h3 class="label">%item_title</h3>
<img class="thumbnail" onerror="image_error(this)">
<label class="thumbnail">%item_thumbnail</label>
<label class="plot">%item_plot</label>
<label class="fanart">%item_fanart</label>
</a>
%item_menu
</li>

View File

@@ -1,6 +0,0 @@
<object class="media_player" data="http://releases.flowplayer.org/swf/flowplayer-3.2.18.swf" type="application/x-shockwave-flash">
<param name="movie" value="http://releases.flowplayer.org/swf/flowplayer-3.2.18.swf" />
<param name="allowfullscreen" value="true" />
<param name="allowscriptaccess" value="always" />
<param name="flashvars" value='config={"clip":{"url":"%video_url"},"playlist":[{"url":"%video_url"}]}' />
</object>

View File

@@ -1 +0,0 @@
<video class="media_player" id="media_player" type="application/x-mplayer2" autoplay="true" controls="true" src="%video_url"/>

View File

@@ -1,7 +0,0 @@
<object class="media_player" classid="clsid:9BE31822-FDAD-461B-AD51-BE1D1C159921" codebase="http://downloads.videolan.org/pub/videolan/vlc/latest/win32/axvlc.cab" id="vlc" events="False">
<param name="Src" value="%video_url"></param>
<param name="ShowDisplay" value="True"></param>
<param name="AutoLoop" value="no"></param>
<param name="AutoPlay" value="yes"></param>
<embed type="application/x-google-vlc-plugin" name="vlcfirefox" autoplay="yes" loop="no" width="100%" height="100%" target="%video_url"></embed>
</object>

View File

@@ -1,5 +0,0 @@
<li class="item">
<a href="javascript:void(0)" onmouseover="focus_element(this)" onclick="dialog.closeall(); %item_action">
<h3>%item_title</h3>
</a>
</li>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

View File

@@ -1,503 +0,0 @@
loading.close = function () {
var el = document.getElementById("window_loading");
if (el.style.display == "block") {
el.style.display = "none";
document.getElementById("window_overlay").style.display = "none";
if (focused_item) {
focused_item.focus();
}
else if (document.getElementById("itemlist").children.length) {
document.getElementById("itemlist").children[0].children[0].focus();
};
};
};
loading.show = function (message) {
if (!message) {
message = "Cargando...";
};
var el = document.getElementById("window_loading");
el.getElementById("loading_message").innerHTML = message;
document.getElementById("window_overlay").style.display = "block";
el.style.display = "block";
el.getElementById("loading_message").focus();
center_window(el);
};
dialog.closeall = function () {
document.getElementById('window_overlay').style.display = 'none';
document.getElementById("window_loading").style.display = "none";
document.getElementById("window_select").style.display = "none";
document.getElementById("window_settings").style.display = "none";
document.getElementById("window_settings").style.display = "none";
document.getElementById("window_player").style.display = "none";
document.getElementById("window_player").getElementById("media_content").innerHTML = '';
document.getElementById("window_ok").style.display = "none";
document.getElementById("window_yesno").style.display = "none";
document.getElementById("window_input").style.display = "none";
document.getElementById("window_recaptcha").style.display = "none";
document.getElementById("window_progress").style.display = "none";
document.getElementById("window_info").style.display = "none";
if (focused_item) {
focused_item.focus();
}
else if (document.getElementById("itemlist").children.length) {
document.getElementById("itemlist").children[0].children[0].focus();
};
};
dialog.menu = function (title, list) {
dialog.closeall();
if (list) {
var el = document.getElementById("window_select")
el.getElementById("window_heading").innerHTML = title;
el.getElementById("control_list").innerHTML = atob(list);
el.style.display = "block";
document.getElementById("window_overlay").style.display = "block";
el.getElementById("control_list").children[0].children[0].focus();
center_window(el);
};
};
dialog.select = function (id, data) {
dialog.closeall();
var el = document.getElementById("window_select");
el.getElementById("window_heading").innerHTML = data.title;
el.RequestID = id;
var lista = [];
for (var x in data.list) {
lista.push(replace_list(html.dialog.select.item, {
"item_title": data.list[x],
"item_action": "send_data({'id':'" + id + "', 'result':" + x + "})"
}));
};
el.getElementById("control_list").innerHTML = lista.join("");
el.style.display = "block";
document.getElementById("window_overlay").style.display = "block";
el.getElementById("control_list").children[0].children[0].focus();
center_window(el);
};
dialog.player = function (title, player) {
dialog.closeall();
var el = document.getElementById("window_player");
el.getElementById("window_heading").innerHTML = title;
el.getElementById("media_content").innerHTML = player;
el.style.display = "block";
document.getElementById("window_overlay").style.display = "block";
el.children[0].focus();
center_window(el);
};
dialog.ok = function (id, data) {
dialog.closeall();
var el = document.getElementById("window_ok");
document.getElementById("window_overlay").style.display = "block";
el.style.display = "block";
el.RequestID = id;
el.getElementById("window_message").innerHTML = data.text.replace(new RegExp("\n", 'g'), "<br/>");
el.getElementById("window_heading").innerHTML = data.title;
el.getElementById("window_footer").children[0].focus();
center_window(el);
};
dialog.yesno = function (id, data) {
dialog.closeall();
var el = document.getElementById("window_yesno");
document.getElementById("window_overlay").style.display = "block";
el.style.display = "block";
el.RequestID = id;
el.getElementById("window_message").innerHTML = data.text.replace(new RegExp("\n", 'g'), "<br/>");
el.getElementById("window_heading").innerHTML = data.title;
el.getElementById("window_footer").children[0].focus();
center_window(el);
};
dialog.notification = function (id, data) {
var el = document.getElementById("window_notification");
el.style.display = "block";
if (!data.icon){data.icon = 0}
el.getElementById("window_heading").innerHTML = data.title;
el.getElementById("window_message").innerHTML = data.text;
el.getElementById("window_icon").className = "window_icon" + data.icon;
auto_scroll(el.getElementById("window_message"))
setTimeout(function(){ el.style.display = "none"; }, data.time);
};
dialog.keyboard = function (id, data) {
dialog.closeall();
var el = document.getElementById("window_input");
if (data.title === "") {
data.title = "Teclado";
};
if (data.password == true) {
el.getElementById("window_value").type = "password";
}
else {
el.getElementById("window_value").type = "text";
};
el.RequestID = id;
document.getElementById("window_overlay").style.display = "block";
el.style.display = "block";
el.getElementById("window_value").value = data.text;
el.getElementById("window_heading").innerHTML = data.title;
el.getElementById("window_value").focus();
center_window(el);
};
dialog.recaptcha = function (id, data) {
dialog.closeall();
var el = document.getElementById("window_recaptcha");
if (data.title === "") {
data.title = "Introduce el texto de la imagen";
};
el.RequestID = id;
document.getElementById("window_overlay").style.display = "block";
el.style.display = "block";
el.getElementById("window_image").style.backgroundImage = "url(" + data.image + ")";
el.getElementById("window_heading").innerHTML = data.title;
el.getElementById("window_message").innerHTML = data.message;
for (var x in [0,1,2,3,4,5,6,7,8]) {
el.getElementById("window_image").children[x].className = "";
}
el.getElementById("window_footer").children[0].focus();
center_window(el);
};
dialog.recaptcha_select = function (id, data) {
var el = document.getElementById("window_recaptcha");
console.log(data.selected)
console.log(data.unselected)
for (var x in data.selected) {
el.getElementById("window_image").children[data.selected[x]].className = "selected";
}
for (var x in data.unselected) {
el.getElementById("window_image").children[data.unselected[x]].className = "";
}
};
dialog.progress_bg = function (id, data) {
var el = document.getElementById("window_background_progress");
el.style.display = "block";
el.RequestID = id;
el.getElementById("window_message").innerHTML = data.text.replace(new RegExp("\n", 'g'), "<br/>");
el.getElementById("window_heading").innerHTML = data.title;
el.getElementById("progressbar").style.width = data.percent + "%";
};
dialog.progress_bg_close = function () {
document.getElementById("window_background_progress").style.display = "none";
};
dialog.progress = function (id, data) {
var el = document.getElementById("window_progress");
if (id != el.RequestID) {
dialog.closeall();
};
el.RequestID = id;
document.getElementById("window_overlay").style.display = "block";
el.style.display = "block";
el.getElementById("window_message").innerHTML = data.text.replace(new RegExp("\n", 'g'), "<br/>");
el.getElementById("window_heading").innerHTML = data.title;
el.getElementById("canceled").checked = "";
el.getElementById("progress").style.width = data.percent + "%";
el.getElementById("window_footer").children[0].focus;
center_window(el);
};
dialog.progress_update = function (id, data) {
var el = document.getElementById("window_progress");
el.getElementById("window_message").innerHTML = data.text.replace(new RegExp("\n", 'g'), "<br/>");
if (el.getElementById("canceled").checked != "") {
el.getElementById("window_heading").innerHTML = data.title + " " + data.percent + "% - Cancelando...";
}
else {
el.getElementById("window_heading").innerHTML = data.title + " " + data.percent + "%";
};
el.getElementById("progress").style.width = data.percent + "%";
};
dialog.progress_close = function () {
dialog.closeall();
};
dialog.custom_button = function(id, data) {
var el = document.getElementById("window_settings");
el.RequestID = id;
if (data.return_value.label){
el.getElementById("custom_button").innerHTML = data.return_value.label
};
var controls = document.getElementById("window_settings").getControls();
for (var x in controls) {
switch (controls[x].type) {
case "text":
controls[x].value = data.values[controls[x].id];
break;
case "password":
controls[x].value = data.values[controls[x].id];
break;
case "checkbox":
value = data.values[controls[x].id];
if (value == true) {
value = "checked";
}
else {
value = "";
};
controls[x].checked = value;
break;
case "select-one":
if (controls[x].name == "enum") {
controls[x].selectedIndex = data.values[controls[x].id];
}
else if (controls[x].name == "labelenum") {
controls[x].value = data.values[controls[x].id];
};
break;
};
controls[x].onchange()
};
};
dialog.config = function (id, data, Secciones, Lista) {
dialog.closeall();
var el = document.getElementById("window_settings");
el.RequestID = id;
el.getElementById("controls_container").innerHTML = Lista;
el.getElementById("window_heading").innerHTML = data.title;
if (data.custom_button != null) {
if (!data.custom_button.visible) {
el.getElementById("custom_button").style.display = "none"
}
else {
el.getElementById("custom_button").style.display = "inline";
el.getElementById("custom_button").innerHTML = data.custom_button.label;
el.getElementById("custom_button").onclick = function () {
custom_button(data.custom_button);
};
};
}
else {
el.getElementById("custom_button").style.display = "inline";
el.getElementById("custom_button").innerHTML = "Por defecto";
el.getElementById("custom_button").onclick = function () {
custom_button(null);
};
};
if (Secciones != "") {
el.getElementById("category_container").innerHTML = Secciones;
el.getElementById("category_container").style.display = "block";
el.getElementById("category_General").style.display = "block";
}
else {
el.getElementById("category_container").style.display = "none";
el.getElementById("category_undefined").style.display = "block";
};
el.getElementById("window_footer").style.display = "block";
el.getElementById("window_footer_local").style.display = "none";
document.getElementById("window_overlay").style.display = "block";
el.style.display = "block";
if (Secciones != "") {
el.getElementById("category_container").children[0].focus();
el.getElementById("category_General").scrollTop = 0;
}
else {
el.getElementById("window_footer").children[0].focus();
el.getElementById("category_undefined").scrollTop = 0;
};
center_window(el);
};
dialog.settings = function () {
dialog.closeall();
var el = document.getElementById("window_settings");
el.getElementById("window_heading").innerHTML = "Ajustes";
var controls = [];
controls.push(replace_list(html.config.label, {
"item_color": "#FFFFFF",
"item_label": "Navegación:"
}));
if (settings.builtin_history) {
var value = "checked=checked";
}
else {
var value = "";
};
controls.push(replace_list(html.config.bool, {
"item_color": "#FFFFFF",
"item_label": "Usar navegación del explorador",
"item_id": "builtin_history",
"item_value": value
}));
controls.push(replace_list(html.config.label, {
"item_color": "#FFFFFF",
"item_label": "Visualización:"
}));
if (settings.show_fanart) {
var value = "checked=checked";
}
else {
var value = "";
};
controls.push(replace_list(html.config.bool, {
"item_color": "#FFFFFF",
"item_label": "Mostrar Fanarts",
"item_id": "show_fanart",
"item_value": value
}));
controls.push(replace_list(html.config.label, {
"item_color": "#FFFFFF",
"item_label": "Reproducción:"
}));
var options = ["<option>Preguntar</option>", "<option>Indirecto</option>", "<option>Directo</option>"];
options[settings.play_mode] = options[settings.play_mode].replace("<option>", "<option selected=selected>");
controls.push(replace_list(html.config.list, {
"item_type": "enum",
"item_color": "#FFFFFF",
"item_label": "Método de reproduccion:",
"item_id": "play_mode",
"item_values": options.join("")
}));
options = ["<option>Preguntar</option>"];
for (var player in players) {
options.push("<option>" + players[player] + "</option>");
};
options[settings.player_mode] = options[settings.player_mode].replace("<option>", "<option selected=selected>");
controls.push(replace_list(html.config.list, {
"item_type": "enum",
"item_color": "#FFFFFF",
"item_label": "Reproductor:",
"item_id": "player_mode",
"item_values": options.join("")
}));
el.getElementById("controls_container").innerHTML = replace_list(html.config.container, {
"item_id": "category_all",
"item_value": controls.join("").replace(/evaluate_controls\(this\)/g, '')
});
el.getElementById("category_container").style.display = "none";
el.getElementById("category_all").style.display = "block";
el.getElementById("window_footer").style.display = "none";
el.getElementById("window_footer_local").style.display = "block";
document.getElementById("window_overlay").style.display = "block";
el.style.display = "block";
el.children[0].focus();
center_window(el);
};
dialog.info = function (id, data) {
dialog.closeall();
var el = document.getElementById("window_info");
el.RequestID = id;
el.getElementById("window_heading").innerHTML = data.title;
el.getElementById("info_fanart").src = data.fanart;
el.getElementById("info_poster").src = data.thumbnail;
if (data.buttons) {
el.getElementById("window_footer").style.display = "block";
el.getElementById("page_info").innerHTML = data.count;
if (data.previous) {
el.getElementById("previous").onclick = function () {
info_window('previous');
};
el.getElementById("previous").className = "control_button";
el.getElementById("previous").disabled = false;
}
else {
el.getElementById("previous").onclick = "";
el.getElementById("previous").className = "control_button disabled";
el.getElementById("previous").disabled = true;
};
if (data.next) {
el.getElementById("next").onclick = function () {
info_window('next');
};
el.getElementById("next").className = "control_button";
el.getElementById("next").disabled = false;
}
else {
el.getElementById("next").onclick = "";
el.getElementById("next").className = "control_button disabled";
el.getElementById("next").disabled = true;
};
}
else {
el.getElementById("window_footer").style.display = "none";
};
el.getElementById("line1_head").innerHTML = data["lines"][0]["title"];
el.getElementById("line2_head").innerHTML = data["lines"][1]["title"];
el.getElementById("line3_head").innerHTML = data["lines"][2]["title"];
el.getElementById("line4_head").innerHTML = data["lines"][3]["title"];
el.getElementById("line5_head").innerHTML = data["lines"][4]["title"];
el.getElementById("line6_head").innerHTML = data["lines"][5]["title"];
el.getElementById("line7_head").innerHTML = data["lines"][6]["title"];
el.getElementById("line8_head").innerHTML = data["lines"][7]["title"];
el.getElementById("line1").innerHTML = data["lines"][0]["text"];
el.getElementById("line2").innerHTML = data["lines"][1]["text"];
el.getElementById("line3").innerHTML = data["lines"][2]["text"];
el.getElementById("line4").innerHTML = data["lines"][3]["text"];
el.getElementById("line5").innerHTML = data["lines"][4]["text"];
el.getElementById("line6").innerHTML = data["lines"][5]["text"];
el.getElementById("line7").innerHTML = data["lines"][6]["text"];
el.getElementById("line8").innerHTML = data["lines"][7]["text"];
if (el.style.display == "block") {
update = true;
}
else {
update = false;
};
document.getElementById("window_overlay").style.display = "block";
el.style.display = "block";
auto_scroll(el.getElementById("line1"));
auto_scroll(el.getElementById("line2"));
auto_scroll(el.getElementById("line3"));
auto_scroll(el.getElementById("line4"));
auto_scroll(el.getElementById("line5"));
auto_scroll(el.getElementById("line6"));
auto_scroll(el.getElementById("line7"));
auto_scroll(el.getElementById("line8"));
if (data["buttons"]) {
if (!update) {
el.getElementById("window_footer").children[3].focus();
};
}
else {
el.children[0].focus();
};
center_window(el);
};

View File

@@ -1,107 +0,0 @@
HTMLElement.prototype.getElementById = function(id) {
if (this.querySelector("#" + id)) {
return this.querySelector("#" + id);
};
for (var x = 0; x < this.children.length; x++) {
if (this.children[x].id == id) {
return this.children[x];
};
};
for (var x = 0; x < this.children.length; x++) {
result = this.children[x].getElementById(id);
if (result != null) {
return result;
};
};
return null;
};
HTMLElement.prototype.getControls = function() {
return [].concat(Array.prototype.slice.call(this.getElementsByTagName("input")), Array.prototype.slice.call(this.getElementsByTagName("select")));
};
window.onload = function() {
var url = (window.location.href.split("#")[1] ? window.location.href.split("#")[1] : "");
dispose();
loading.show("Cargando pagina...");
ajax_running.remove = function(val) {
if (this.indexOf(val) > -1) {
this.splice(this.indexOf(val), 1);
};
if (!this.length && !websocket) {
send_request(url);
};
};
load_settings();
dowload_files();
};
window.onpopstate = function(e) {
if (e.state) {
nav_history.go(e.state - nav_history.current);
};
};
window.onresize = function() {
dispose();
};
window.getCookie = function(name) {
var match = document.cookie.match(new RegExp(name + '=([^;]+)'));
if (match) return match[1];
};
function load_settings() {
settings["play_mode"] = (window.getCookie("play_mode") ? parseInt(window.getCookie("play_mode")) : 0);
settings["player_mode"] = (window.getCookie("player_mode") ? parseInt(window.getCookie("player_mode")) : 0);
settings["show_fanart"] = (window.getCookie("show_fanart") == "false" ? false : true);
settings["builtin_history"] = (window.getCookie("builtin_history") == "true" ? true : false);
};
function save_settings() {
var controls = document.getElementById("window_settings").getControls();
for (var x in controls) {
switch (controls[x].type) {
case "text":
case "password":
save_setting(controls[x].id, controls[x].value);
break;
case "checkbox":
save_setting(controls[x].id, controls[x].checked);
break;
case "select-one":
save_setting(controls[x].id, controls[x].selectedIndex);
break;
};
};
load_settings();
};
function save_setting(id, value) {
document.cookie = id + "=" + value + '; expires=Fri, 31 Dec 9999 23:59:59 GMT';
};
function dowload_files() {
ajax_to_dict("/media/html/player_vlc.html", html, "vlc_player");
ajax_to_dict("/media/html/player_html.html", html, "html_player");
ajax_to_dict("/media/html/player_flash.html", html, "flash_player");
ajax_to_dict("/media/html/itemlist_banner.html", html, "itemlist.banner");
ajax_to_dict("/media/html/itemlist_channel.html", html, "itemlist.channel");
ajax_to_dict("/media/html/itemlist_movie.html", html, "itemlist.movie");
ajax_to_dict("/media/html/itemlist_list.html", html, "itemlist.list");
ajax_to_dict("/media/html/itemlist_menu.html", html, "itemlist.menu");
ajax_to_dict("/media/html/select_item.html", html, "dialog.select.item");
ajax_to_dict("/media/html/config_label.html", html, "config.label");
ajax_to_dict("/media/html/config_sep.html", html, "config.sep");
ajax_to_dict("/media/html/config_text.html", html, "config.text");
ajax_to_dict("/media/html/config_bool.html", html, "config.bool");
ajax_to_dict("/media/html/config_list.html", html, "config.list");
ajax_to_dict("/media/html/config_category.html", html, "config.category");
ajax_to_dict("/media/html/config_container.html", html, "config.container");
};

View File

@@ -1,739 +0,0 @@
window.onkeydown = function (e) {
if (e.keyCode == 27) {
dialog.closeall()
}
if (e.target.tagName == "BODY") {
body_events(e);
};
if (document.getElementById("window_loading").contains(e.target)) {
window_loading_events(e);
};
if (document.getElementById("window_settings").contains(e.target)) {
window_settings_events(e);
};
if (document.getElementById("window_select").contains(e.target)) {
window_select_events(e);
};
if (document.getElementById("window_ok").contains(e.target)) {
window_generic_events(e);
};
if (document.getElementById("window_yesno").contains(e.target)) {
window_generic_events(e);
};
if (document.getElementById("window_recaptcha").contains(e.target)) {
window_recaptcha_events(e);
};
if (document.getElementById("window_progress").contains(e.target)) {
window_generic_events(e);
};
if (document.getElementById("window_info").contains(e.target)) {
window_generic_events(e);
}
if (document.getElementById("window_input").contains(e.target)) {
window_input_events(e);
};
if (document.getElementById("itemlist").contains(e.target)) {
itemlist_events(e);
};
};
function itemlist_events(e) {
var el = document.getElementById('itemlist');
switch (e.keyCode) {
case 96:
case 97:
case 98:
case 99:
case 100:
case 101:
case 102:
case 103:
case 104:
case 105:
numeric_search(e.keyCode);
break;
case 93: //Menu
e.preventDefault();
if (e.target.parentNode.children.length == 2) {
e.target.parentNode.children[1].onclick.apply(e.target.parentNode.children[1]);
focused_item = e.target.parentNode.children[1];
};
break;
case 8: //BACK
e.preventDefault();
if (nav_history.current > 0) {
send_request("go_back");
};
break;
case 37: //LEFT
e.preventDefault();
var index = Array.prototype.indexOf.call(e.target.parentNode.children, e.target);
if (index > 0){
e.target.parentNode.children[index - 1].focus();
};
break;
case 38: //UP
e.preventDefault();
var index = Array.prototype.indexOf.call(el.children, e.target.parentNode);
if (index == 0) {
index = el.children.length;
};
el.children[index - 1].children[0].focus();
break;
case 39: //RIGHT
e.preventDefault();
var index = Array.prototype.indexOf.call(e.target.parentNode.children, e.target);
if (index < e.target.parentNode.children.length - 1){
e.target.parentNode.children[index + 1].focus();
};
break;
case 40: //DOWN
e.preventDefault();
var index = Array.prototype.indexOf.call(el.children, e.target.parentNode);
if (index + 1 == el.children.length) {
index = -1;
};
el.children[index + 1].children[0].focus();
break;
};
};
function window_loading_events(e) {
switch (e.keyCode) {
case 8: //BACK
loading.close();
connection_retry = false;
e.preventDefault();
break;
};
};
function body_events(e) {
switch (e.keyCode) {
case 8: //BACK
e.preventDefault();
break;
case 37: //LEFT
case 38: //UP
case 39: //RIGHT
case 40: //DOWN
e.preventDefault();
document.getElementById("itemlist").children[0].children[0].focus();
break;
};
};
function window_generic_events(e) {
var el = (document.getElementById("window_ok").contains(e.target) ? document.getElementById("window_ok") : el);
var el = (document.getElementById("window_yesno").contains(e.target) ? document.getElementById("window_yesno") : el);
var el = (document.getElementById("window_progress").contains(e.target) ? document.getElementById("window_progress") : el);
var el = (document.getElementById("window_info").contains(e.target) ? document.getElementById("window_info") : el);
switch (e.keyCode) {
case 8: //BACK
e.preventDefault();
dialog.closeall();
break;
case 38: //UP
e.preventDefault();
if (el.getElementById("window_footer").contains(e.target)) {
el.children[0].focus();
};
break;
case 37: //LEFT
e.preventDefault();
if (el.getElementById("window_footer").contains(e.target)) {
var index = Array.prototype.indexOf.call(el.getElementById("window_footer").children, e.target) -1;
while (index >= 0 && el.getElementById("window_footer").children[index].disabled){
index --;
};
if (index >=0){
el.getElementById("window_footer").children[index].focus();
};
};
break;
case 39: //RIGHT
e.preventDefault();
if (el.getElementById("window_footer").contains(e.target)) {
var index = Array.prototype.indexOf.call(el.getElementById("window_footer").children, e.target) +1;
while (index < el.getElementById("window_footer").children.length && el.getElementById("window_footer").children[index].disabled){
index ++;
};
if (index < el.getElementById("window_footer").children.length){
el.getElementById("window_footer").children[index].focus();
};
};
break;
case 40: //DOWN
e.preventDefault();
if (e.target.parentNode == el) {
el.getElementById("window_footer").children[0].focus();
};
break;
};
};
function window_recaptcha_events(e) {
var el = document.getElementById("window_recaptcha");
switch (e.keyCode) {
case 8: //BACK
e.preventDefault();
dialog.closeall();
break;
case 38: //UP
e.preventDefault();
if (el.getElementById("window_footer").contains(e.target)) {
el.getElementById("window_image").children[el.getElementById("window_image").children.length -1].focus();
}
else {
var index = Array.prototype.indexOf.call(el.getElementById("window_image").children, e.target) -3;
if (index >-1) {
el.getElementById("window_image").children[index].focus();
}
else {
el.children[0].focus();
};
};
break;
case 37: //LEFT
e.preventDefault();
if (el.getElementById("window_footer").contains(e.target)) {
var index = Array.prototype.indexOf.call(el.getElementById("window_footer").children, e.target) -1;
while (index >= 0 && el.getElementById("window_footer").children[index].disabled){
index --;
};
if (index >=0){
el.getElementById("window_footer").children[index].focus();
};
} else if (e.target.parentNode == el.getElementById("window_image")) {
var index = Array.prototype.indexOf.call(el.getElementById("window_image").children, e.target) -1;
if ([-1,2,5].indexOf(index) == -1) {
el.getElementById("window_image").children[index].focus();
};
};
break;
case 39: //RIGHT
e.preventDefault();
if (el.getElementById("window_footer").contains(e.target)) {
var index = Array.prototype.indexOf.call(el.getElementById("window_footer").children, e.target) +1;
while (index < el.getElementById("window_footer").children.length && el.getElementById("window_footer").children[index].disabled){
index ++;
};
if (index < el.getElementById("window_footer").children.length){
el.getElementById("window_footer").children[index].focus();
};
} else if (e.target.parentNode == el.getElementById("window_image")) {
var index = Array.prototype.indexOf.call(el.getElementById("window_image").children, e.target) +1;
if ([3,6,9].indexOf(index) == -1) {
el.getElementById("window_image").children[index].focus();
};
};
break;
case 40: //DOWN
e.preventDefault();
if (e.target.parentNode == el) {
el.getElementById("window_image").children[0].focus();
}
else if (e.target.parentNode == el.getElementById("window_image")) {
var index = Array.prototype.indexOf.call(el.getElementById("window_image").children, e.target) +3;
if (index < el.getElementById("window_image").children.length) {
el.getElementById("window_image").children[index].focus();
}
else {
el.getElementById("window_footer").children[0].focus();
};
};
break;
};
};
function window_select_events(e) {
var el = document.getElementById('window_select');
switch (e.keyCode) {
case 8: //BACK
e.preventDefault();
dialog.closeall();
break;
case 38: //UP
e.preventDefault();
var index = Array.prototype.indexOf.call(el.getElementById("control_list").children, e.target.parentNode);
if (index != 0) {
el.getElementById("control_list").children[index - 1].children[0].focus();
}
else {
el.children[0].focus();
};
break;
case 40: //DOWN
e.preventDefault();
if (e.target.parentNode == el) {
el.getElementById("control_list").children[0].children[0].focus();
}
else {
var index = Array.prototype.indexOf.call(el.getElementById("control_list").children, e.target.parentNode);
el.getElementById("control_list").children[index + 1].children[0].focus();
};
break;
};
};
function window_settings_events(e) {
el = document.getElementById('window_settings');
switch (e.keyCode) {
case 8: //BACK
if ((e.target.tagName != "INPUT" || (e.target.type != "text" && e.target.type != "password")) && e.target.tagName != "SELECT") {
e.preventDefault();
dialog.closeall();
};
break;
case 38: //UP
e.preventDefault();
if (e.target.parentNode == el) {
return;
};
if (el.getElementById("category_container").contains(e.target)) {
el.children[0].focus();
return;
}
else if (el.getElementById("window_footer").contains(e.target) || el.getElementById("window_footer_local").contains(e.target)) {
var index = null;
var group = null;
}
else if (el.getElementById("controls_container").contains(e.target)) {
var group = Array.prototype.indexOf.call(el.getElementById("controls_container").children, e.target.parentNode.parentNode.parentNode);
var index = Array.prototype.indexOf.call(el.getElementById("controls_container").children[group].children, e.target.parentNode.parentNode) - 1;
};
if (group == null) {
for (group = 0; group < el.getElementById("category_container").children.length; group++) {
if (el.getElementById("category_container").children[group].style.display != "none") {
break;
};
};
};
if (index == null) {
index = el.getElementById("controls_container").children[group].children.length - 1;
};
while (index >= 0 &&
(el.getElementById("controls_container").children[group].children[index].children[0].className != "control" ||
el.getElementById("controls_container").children[group].children[index].children[0].children[1].disabled ||
el.getElementById("controls_container").children[group].children[index].style.display == "none")) {
index--;
};
if (index >= 0) {
el.getElementById("controls_container").children[group].children[index].children[0].children[1].focus();
}
else {
if (el.getElementById("category_container").style.display == "none") {
el.children[0].focus();
}
else {
el.getElementById("category_container").children[0].focus();
};
};
break;
case 37: //LEFT
if ((e.target.tagName != "INPUT" || (e.target.type != "text" && e.target.type != "password")) && e.target.tagName != "SELECT") {
e.preventDefault();
if (el.getElementById("category_container").contains(e.target)) {
var index = Array.prototype.indexOf.call(el.getElementById("category_container").children, e.target);
el.getElementById("category_container").children[index - 1].focus();
}
else if (el.getElementById("window_footer").contains(e.target)) {
var index = Array.prototype.indexOf.call(el.getElementById("window_footer").children, e.target);
el.getElementById("window_footer").children[index - 1].focus();
}
else if (el.getElementById("window_footer_local").contains(e.target)) {
var index = Array.prototype.indexOf.call(el.getElementById("window_footer_local").children, e.target);
el.getElementById("window_footer_local").children[index - 1].focus();
};
};
break;
case 39: //RIGHT
if ((e.target.tagName != "INPUT" || (e.target.type != "text" && e.target.type != "password")) && e.target.tagName != "SELECT") {
e.preventDefault();
if (el.getElementById("category_container").contains(e.target)) {
var index = Array.prototype.indexOf.call(el.getElementById("category_container").children, e.target);
el.getElementById("category_container").children[index + 1].focus();
}
else if (el.getElementById("window_footer").contains(e.target)) {
var index = Array.prototype.indexOf.call(el.getElementById("window_footer").children, e.target);
el.getElementById("window_footer").children[index + 1].focus();
}
else if (el.getElementById("window_footer_local").contains(e.target)) {
var index = Array.prototype.indexOf.call(el.getElementById("window_footer_local").children, e.target);
el.getElementById("window_footer_local").children[index + 1].focus();
};
};
break;
case 40: //DOWN
e.preventDefault();
if (e.target.parentNode == el) {
if (el.getElementById("category_container").style.display == "none") {
var index = 0;
var group = null;
}
else {
el.getElementById("category_container").children[0].focus();
};
}
else if (el.getElementById("category_container").contains(e.target)) {
var index = 0;
var group = null;
}
else if (el.getElementById("controls_container").contains(e.target)) {
var group = Array.prototype.indexOf.call(el.getElementById("controls_container").children, e.target.parentNode.parentNode.parentNode);
var index = Array.prototype.indexOf.call(el.getElementById("controls_container").children[group].children, e.target.parentNode.parentNode) + 1;
};
if (group == null) {
for (group = 0; group < el.getElementById("category_container").children.length; group++) {
if (el.getElementById("category_container").children[group].style.display != "none") {
break;
};
};
};
while (index < el.getElementById("controls_container").children[group].children.length &&
(el.getElementById("controls_container").children[group].children[index].children[0].className != "control" ||
el.getElementById("controls_container").children[group].children[index].children[0].children[1].disabled ||
el.getElementById("controls_container").children[group].children[index].style.display == "none")) {
index++;
};
if (index < el.getElementById("controls_container").children[group].children.length) {
el.getElementById("controls_container").children[group].children[index].children[0].children[1].focus();
}
else {
el.getElementById("window_footer").children[0].focus();
el.getElementById("window_footer_local").children[0].focus();
};
break;
};
};
function window_input_events(e) {
el = document.getElementById("window_input");
switch (e.keyCode) {
case 8: //BACK
if (e.target.tagName != "INPUT") {
e.preventDefault();
dialog.closeall();
};
break;
case 38: //UP
e.preventDefault();
if (el.getElementById("window_footer").contains(e.target)) {
el.getElementById("control_input").children[0].focus();
}
if (el.getElementById("control_input").contains(e.target)) {
el.children[0].focus();
};
break;
case 37: //LEFT
if (el.getElementById("window_footer").contains(e.target)) {
var index = Array.prototype.indexOf.call(el.getElementById("window_footer").children, e.target);
el.getElementById("window_footer").children[index - 1].focus();
e.preventDefault();
};
break;
case 39: //RIGHT
if (el.getElementById("window_footer").contains(e.target)) {
var index = Array.prototype.indexOf.call(el.getElementById("window_footer").children, e.target);
el.getElementById("window_footer").children[index + 1].focus();
e.preventDefault();
};
break;
case 40: //DOWN
e.preventDefault();
if (e.target.parentNode == el) {
el.getElementById("control_input").children[0].focus();
};
if (el.getElementById("control_input").contains(e.target)) {
el.getElementById("window_footer").children[0].focus();
};
break;
};
};
function numeric_search(keyCode) {
switch (keyCode) {
case 96:
keychar["keyCode"] = keyCode;
keychar["Char"] = "0";
break;
case 97:
keychar["keyCode"] = keyCode;
keychar["Char"] = "1";
break;
case 98:
if (keychar["keyCode"] == keyCode) {
switch (keychar["Char"]) {
case "a":
keychar["Char"] = "b";
break;
case "b":
keychar["Char"] = "c";
break;
case "c":
keychar["Char"] = "2";
break;
case "2":
keychar["Char"] = "a";
break;
};
}
else {
keychar["keyCode"] = keyCode;
keychar["Char"] = "a";
};
break;
case 99:
if (keychar["keyCode"] == keyCode) {
switch (keychar["Char"]) {
case "d":
keychar["Char"] = "e";
break;
case "e":
keychar["Char"] = "f";
break;
case "f":
keychar["Char"] = "3";
break;
case "3":
keychar["Char"] = "d";
break;
};
}
else {
keychar["keyCode"] = keyCode;
keychar["Char"] = "d";
};
break;
case 100:
if (keychar["keyCode"] == keyCode) {
switch (keychar["Char"]) {
case "g":
keychar["Char"] = "h";
break;
case "h":
keychar["Char"] = "i";
break;
case "i":
keychar["Char"] = "4";
break;
case "4":
keychar["Char"] = "g";
break;
};
}
else {
keychar["keyCode"] = keyCode;
keychar["Char"] = "g";
};
break;
case 101:
if (keychar["keyCode"] == keyCode) {
switch (keychar["Char"]) {
case "j":
keychar["Char"] = "k";
break;
case "k":
keychar["Char"] = "l";
break;
case "l":
keychar["Char"] = "5";
break;
case "5":
keychar["Char"] = "j";
break;
};
}
else {
keychar["keyCode"] = keyCode;
keychar["Char"] = "j";
};
break;
case 102:
if (keychar["keyCode"] == keyCode) {
switch (keychar["Char"]) {
case "m":
keychar["Char"] = "n";
break;
case "n":
keychar["Char"] = "o";
break;
case "o":
keychar["Char"] = "6";
break;
case "6":
keychar["Char"] = "m";
break;
};
}
else {
keychar["keyCode"] = keyCode;
keychar["Char"] = "m";
};
break;
case 103:
if (keychar["keyCode"] == keyCode) {
switch (keychar["Char"]) {
case "p":
keychar["Char"] = "q";
break;
case "q":
keychar["Char"] = "r";
break;
case "r":
keychar["Char"] = "s";
break;
case "s":
keychar["Char"] = "7";
break;
case "7":
keychar["Char"] = "p";
break;
};
}
else {
keychar["keyCode"] = keyCode;
keychar["Char"] = "p";
};
break;
case 104:
if (keychar["keyCode"] == keyCode) {
switch (keychar["Char"]) {
case "t":
keychar["Char"] = "u";
break;
case "u":
keychar["Char"] = "u";
break;
case "v":
keychar["Char"] = "8";
break;
case "8":
keychar["Char"] = "t";
break;
};
}
else {
keychar["keyCode"] = keyCode;
keychar["Char"] = "t";
};
break;
case 105:
if (keychar["keyCode"] == keyCode) {
switch (keychar["Char"]) {
case "x":
keychar["Char"] = "y";
break;
case "y":
keychar["Char"] = "z";
break;
case "z":
keychar["Char"] = "w";
break;
case "w":
keychar["Char"] = "9";
break;
case "9":
keychar["Char"] = "x";
break;
};
}
else {
keychar["keyCode"] = keyCode;
keychar["Char"] = "x";
};
break;
};
var el = document.getElementById('itemlist');
for (x = 0; x < el.children.length; x++) {
if (el.children[x].children[0].children[2].innerHTML.toLowerCase().indexOf(keychar["Char"]) === 0) {
el.children[x].children[0].focus();
break;
};
if (el.children[x].children[0].children[0].innerHTML.toLowerCase().indexOf(keychar["Char"]) === 0) {
el.children[x].children[0].focus();
break;
};
};
};
document.onkeypress = function (e) {
if ((e || window.event).keyCode === 32) {
if (media_player.paused) {
media_player.play();
}
else {
media_player.pause();
};
};
};
document.ondblclick = function () {
if (media_player.requestFullscreen) {
media_player.requestFullscreen();
}
else if (media_player.mozRequestFullScreen) {
media_player.mozRequestFullScreen();
}
else if (media_player.webkitRequestFullscreen) {
media_player.webkitRequestFullscreen();
};
};

View File

@@ -1,674 +0,0 @@
function get_response(data) {
var response = JSON.parse(data)
var data = response.data;
switch (response.action) {
case "connect":
document.getElementById("version").innerHTML = data.version;
document.getElementById("date").innerHTML = data.date;
session_id = response.id;
break;
case "EndItems":
var item_list = [];
for (var item in data.itemlist) {
context_items = [];
item = data.itemlist[item];
if (item.thumbnail && item.thumbnail.indexOf("http") != 0) {
item.thumbnail = domain + "/local/" + encodeURIComponent(btoa(item.thumbnail));
}
else if (item.thumbnail & false){
item.thumbnail = domain + "/proxy/" + encodeURIComponent(btoa(item.thumbnail));
};
if (item.fanart && item.fanart.indexOf("http") != 0) {
item.fanart = domain + "/local/" + encodeURIComponent(btoa(item.fanart));
}
else if (item.fanart & false){
item.fanart = domain + "/proxy/" + encodeURIComponent(btoa(item.fanart));
};
if (item.action == "go_back") {
item.url = "go_back";
};
if (item.context.length ) {
for (var x in item.context) {
html_item = replace_list(html.dialog.select.item, {
"item_action": "send_request('" + item.context[x].url + "')",
"item_title": item.context[x].title
});
context_items.push(html_item);
}
var menu_button = replace_list(html.itemlist.menu, {
"menu_items": btoa(context_items.join(""))
});
var menu_class = "item_with_menu";
}
else {
var menu_button = "";
var menu_class = "";
};
var replace_dict = {
"item_class": menu_class,
"item_url": item.url,
"item_thumbnail": item.thumbnail,
"item_fanart": item.fanart,
"item_title": item.title,
"item_plot": item.plot,
"item_menu": menu_button,
"menu_items": btoa(context_items.join(""))
};
if (html.itemlist[data.viewmode]) {
var html_item = replace_list(html.itemlist[data.viewmode], replace_dict);
}
else {
var html_item = replace_list(html.itemlist.movie, replace_dict);
}
item_list.push(html_item);
};
document.getElementById("itemlist").innerHTML = item_list.join("");
set_category(data.category);
document.getElementById("itemlist").children[0].children[0].focus();
document.getElementById("itemlist").scrollTop = 0;
show_images();
nav_history.newResponse(item_list, data.category);
//console.debug(nav_history)
send_data({
"id": response.id,
"result": true
});
loading.close();
break;
case "Refresh":
nav_history.current -= 1
send_request(nav_history.states[nav_history.current].url);
send_data({
"id": response.id,
"result": true
});
break;
case "Alert":
loading.close();
dialog.ok(response.id, data);
break;
case "notification":
dialog.notification(response.id, data);
break;
case "AlertYesNo":
loading.close()
dialog.yesno(response.id, data)
break;
case "ProgressBG":
dialog.progress_bg(response.id, data);
send_data({
"id": response.id,
"result": true
});
break;
case "ProgressBGUpdate":
dialog.progress_bg(response.id, data);
break;
case "ProgressBGClose":
dialog.progress_bg_close();
send_data({
"id": response.id,
"result": true
});
break;
case "Progress":
loading.close();
dialog.progress(response.id, data);
send_data({
"id": response.id,
"result": true
});
break;
case "ProgressUpdate":
dialog.progress_update(response.id, data);
break;
case "ProgressClose":
dialog.progress_close();
send_data({
"id": response.id,
"result": true
});
loading.close();
break;
case "ProgressIsCanceled":
send_data({
"id": response.id,
"result": document.getElementById("window_progress").getElementById("canceled").checked != ""
});
break;
case "isPlaying":
send_data({
"id": response.id,
"result": document.getElementById("Player-popup").style.display == "block" || document.getElementById("Lista-popup").style.display == "block"
});
break;
case "Keyboard":
loading.close();
dialog.keyboard(response.id, data);
break;
case "recaptcha":
loading.close();
dialog.recaptcha(response.id, data);
break;
case "recaptcha_select":
loading.close();
dialog.recaptcha_select(response.id, data);
break
case "List":
loading.close();
dialog.select(response.id, data);
break;
case "Play":
send_data({
"id": response.id,
"result": true
});
loading.close();
if (settings.player_mode == 0) {
var lista = [];
for (var player in players) {
lista.push(replace_list(html.dialog.select.item, {
"item_title": players[player],
"item_action": "play_mode('" + data.video_url + "','" + data.title + "','" + player + "')"
}));
};
dialog.menu("Elige el Reproductor", btoa(lista.join("")));
}
else {
play_mode(data.video_url, data.title, Object.keys(players)[settings.player_mode - 1]);
};
break;
case "Update":
send_request(data.url);
loading.close();
break;
case "HideLoading":
loading.close();
break;
case "ShowLoading":
loading.show();
break;
case "OpenInfo":
loading.close();
dialog.info(response.id, data);
break;
case "custom_button":
dialog.custom_button(response.id, data);
break;
case "OpenConfig":
loading.close();
var itemlist = {};
default_settings = {};
settings_controls = [];
for (var x in data.items) {
if (!itemlist[data.items[x].category]) {
itemlist[data.items[x].category] = [];
};
if (data.items[x].id) {
default_settings[data.items[x].id] = data.items[x]["default"];
}
if (!data.items[x].color || data.items[x].color == "auto") {
data.items[x].color = "#FFFFFF";
};
if (!data.items[x].enabled && data.items[x].enable) {
data.items[x].enabled = data.items[x].enable;
};
settings_controls.push(data.items[x]);
switch (data.items[x].type) {
case "sep":
itemlist[data.items[x].category].push(replace_list(html.config.sep, {}));
break;
case "lsep":
case "label":
itemlist[data.items[x].category].push(replace_list(html.config.label, {
"item_color": data.items[x].color,
"item_label": data.items[x].label
}));
break;
case "number":
case "text":
if (data.items[x].hidden) {
var type = "password";
}
else {
var type = "text";
};
if (data.items[x].type == 'number') {
keypress = "if ('0123456789'.indexOf(event.key) == -1 && event.charCode){return false}"
}
else {
keypress = "";
};
itemlist[data.items[x].category].push(replace_list(html.config.text, {
"item_color": data.items[x].color,
"item_label": data.items[x].label,
"item_id": data.items[x].id,
"item_value": data.items[x].value,
"item_type": type,
"keypress": keypress
}));
break;
case "bool":
if (data.items[x].value == "true" || data.items[x].value == true) {
var value = "checked='checked'";
}
else {
var value = "";
};
itemlist[data.items[x].category].push(replace_list(html.config.bool, {
"item_color": data.items[x].color,
"item_label": data.items[x].label,
"item_id": data.items[x].id,
"item_value": value
}));
break;
case "labelenum":
if (!data.items[x].values) {
var values = data.items[x].lvalues.split("|");
}
else {
var values = data.items[x].values.split("|");
};
var options = [];
for (var y in values) {
if (data.items[x].value == values[y]) {
options.push("<option selected=selected>" + values[y] + "</option>");
}
else {
options.push("<option>" + values[y] + "</option>");
};
};
itemlist[data.items[x].category].push(replace_list(html.config.list, {
"item_type": "labelenum",
"item_color": data.items[x].color,
"item_label": data.items[x].label,
"item_id": data.items[x].id,
"item_values": options
}));
break;
case "list":
var options = [];
for (var y in data.items[x].lvalues) {
if (data.items[x].value == y) {
options.push("<option selected=selected>" + data.items[x].lvalues[y] + "</option>");
}
else {
options.push("<option>" + data.items[x].lvalues[y] + "</option>");
};
};
itemlist[data.items[x].category].push(replace_list(html.config.list, {
"item_type": "enum",
"item_color": data.items[x].color,
"item_label": data.items[x].label,
"item_id": data.items[x].id,
"item_values": options
}));
break;
case "enum":
if (!data.items[x].values) {
var values = data.items[x].lvalues.split("|");
}
else {
var values = data.items[x].values.split("|");
};
var options = [];
for (var y in values) {
if (data.items[x].value == y) {
options.push("<option selected=selected>" + values[y] + "</option>");
}
else {
options.push("<option>" + values[y] + "</option>");
};
};
itemlist[data.items[x].category].push(replace_list(html.config.list, {
"item_type": "enum",
"item_color": data.items[x].color,
"item_label": data.items[x].label,
"item_id": data.items[x].id,
"item_values": options
}));
break;
default:
break;
};
};
var categories = [];
var category_list = [];
for (var category in itemlist) {
if (Object.keys(itemlist).length > 1 || category != "undefined") {
categories.push(replace_list(html.config.category, {
"item_label": category,
"item_category": category
}));
};
category_list.push(replace_list(html.config.container, {
"item_id": "category_" + category,
"item_value": itemlist[category].join("")
}));
};
dialog.config(response.id, data, categories.join(""), category_list.join(""));
evaluate_controls();
break;
default:
break;
};
};
function custom_button(data) {
if (data == null) {
var controls = document.getElementById("window_settings").getControls();
for (var x in controls) {
switch (controls[x].type) {
case "text":
controls[x].value = default_settings[controls[x].id];
break;
case "password":
controls[x].value = default_settings[controls[x].id];
break;
case "checkbox":
value = default_settings[controls[x].id];
if (value == true) {
value = "checked";
}
else {
value = "";
};
controls[x].checked = value;
break;
case "select-one":
if (controls[x].name == "enum") {
controls[x].selectedIndex = default_settings[controls[x].id];
}
else if (controls[x].name == "labelenum") {
controls[x].value = default_settings[controls[x].id];
};
break;
};
controls[x].onchange()
};
}
else {
send_data({
"id": document.getElementById("window_settings").RequestID,
"result": "custom_button"
});
if (data["close"] == true) {
dialog.closeall();
};
};
};
function info_window(comando) {
send_data({
"id": document.getElementById("window_info").RequestID,
"result": comando
});
};
function save_config(Guardar) {
if (Guardar === true) {
var JsonAjustes = {};
var controls = document.getElementById("window_settings").getControls();
for (var x in controls) {
switch (controls[x].type) {
case "text":
JsonAjustes[controls[x].id] = controls[x].value;
break;
case "password":
JsonAjustes[controls[x].id] = controls[x].value;
break;
case "checkbox":
JsonAjustes[controls[x].id] = controls[x].checked.toString();
break;
case "select-one":
if (controls[x].name == "enum") {
JsonAjustes[controls[x].id] = controls[x].selectedIndex.toString();
}
else if (controls[x].name == "labelenum") {
JsonAjustes[controls[x].id] = controls[x].value;
}
break;
}
}
send_data({
"id": document.getElementById("window_settings").RequestID,
"result": JsonAjustes
});
}
else {
send_data({
"id": document.getElementById("window_settings").RequestID,
"result": false
});
};
loading.show();
};
function evaluate_controls(control_changed) {
if (typeof control_changed != "undefined") {
for (var x in settings_controls) {
if (settings_controls[x].id == control_changed.id) {
switch (control_changed.type) {
case "text":
settings_controls[x].value = control_changed.value;
break;
case "password":
settings_controls[x].value = control_changed.value;
break;
case "checkbox":
settings_controls[x].value = control_changed.checked;
break;
case "select-one":
if (control_changed.name == "enum") {
settings_controls[x].value = control_changed.selectedIndex;
}
else if (control_changed.name == "labelenum") {
settings_controls[x].value = control_changed.value;
};
break;
};
break;
};
};
};
for (var index in settings_controls) {
control = get_control_group(index);
set_visible(document.getElementById("window_settings").getElementById("controls_container").children[control[0]].children[control[1]], evaluate(index, settings_controls[index].visible));
set_enabled(document.getElementById("window_settings").getElementById("controls_container").children[control[0]].children[control[1]], evaluate(index, settings_controls[index].enabled));
};
};
function set_visible(element, visible) {
if (visible) {
element.style.display = "block";
}
else {
element.style.display = "none";
};
};
function set_enabled(element, enabled) {
if (element.children[0].className == "control") {
element.children[0].children[1].disabled = !enabled;
};
};
function get_control_group(index) {
var group = 0;
var pos = 0;
var children = document.getElementById("window_settings").getElementById("controls_container").children;
for (child in children) {
if (pos + children[child].children.length <= index) {
group ++;
pos += children[child].children.length;
}
else {
break;
};
};
return [group, index - pos];
};
function evaluate(index, condition) {
index = parseInt(index);
if (typeof condition == "undefined") {
return true;
};
if (typeof condition == "boolean") {
return condition;
};
if (condition.toLocaleLowerCase() == "true") {
return true;
}
else if (condition.toLocaleLowerCase() == "false") {
return false;
};
const regex = /(!?eq|!?gt|!?lt)?\(([^,]+),[\"|']?([^)|'|\"]*)['|\"]?\)[ ]*([+||])?/g;
while ((m = regex.exec(condition)) !== null) {
// This is necessary to avoid infinite loops with zero-width matches
if (m.index === regex.lastIndex) {
regex.lastIndex++;
};
var operator = m[1];
var id = parseInt(m[2]);
var value = m[3];
var next = m[4];
if (isNaN(id)) {
return false;
};
if (index + id < 0 || index + id >= settings_controls.length) {
return false;
}
else {
if (settings_controls[index + id].type == "list" || settings_controls[index + id].type == "enum") {
if (settings_controls[index + id].lvalues){
control_value = settings_controls[index + id].lvalues[settings_controls[index + id].value];
}
else {
control_value = settings_controls[index + id].values[settings_controls[index + id].value];
};
}
else {
control_value = settings_controls[index + id].value;
};
};
if (["lt", "!lt", "gt", "!gt"].indexOf(operator) > -1) {
value = parseInt(value);
if (isNaN(value)) {
return false;
};
};
if (["eq", "!eq"].indexOf(operator) > -1) {
if (typeof(value) == "string") {
if (!isNaN(parseInt(value))) {
value = parseInt(value);
}
else if (value.toLocaleLowerCase() == "true") {
value = true;
}
else if (value.toLocaleLowerCase() == "false") {
value = false;
};
};
};
if (operator == "eq") {
ok = (control_value == value);
};
if (operator == "!eq") {
ok = !(control_value == value);
};
if (operator == "gt") {
ok = (control_value > value);
};
if (operator == "!gt") {
ok = !(control_value > value);
};
if (operator == "lt") {
ok = (control_value < value);
};
if (operator == "!lt") {
ok = !(control_value < value);
};
if (next == "|" && ok == true) {
break;
};
if (next == "+" && ok == false) {
break;
};
};
return ok;
};

View File

@@ -1,79 +0,0 @@
function websocket_connect() {
if (websocket) {
websocket.close();
};
var status = document.getElementById("footer").getElementById("status");
status.innerHTML = "Conectando...";
loading.show("Estableciendo conexión...");
websocket = new WebSocket(websocket_host);
websocket.onopen = function (evt) {
loading.show();
status.innerHTML = "Conectado";
};
websocket.onclose = function (evt) {
status.innerHTML = "Desconectado";
};
websocket.onmessage = function (evt) {
get_response(evt.data);
};
websocket.onerror = function (evt) {
websocket.close();
};
};
function websocket_send(data, retry) {
if (!retry) {
connection_retry = true;
};
if (!websocket){
websocket_connect();
};
if (websocket.readyState != 1) {
if ((websocket.readyState == 2 || websocket.readyState == 3) && connection_retry) {
websocket_connect();
};
setTimeout(websocket_send, 500, data, true);
return;
}
else if (websocket.readyState == 1) {
data["id"] = session_id;
websocket.send(JSON.stringify(data));
};
};
function send_request(url) {
if (url == "go_back") {
nav_history.go(-1);
return;
};
nav_history.newRequest(url);
loading.show();
var send = {};
send["request"] = url;
websocket_send(send);
};
function send_data(dato) {
var send = {};
send["data"] = dato;
websocket_send(send);
};
function ajax_to_dict(url, obj, key) {
var xhttp = new XMLHttpRequest();
ajax_running.push(xhttp);
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
eval("obj." + key + " = xhttp.responseText");
ajax_running.remove(xhttp)
};
};
xhttp.open("GET", url, true);
xhttp.send();
};

View File

@@ -1,225 +0,0 @@
function dispose() {
var height = document.getElementById("window").offsetHeight;
var header = document.getElementById("header").offsetHeight;
var footer = document.getElementById("footer").offsetHeight;
var panelheight = height - header - footer;
document.getElementById('content').style.height = panelheight + "px";
if (document.getElementById("window").offsetWidth < 800) {
document.getElementById('panel_items').className = "panel_items_vertical";
document.getElementById('panel_info').className = "panel_info_vertical";
}
else {
document.getElementById('panel_items').className = "panel_items";
document.getElementById('panel_info').className = "panel_info";
}
};
function replace_list(data, list) {
for (var key in list) {
var re = new RegExp("%" + key, "g");
data = data.replace(re, list[key]);
};
return data;
};
function play_mode(url, title, player) {
if (!new RegExp("^(.+://)").test(url)) {
url = domain + "/local/" + encodeURIComponent(btoa(Utf8.encode(data.video_url))) + "/video.mp4";
}
else {
var indirect_url = domain + "/proxy/" + encodeURIComponent(btoa(Utf8.encode(url))) + "/video.mp4";
};
if (settings.play_mode == 0 && indirect_url) {
var lista = [];
lista.push(replace_list(html.dialog.select.item, {
"item_title": "Indirecto",
"item_action": player + "('" + indirect_url + "','" + title + "')"
}));
lista.push(replace_list(html.dialog.select.item, {
"item_title": "Directo",
"item_action": player + "('" + url + "','" + title + "')"
}));
dialog.menu("Metodo de reproducción", btoa(lista.join("")));
}
else if (settings.play_mode == 1 && indirect_url) {
eval(player)(indirect_url, title);
}
else {
eval(player)(url, title);
};
};
function play(url, title) {
window.open(url);
}
function vlc_play(url, title) {
var html_code = replace_list(html.vlc_player, {
"video_url": url
});
dialog.player(title, html_code);
}
function flash_play(url, title) {
var html_code = replace_list(html.flash_player, {
"video_url": url
});
dialog.player(title, html_code);
}
function html_play(url, title) {
var html_code = replace_list(html.html_player, {
"video_url": url
});
dialog.player(title, html_code);
}
function set_category(category) {
var el = document.getElementById("header");
if (category) {
el.getElementById("heading").innerHTML = "alfa / " + category;
document.title = "alfa / " + category;
}
else {
el.getElementById("heading").innerHTML = "alfa";
document.title = "alfa";
};
};
function focus_element(element) {
element.focus()
};
function image_error(thumbnail) {
var src = thumbnail.src;
if (thumbnail.src.indexOf(domain) == 0) {
thumbnail.src = "http://media.tvalacarta.info/pelisalacarta/thumb_folder2.png";
}
else {
thumbnail.src = domain + "/proxy/" + encodeURIComponent(btoa(thumbnail.src));
}
if (thumbnail.parentNode == document.activeElement && document.activeElement.className != "item_menu"){
document.activeElement.onfocus();
};
};
function show_images(){
var container = document.getElementById("itemlist");
var images = container.getElementsByTagName("img");
var item_height = images[0].parentNode.parentNode.offsetHeight;
var first = Math.floor(container.scrollTop / item_height);
var count = Math.ceil(container.offsetHeight / item_height + (container.scrollTop / item_height - first));
for (var x = first; x < first + count; x++){
var image = images[x]
if (image && !image.src){
image.src = image.parentNode.getElementsByClassName("thumbnail")[1].innerHTML;
if (image.parentNode == document.activeElement){
document.activeElement.onfocus();
};
};
};
};
function load_info(item, viewmode) {
var thumbnail = item.getElementsByClassName("thumbnail")[0];
var fanart = item.getElementsByClassName("fanart")[0];
var title = item.getElementsByClassName("label")[0];
var plot = item.getElementsByClassName("plot")[0];
var el = document.getElementById("media_info");
el.getElementById("media_poster").src = thumbnail.src;
el.getElementById("media_plot").innerHTML = plot.innerHTML.replace(/\n/g, "<br>");
el.getElementById("media_title").innerHTML = title.innerHTML;
if (fanart.innerHTML && settings.show_fanart) {
document.getElementById("content").style.backgroundImage = "linear-gradient(rgba(255,255,255,0.5),rgba(255,255,255,0.5)), url(" + fanart.innerHTML + ")";
document.getElementById("content").children[0].style.opacity = ".9";
document.getElementById("content").children[1].style.opacity = ".9";
}
else {
document.getElementById("content").style.backgroundImage = "";
document.getElementById("content").children[0].style.opacity = "";
document.getElementById("content").children[1].style.opacity = "";
};
if (viewmode == "list") {
el.getElementById("media_poster").style.display = "block";
el.getElementById("media_plot").style.display = "block";
el.getElementById("media_title").style.display = "none";
document.getElementById("version_info").style.display = "none";
}
else if (viewmode == "banner" || viewmode == "channel") {
el.getElementById("media_poster").style.display = "none";
el.getElementById("media_plot").style.display = "none";
el.getElementById("media_title").style.display = "none";
document.getElementById("version_info").style.display = "block";
}
else {
el.getElementById("media_poster").style.display = "block";
el.getElementById("media_plot").style.display = "block";
el.getElementById("media_title").style.display = "block";
document.getElementById("version_info").style.display = "none";
}
auto_scroll(el.getElementById("media_plot"));
};
function unload_info(obj) {
var el = document.getElementById('media_info');
document.getElementById("version_info").style.display = "block";
el.getElementById("media_poster").style.display = "none";
el.getElementById("media_plot").style.display = "none";
el.getElementById("media_title").style.display = "none";
el.getElementById("media_poster").src = "";
el.getElementById("media_plot").innerHTML = "";
el.getElementById("media_title").innerHTML = "";
document.getElementById("content").style.backgroundImage = ""
document.getElementById("content").children[0].style.opacity = "";
document.getElementById("content").children[1].style.opacity = "";
};
function change_category(category) {
var el = document.getElementById('window_settings');
el.getElementById("controls_container").scrollTop = 0;
categories = el.getElementById("controls_container").getElementsByTagName("ul");
for (var x in categories) {
if (categories[x].id == "category_" + category) {
categories[x].style.display = "block";
}
else if (categories[x].style) {
categories[x].style.display = "none";
};
};
};
function auto_scroll(element) {
clearInterval(element.interval);
element.scrollLeft = 0;
element.scrollTop = 0;
if (element.scrollWidth > element.offsetWidth) {
initialscrollWidth = element.scrollWidth;
element.innerHTML = element.innerHTML + " | " + element.innerHTML;
element.interval = setInterval(function () {
element.scrollLeft += 1;
if (element.scrollLeft - 1 >= element.scrollWidth - initialscrollWidth) {
element.scrollLeft = 0;
};
}, 80);
};
if (element.scrollHeight > element.offsetHeight) {
initialscrollHeight = element.scrollHeight;
element.innerHTML = element.innerHTML + "</br>" + element.innerHTML;
element.interval = setInterval(function () {
element.scrollTop += 1;
if (element.scrollTop >= element.scrollHeight - initialscrollHeight) {
element.scrollTop = 0;
};
}, 80);
};
};
function center_window(el) {
el.style.top = document.getElementById("window").offsetHeight / 2 - el.offsetHeight / 2 + "px";
};

View File

@@ -1,43 +0,0 @@
var Utf8 = { // public method for url encoding
encode: function(string) {
string = string.replace(/\r\n/g, "\n");
var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
} else if ((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
} else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return utftext;
}, // public method for url decoding
decode: function(utftext) {
var string = "";
var i = 0;
var c = c1 = c2 = 0;
while (i < utftext.length) {
c = utftext.charCodeAt(i);
if (c < 128) {
string += String.fromCharCode(c);
i++;
} else if ((c > 191) && (c < 224)) {
c2 = utftext.charCodeAt(i + 1);
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
i += 2;
} else {
c2 = utftext.charCodeAt(i + 1);
c3 = utftext.charCodeAt(i + 2);
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
i += 3;
}
}
return string;
}
};

View File

@@ -1,139 +0,0 @@
var domain = window.location.href.split("/").slice(0, 3).join("/");
var focused_item = null;
var websocket = null;
var session_id = null;
var default_settings = {};
var settings_controls = [];
var connection_retry = true;
var settings = {};
var loading = {};
var dialog = {};
var ajax_running = [];
var keychar = {
"keyCode": 0,
"Time": 0,
"Char": ""
};
var html = {
"dialog": {
"select": {}
},
"config": {},
"itemlist": {}
};
var players = {
"play": "Abrir enlace",
"vlc_play": "Plugin VLC",
"flash_play": "Reproductor Flash",
"html_play": "Video HTML"
};
var nav_history = {
"newRequest": function (url) {
if (this.confirmed) {
if (this.states[this.current].url == url) {
this.states[this.current].url;
this.states[this.current].start;
}
else {
this.states[this.current].scroll = document.getElementById("itemlist").scrollTop;
this.states[this.current].focus = Array.prototype.indexOf.call(document.getElementById("itemlist").children, focused_item.parentNode);
this.current += 1;
this.states.splice(this.current, 0, {
"start": new Date().getTime(),
"url": url
});
this.confirmed = false;
}
}
else {
if (this.current == -1) {
this.current = 0;
this.states.push({
"start": new Date().getTime(),
"url": url
});
}
else {
this.states[this.current].start = new Date().getTime();
this.states[this.current].url = url;
}
}
},
"newResponse": function (data, category) {
if (!this.confirmed) {
if (this.states[this.current].focus >= 0) {
document.getElementById("itemlist").children[this.states[this.current].focus].children[0].focus();
document.getElementById("itemlist").scrollTop = this.states[this.current].scroll;
}
this.states[this.current].end = new Date().getTime();
this.states[this.current].data = data;
this.states[this.current].category = category;
this.confirmed = true;
if (settings.builtin_history && !this.from_nav) {
if (this.current > 0) {
history.pushState(this.current.toString(), "", "#" + this.states[this.current].url);
}
else {
history.replaceState(this.current.toString(), "", "#" + this.states[this.current].url);
}
}
}
else {
if (this.states[this.current].focus >= 0) {
document.getElementById("itemlist").children[this.states[this.current].focus].children[0].focus();
document.getElementById("itemlist").scrollTop = this.states[this.current].scroll;
}
this.states[this.current].end = new Date().getTime();
this.states[this.current].data = data;
this.states[this.current].category = category;
this.states = this.states.slice(0, this.current + 1);
}
this.from_nav = false;
},
"go": function (index) {
if (!this.confirmed) {
this.current -= 1;
this.confirmed = true;
}
this.states[this.current].scroll = document.getElementById("itemlist").scrollTop;
this.states[this.current].focus = Array.prototype.indexOf.call(document.getElementById("itemlist").children, focused_item.parentNode);
if (this.current + index < 0) {
this.current = -1;
this.confirmed = false;
send_request("");
return;
}
else if (this.current + index >= this.states.lenght) {
this.current = this.states.lenght - 1;
}
else {
this.current += index;
}
if (this.states[this.current].end - this.states[this.current].start > this.cache) {
document.getElementById("itemlist").innerHTML = this.states[this.current].data.join("");
set_category(this.states[this.current].category)
if (this.states[this.current].focus >= 0) {
document.getElementById("itemlist").children[this.states[this.current].focus].children[0].focus();
}
if (this.states[this.current].scroll) {
document.getElementById("itemlist").scrollTop = this.states[this.current].scroll;
}
show_images();
this.confirmed = true;
}
else {
this.confirmed = false;
this.from_nav = true;
send_request(this.states[this.current].url);
}
},
"current": -1,
"confirmed": false,
"from_nav": false,
"states": [],
"cache": 2000 //Tiempo para determinar si se cargará la cache o se volvera a solicitar el item (el tiempo es el que tarda en responder el servidor)
};

View File

@@ -1,15 +0,0 @@
{
"name": "alfa",
"icons": [
{
"src": "/media/icon-512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#00779F",
"background_color": "#00779F",
"start_url": "/",
"display": "standalone",
"orientation": "any"
}

View File

@@ -1,224 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="/media/favicon.ico" />
<!-- Web as app support -->
<link rel="manifest" href="/media/manifest.json">
<meta name="mobile-web-app-capable" content="yes">
<!-- Navigation bar color -->
<!-- Chrome, Firefox OS and Opera -->
<meta name="theme-color" content="#01455c">
<!-- Windows Phone -->
<meta name="msapplication-navbutton-color" content="#01455c">
<!-- iOS Safari -->
<meta name="apple-mobile-web-app-status-bar-style" content="#01455c">
<title>alfa</title>
<link rel="stylesheet" href="/media/css/alfa.css" />
<script type="text/javascript" src="/media/js/main.js"></script>
<script type="text/javascript" src="/media/js/vars.js"></script>
<script type="text/javascript" src="/media/js/ui.js"></script>
<script type="text/javascript" src="/media/js/navigation.js"></script>
<script type="text/javascript" src="/media/js/dialogs.js"></script>
<script type="text/javascript" src="/media/js/protocol.js"></script>
<script type="text/javascript" src="/media/js/socket.js"></script>
<script type="text/javascript" src="/media/js/utils.js"></script>
<script type="text/javascript">
websocket_host = 'ws://' + window.location.hostname + ':{$WSPORT}'
</script>
</head>
<body>
<!-- loading -->
<div class="window_loading" id="window_loading">
<span class="loading_animation"></span>
<a class="loading_message" id="loading_message" href="javascript:void(0)">Cargando...</a>
</div>
<!--/window_progress -->
<div class="window_background_progress" id="window_background_progress">
<div Class="window_heading" id="window_heading"></div>
<div Class="window_message" id="window_message"></div>
<div Class="progressbar_background" id="progressbar_background">
<div Class="progressbar" id="progressbar"></div>
</div>
</div>
<div class="window_overlay" id="window_overlay"></div>
<!-- window_select -->
<div class="window_select" id="window_select">
<a class="window_close" href="javascript:void(0)" onmouseover="this.focus()" onclick="send_data({'id':this.parentNode.RequestID, 'result':-1 });dialog.closeall();"></a>
<div class="window_heading" id="window_heading"></div>
<ul class="control_list" id="control_list"></ul>
</div>
<!-- window_ok -->
<div class="window_ok" id="window_ok">
<a class="window_close" href="javascript:void(0)" onmouseover="this.focus()" onclick="send_data({'id':this.parentNode.RequestID, 'result':true });dialog.closeall();"></a>
<div class="window_heading" id="window_heading"></div>
<div Class="window_message" id="window_message"></div>
<div class="window_footer" id="window_footer">
<a href="javascript:void(0)" class="control_button button_ok" onmouseover="this.focus()" onclick="send_data({'id':this.parentNode.parentNode.RequestID, 'result':true });dialog.closeall();">Aceptar</a>
</div>
</div>
<!-- window_yesno -->
<div class="window_yesno" id="window_yesno">
<a class="window_close" href="javascript:void(0)" onmouseover="this.focus()" onclick="send_data({'id':this.parentNode.RequestID, 'result':false });dialog.closeall();"></a>
<div class="window_heading" id="window_heading"></div>
<div Class="window_message" id="window_message"></div>
<div class="window_footer" id="window_footer">
<a href="javascript:void(0)" class="control_button button_ok" onmouseover="this.focus()" onclick="send_data({'id':this.parentNode.parentNode.RequestID, 'result':true });dialog.closeall();">Si</a>
<a href="javascript:void(0)" class="control_button button_close" onmouseover="this.focus()" onclick="send_data({'id':this.parentNode.parentNode.RequestID, 'result':false });dialog.closeall();">No</a>
</div>
</div>
<!-- window_notification -->
<div class="window_notification" id="window_notification">
<div class="window_icon" id="window_icon"></div>
<div Class="window_heading" id="window_heading"></div>
<div Class="window_message" id="window_message"></div>
</div>
<!--/window_progress -->
<div class="window_progress" id="window_progress">
<a class="window_close" href="javascript:void(0)" onmouseover="this.focus()" onclick="this.parentNode.querySelector('#canceled').checked='checked';this.parentNode.querySelector('#window_heading').innerHTML += ' Cancelando...';"></a>
<div class="window_heading" id="window_heading"></div>
<div Class="window_message" id="window_message"></div>
<div Class="progress_background" id="progress_background">
<div Class="progress" id="progress"></div>
</div>
<div class="window_footer" id="window_footer">
<a href="javascript:void(0)" class="control_button button_close" onmouseover="this.focus()" onclick="this.parentNode.querySelector('#canceled').checked='checked';this.parentNode.parentNode.querySelector('#window_heading').innerHTML += ' Cancelando...';">Cancelar</a>
<input type="checkbox" style="display:none" id="canceled">
</div>
</div>
<!-- window_input -->
<div class="window_input" id="window_input">
<a class="window_close" href="javascript:void(0)" onmouseover="this.focus()" onclick="send_data({'id':this.parentNode.RequestID, 'result':null });dialog.closeall();"></a>
<div class="window_heading" id="window_heading"></div>
<div class="control_input" id="control_input">
<input class="control_input" id="window_value" type="text" onkeypress="if(event.keyCode == 13){send_data({'id':this.parentNode.parentNode.RequestID, 'result':this.value });dialog.closeall();loading.show();}">
<label class="control_input"></label>
</div>
<div class="window_footer" id="window_footer">
<a href="javascript:void(0)" class="control_button button_ok" onmouseover="this.focus()" onclick="send_data({'id':this.parentNode.parentNode.RequestID, 'result':this.parentNode.parentNode.getElementById('window_value').value});dialog.closeall();loading.show();">Aceptar</a>
<a href="javascript:void(0)" class="control_button button_close" onmouseover="this.focus()" onclick="send_data({'id':this.parentNode.parentNode.RequestID, 'result':null });dialog.closeall();">Cancelar</a>
</div>
</div>
<!-- window_captcha -->
<div class="window_recaptcha" id="window_recaptcha">
<a class="window_close" href="javascript:void(0)" onmouseover="this.focus()" onclick="send_data({'id':this.parentNode.RequestID, 'result':null });dialog.closeall();"></a>
<div class="window_heading" id="window_heading"></div>
<div Class="window_message" id="window_message"></div>
<div class="window_image" id= "window_image">
<a href="javascript:void(0)" onmouseover="this.focus()" onmouseout="this.blur()" onclick="send_data({'id':this.parentNode.parentNode.RequestID, 'result': 0})"></a>
<a href="javascript:void(0)" onmouseover="this.focus()" onmouseout="this.blur()" onclick="send_data({'id':this.parentNode.parentNode.RequestID, 'result': 1})"></a>
<a href="javascript:void(0)" onmouseover="this.focus()" onmouseout="this.blur()" onclick="send_data({'id':this.parentNode.parentNode.RequestID, 'result': 2})"></a>
<a href="javascript:void(0)" onmouseover="this.focus()" onmouseout="this.blur()" onclick="send_data({'id':this.parentNode.parentNode.RequestID, 'result': 3})"></a>
<a href="javascript:void(0)" onmouseover="this.focus()" onmouseout="this.blur()" onclick="send_data({'id':this.parentNode.parentNode.RequestID, 'result': 4})"></a>
<a href="javascript:void(0)" onmouseover="this.focus()" onmouseout="this.blur()" onclick="send_data({'id':this.parentNode.parentNode.RequestID, 'result': 5})"></a>
<a href="javascript:void(0)" onmouseover="this.focus()" onmouseout="this.blur()" onclick="send_data({'id':this.parentNode.parentNode.RequestID, 'result': 6})"></a>
<a href="javascript:void(0)" onmouseover="this.focus()" onmouseout="this.blur()" onclick="send_data({'id':this.parentNode.parentNode.RequestID, 'result': 7})"></a>
<a href="javascript:void(0)" onmouseover="this.focus()" onmouseout="this.blur()" onclick="send_data({'id':this.parentNode.parentNode.RequestID, 'result': 8})"></a>
</div>
<div class="window_footer" id="window_footer">
<a href="javascript:void(0)" class="control_button button_ok" onmouseover="this.focus()" onclick="send_data({'id':this.parentNode.parentNode.RequestID, 'result':true});dialog.closeall();loading.show();">Aceptar</a>
<a href="javascript:void(0)" class="control_button button_close" onmouseover="this.focus()" onclick="send_data({'id':this.parentNode.parentNode.RequestID, 'result':null });dialog.closeall();">Cancelar</a>
<a href="javascript:void(0)" class="control_button button_ok" onmouseover="this.focus()" onclick="send_data({'id':this.parentNode.parentNode.RequestID, 'result':'refresh'});dialog.closeall();loading.show();">Recargar</a>
</div>
</div>
<!--/window_settings -->
<div id="window_settings" class="window_settings">
<a class="window_close" href="javascript:void(0)" onmouseover="this.focus()" onclick="dialog.closeall();if(this.parentNode.getElementById('window_footer').style.display != 'none'){save_config(false)}"></a>
<div class="window_heading" id="window_heading"></div>
<div class="category_container" id="category_container"></div>
<div class="controls_container" id="controls_container"></div>
<div class="window_footer" id="window_footer_local" style="display:none">
<a href="javascript:void(0)" class="control_button button_ok" onmouseover="this.focus()" onclick="save_settings();dialog.closeall()">Guardar</a>
<a href="javascript:void(0)" class="control_button button_close" onmouseover="this.focus()" onclick="dialog.closeall()">Cerrar</a>
</div>
<div class="window_footer" id="window_footer">
<a href="javascript:void(0)" class="control_button button_ok" onmouseover="this.focus()" onclick="dialog.closeall();save_config(true);">Guardar</a>
<a href="javascript:void(0)" class="control_button button_close" onmouseover="this.focus()" onclick="dialog.closeall();save_config(false);">Cerrar</a>
<a href="javascript:void(0)" class="control_button" onmouseover="this.focus()" onclick="custom_button();" id="custom_button"></a>
</div>
</div>
<!--/window_info -->
<div class="window_info" id="window_info">
<a class="window_close" href="javascript:void(0)" onmouseover="this.focus()" onclick="dialog.closeall();info_window('close')"></a>
<div class="window_heading" id="window_heading"></div>
<div class="window_content">
<img class="info_fanart" id="info_fanart">
<img class="info_poster" id="info_poster">
<span class="line1_head" id="line1_head"></span><span class="line1" id="line1"></span>
<span class="line2_head" id="line2_head"></span><span class="line2" id="line2"></span>
<span class="line3_head" id="line3_head"></span><span class="line3" id="line3"></span>
<span class="line4_head" id="line4_head"></span><span class="line4" id="line4"></span>
<span class="line5_head" id="line5_head"></span><span class="line5" id="line5"></span>
<span class="line6_head" id="line6_head"></span><span class="line6" id="line6"></span>
<span class="line7_head" id="line7_head"></span><span class="line7" id="line7"></span>
<span class="line8_head" id="line8_head"></span><span class="line8" id="line8"></span>
<span class="page_info" id="page_info"></span>
</div>
<div class="window_footer" id="window_footer">
<a href="javascript:void(0)" class="control_button" id="previous" onmouseover="this.focus()" onclick="info_window('previous')">Anterior</a>
<a href="javascript:void(0)" class="control_button" id="next" onmouseover="this.focus()" onclick="info_window('next')">Siguiente</a>
<a href="javascript:void(0)" class="control_button button_close" onmouseover="this.focus()" onclick="dialog.closeall();info_window('close')">Cancelar</a>
<a href="javascript:void(0)" class="control_button button_close" onmouseover="this.focus()" onclick="dialog.closeall();info_window('ok')">Aceptar</a>
</div>
</div>
<!-- window_player -->
<div class="window_player" id="window_player">
<a class="window_close" href="javascript:void(0)" onmouseover="this.focus()" onclick="dialog.closeall()"></a>
<div class="window_heading" id="window_heading"></div>
<div id="media_content" class="media_content"></div>
</div>
<div class="window" id="window">
<div class="header" id="header">
<div class="logo"></div>
<h1 class="heading" id="heading">alfa</h1>
<a class="settings" href="javascript:void(0)" onclick="dialog.settings()"></a>
</div>
<div class="content" id="content">
<div class="panel_info" id="panel_info">
<div class="media_info" id="media_info">
<img id="media_poster" src="" />
<h3 id="media_title"></h3>
<div id="media_plot"></div>
</div>
<div class="version_info" id="version_info">
<span class="Version" id="version"></span><br/>
<span class="Version" id="date"></span>
</div>
</div>
<div class="panel_items" id="panel_items">
<ul class="itemlist" id="itemlist" onscroll="show_images()">
</ul>
</div>
</div>
<div class="footer" id="footer">
<div class="left">
</div>
<div class="links">
<a href="#">Saber más sobre Alfa</a> | <a href="#">Foro</a>
</div>
<div class="status" id="status">Desconectado</div>
</div>
</div>
</body>
</html>