Merge remote-tracking branch 'alfa-addon/master'

This commit is contained in:
unknown
2018-07-04 21:17:01 -03:00
72 changed files with 25017 additions and 3871 deletions

View File

@@ -5,17 +5,17 @@ import re
import threading
import time
import traceback
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
from BaseHTTPServer import HTTPServer
from HTTPWebSocketsHandler import HTTPWebSocketsHandler
from platformcode import config, logger
from core import jsontools as json
class MyHTTPServer(HTTPServer):
daemon_threads = True
def process_request_thread(self, request, client_address):
try:
self.finish_request(request, client_address)
self.shutdown_request(request)
except:
@@ -35,12 +35,15 @@ class MyHTTPServer(HTTPServer):
logger.error(traceback.format_exc())
class Handler(BaseHTTPRequestHandler):
class Handler(HTTPWebSocketsHandler):
def log_message(self, format, *args):
# sys.stderr.write("%s - - [%s] %s\n" %(self.client_address[0], self.log_date_time_string(), format%args))
pass
def do_GET(self):
def sendMessage(self, message):
self.send_message(message)
def do_GET_HTTP(self):
from platformcode import platformtools
from platformcode import controllers
# Control de accesos
@@ -87,6 +90,40 @@ class Handler(BaseHTTPRequestHandler):
del c
return
def on_ws_message(self, message):
try:
if message:
json_message = json.load(message)
if "request" in json_message:
t = threading.Thread(target=run, args=[self.controller, json_message["request"].encode("utf8")], name=self.ID)
t.setDaemon(True)
t.start()
elif "data" in json_message:
if type(json_message["data"]["result"]) == unicode:
json_message["data"]["result"] = json_message["data"]["result"].encode("utf8")
self.controller.data = json_message["data"]
except:
logger.error(traceback.format_exc())
show_error_message(traceback.format_exc())
def on_ws_connected(self):
try:
self.ID = "%032x" % (random.getrandbits(128))
from platformcode.controllers.html import html
self.controller = html(self, self.ID)
self.server.fnc_info()
except:
logger.error(traceback.format_exc())
def on_ws_closed(self):
self.controller.__del__()
del self.controller
self.server.fnc_info()
def address_string(self):
# Disable reverse name lookups
return self.client_address[:2][0]
@@ -95,6 +132,13 @@ class Handler(BaseHTTPRequestHandler):
PORT = config.get_setting("server.port")
server = MyHTTPServer(('', int(PORT)), Handler)
def run(controller, path):
try:
controller.run(path)
except:
logger.error(traceback.format_exc())
show_error_message(traceback.format_exc())
def start(fnc_info):
server.fnc_info = fnc_info

View File

@@ -1,89 +0,0 @@
# -*- coding: utf-8 -*-
# ------------------------------------------------------------
# HTTPServer
# ------------------------------------------------------------
import os
import random
import traceback
from threading import Thread
import WebSocketServer
from core import jsontools as json
from platformcode import config, platformtools, logger
class HandleWebSocket(WebSocketServer.WebSocket):
def handleMessage(self):
try:
if self.data:
json_message = json.load(str(self.data))
if "request" in json_message:
t = Thread(target=run, args=[self.controller, json_message["request"].encode("utf8")], name=self.ID)
t.setDaemon(True)
t.start()
elif "data" in json_message:
if type(json_message["data"]["result"]) == unicode:
json_message["data"]["result"] = json_message["data"]["result"].encode("utf8")
self.controller.data = json_message["data"]
except:
logger.error(traceback.format_exc())
show_error_message(traceback.format_exc())
def handleConnected(self):
try:
self.ID = "%032x" % (random.getrandbits(128))
from platformcode.controllers.html import html
self.controller = html(self, self.ID)
self.server.fnc_info()
except:
logger.error(traceback.format_exc())
self.close()
def handleClose(self):
self.controller.__del__()
del self.controller
self.server.fnc_info()
port = config.get_setting("websocket.port")
server = WebSocketServer.SimpleWebSocketServer("", int(port), HandleWebSocket)
def start(fnc_info):
server.fnc_info = fnc_info
Thread(target=server.serveforever).start()
def stop():
server.close()
def run(controller, path):
try:
controller.run(path)
except:
logger.error(traceback.format_exc())
show_error_message(traceback.format_exc())
def show_error_message(err_info):
from core import scrapertools
patron = 'File "' + os.path.join(config.get_runtime_path(), "channels", "").replace("\\", "\\\\") + '([^.]+)\.py"'
canal = scrapertools.find_single_match(err_info, patron)
if canal:
platformtools.dialog_ok(
"Se ha producido un error en el canal " + canal,
"Esto puede ser devido a varias razones: \n \
- El servidor no está disponible, o no esta respondiendo.\n \
- Cambios en el diseño de la web.\n \
- Etc...\n \
Comprueba el log para ver mas detalles del error.")
else:
platformtools.dialog_ok(
"Se ha producido un error en Alfa",
"Comprueba el log para ver mas detalles del error.")

View File

@@ -14,12 +14,11 @@ from platformcode import config
sys.path.append(os.path.join(config.get_runtime_path(), 'lib'))
from platformcode import platformtools, logger
import HTTPServer
import WebSocket
import HTTPAndWSServer
http_port = config.get_setting("server.port")
websocket_port = config.get_setting("websocket.port")
myip = config.get_local_ip()
version = config.get_addon_version()
def thread_name_wrap(func):
@@ -43,9 +42,8 @@ if sys.version_info < (2, 7, 11):
def show_info():
os.system('cls' if os.name == 'nt' else 'clear')
print ("--------------------------------------------------------------------")
print ("Alfa Iniciado")
print ("Alfa %s Iniciado" %version)
print ("La URL para acceder es http://%s:%s" % (myip, http_port))
print ("WebSocket Server iniciado en ws://%s:%s" % (myip, websocket_port))
print ("--------------------------------------------------------------------")
print ("Runtime Path : " + config.get_runtime_path())
print ("Data Path : " + config.get_data_path())
@@ -67,14 +65,12 @@ def start():
logger.info("server init...")
config.verify_directories_created()
try:
HTTPServer.start(show_info)
WebSocket.start(show_info)
HTTPAndWSServer.start(show_info)
# Da por levantado el servicio
logger.info("--------------------------------------------------------------------")
logger.info("Alfa Iniciado")
logger.info("Alfa %s Iniciado" %version)
logger.info("La URL para acceder es http://%s:%s" % (myip, http_port))
logger.info("WebSocket Server iniciado en ws://%s:%s" % (myip, websocket_port))
logger.info("--------------------------------------------------------------------")
logger.info("Runtime Path : " + config.get_runtime_path())
logger.info("Data Path : " + config.get_data_path())
@@ -91,9 +87,7 @@ def start():
except KeyboardInterrupt:
print 'Deteniendo el servidor HTTP...'
HTTPServer.stop()
print 'Deteniendo el servidor WebSocket...'
WebSocket.stop()
HTTPAndWSServer.stop()
print 'Alfa Detenido'
flag = False

View File

@@ -0,0 +1,229 @@
'''
The MIT License (MIT)
Copyright (C) 2014, 2015 Seven Watt <info@sevenwatt.com>
<http://www.sevenwatt.com>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
'''
# HTTPWebSocketHandler from SevenW: https://github.com/SevenW/httpwebsockethandler
from SimpleHTTPServer import SimpleHTTPRequestHandler
import struct
from base64 import b64encode
from hashlib import sha1
from mimetools import Message
from StringIO import StringIO
import errno, socket #for socket exceptions
import threading
class WebSocketError(Exception):
pass
class HTTPWebSocketsHandler(SimpleHTTPRequestHandler):
_ws_GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
_opcode_continu = 0x0
_opcode_text = 0x1
_opcode_binary = 0x2
_opcode_close = 0x8
_opcode_ping = 0x9
_opcode_pong = 0xa
mutex = threading.Lock()
def on_ws_message(self, message):
"""Override this handler to process incoming websocket messages."""
pass
def on_ws_connected(self):
"""Override this handler."""
pass
def on_ws_closed(self):
"""Override this handler."""
pass
def do_GET_HTTP(self):
"""Override this handler."""
SimpleHTTPRequestHandler.do_GET(self)
pass
def send_message(self, message):
self._send_message(self._opcode_text, message)
def setup(self):
SimpleHTTPRequestHandler.setup(self)
self.connected = False
# def finish(self):
# #needed when wfile is used, or when self.close_connection is not used
# #
# #catch errors in SimpleHTTPRequestHandler.finish() after socket disappeared
# #due to loss of network connection
# try:
# SimpleHTTPRequestHandler.finish(self)
# except (socket.error, TypeError) as err:
# self.log_message("finish(): Exception: in SimpleHTTPRequestHandler.finish(): %s" % str(err.args))
# def handle(self):
# #needed when wfile is used, or when self.close_connection is not used
# #
# #catch errors in SimpleHTTPRequestHandler.handle() after socket disappeared
# #due to loss of network connection
# try:
# SimpleHTTPRequestHandler.handle(self)
# except (socket.error, TypeError) as err:
# self.log_message("handle(): Exception: in SimpleHTTPRequestHandler.handle(): %s" % str(err.args))
def checkAuthentication(self):
auth = self.headers.get('Authorization')
if auth != "Basic %s" % self.server.auth:
self.send_response(401)
self.send_header("WWW-Authenticate", 'Basic realm="Plugwise"')
self.end_headers();
return False
return True
def do_GET(self):
# if self.server.auth and not self.checkAuthentication():
# return
if self.headers.get("Upgrade", None) == "websocket":
self._handshake()
#This handler is in websocket mode now.
#do_GET only returns after client close or socket error.
self._read_messages()
else:
self.do_GET_HTTP()
def _read_messages(self):
while self.connected == True:
try:
self._read_next_message()
except (socket.error, WebSocketError), e:
#websocket content error, time-out or disconnect.
self.log_message("RCV: Close connection: Socket Error %s" % str(e.args))
self._ws_close()
except Exception as err:
#unexpected error in websocket connection.
self.log_error("RCV: Exception: in _read_messages: %s" % str(err.args))
self._ws_close()
def _read_next_message(self):
#self.rfile.read(n) is blocking.
#it returns however immediately when the socket is closed.
try:
self.opcode = ord(self.rfile.read(1)) & 0x0F
length = ord(self.rfile.read(1)) & 0x7F
if length == 126:
length = struct.unpack(">H", self.rfile.read(2))[0]
elif length == 127:
length = struct.unpack(">Q", self.rfile.read(8))[0]
masks = [ord(byte) for byte in self.rfile.read(4)]
decoded = ""
for char in self.rfile.read(length):
decoded += chr(ord(char) ^ masks[len(decoded) % 4])
self._on_message(decoded)
except (struct.error, TypeError) as e:
#catch exceptions from ord() and struct.unpack()
if self.connected:
raise WebSocketError("Websocket read aborted while listening")
else:
#the socket was closed while waiting for input
self.log_error("RCV: _read_next_message aborted after closed connection")
pass
def _send_message(self, opcode, message):
try:
#use of self.wfile.write gives socket exception after socket is closed. Avoid.
self.request.send(chr(0x80 + opcode))
length = len(message)
if length <= 125:
self.request.send(chr(length))
elif length >= 126 and length <= 65535:
self.request.send(chr(126))
self.request.send(struct.pack(">H", length))
else:
self.request.send(chr(127))
self.request.send(struct.pack(">Q", length))
if length > 0:
self.request.send(message)
except socket.error, e:
#websocket content error, time-out or disconnect.
self.log_message("SND: Close connection: Socket Error %s" % str(e.args))
self._ws_close()
except Exception as err:
#unexpected error in websocket connection.
self.log_error("SND: Exception: in _send_message: %s" % str(err.args))
self._ws_close()
def _handshake(self):
headers=self.headers
if headers.get("Upgrade", None) != "websocket":
return
key = headers['Sec-WebSocket-Key']
digest = b64encode(sha1(key + self._ws_GUID).hexdigest().decode('hex'))
self.send_response(101, 'Switching Protocols')
self.send_header('Upgrade', 'websocket')
self.send_header('Connection', 'Upgrade')
self.send_header('Sec-WebSocket-Accept', str(digest))
self.end_headers()
self.connected = True
#self.close_connection = 0
self.on_ws_connected()
def _ws_close(self):
#avoid closing a single socket two time for send and receive.
self.mutex.acquire()
try:
if self.connected:
self.connected = False
#Terminate BaseHTTPRequestHandler.handle() loop:
self.close_connection = 1
#send close and ignore exceptions. An error may already have occurred.
try:
self._send_close()
except:
pass
self.on_ws_closed()
else:
self.log_message("_ws_close websocket in closed state. Ignore.")
pass
finally:
self.mutex.release()
def _on_message(self, message):
#self.log_message("_on_message: opcode: %02X msg: %s" % (self.opcode, message))
# close
if self.opcode == self._opcode_close:
self.connected = False
#Terminate BaseHTTPRequestHandler.handle() loop:
self.close_connection = 1
try:
self._send_close()
except:
pass
self.on_ws_closed()
# ping
elif self.opcode == self._opcode_ping:
_send_message(self._opcode_pong, message)
# pong
elif self.opcode == self._opcode_pong:
pass
# data
elif (self.opcode == self._opcode_continu or
self.opcode == self._opcode_text or
self.opcode == self._opcode_binary):
self.on_ws_message(message)
def _send_close(self):
#Dedicated _send_close allows for catch all exception handling
msg = bytearray()
msg.append(0x80 + self._opcode_close)
msg.append(0x00)
self.request.send(msg)

View File

@@ -1,648 +0,0 @@
'''
The MIT License (MIT)
Copyright (c) 2013 Dave P.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
'''
import SocketServer
import hashlib
import base64
import socket
import struct
import ssl
import time
import sys
import errno
import logging
from BaseHTTPServer import BaseHTTPRequestHandler
from StringIO import StringIO
from select import select
class HTTPRequest(BaseHTTPRequestHandler):
def __init__(self, request_text):
self.rfile = StringIO(request_text)
self.raw_requestline = self.rfile.readline()
self.error_code = self.error_message = None
self.parse_request()
class WebSocket(object):
handshakeStr = (
"HTTP/1.1 101 Switching Protocols\r\n"
"Upgrade: WebSocket\r\n"
"Connection: Upgrade\r\n"
"Sec-WebSocket-Accept: %(acceptstr)s\r\n\r\n"
)
hixiehandshakedStr = (
"HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
"Upgrade: WebSocket\r\n"
"Connection: Upgrade\r\n"
"Sec-WebSocket-Origin: %(origin)s\r\n"
"Sec-WebSocket-Location: %(type)s://%(host)s%(location)s\r\n\r\n"
)
hixie75handshakedStr = (
"HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
"Upgrade: WebSocket\r\n"
"Connection: Upgrade\r\n"
"WebSocket-Origin: %(origin)s\r\n"
"WebSocket-Location: %(type)s://%(host)s%(location)s\r\n\r\n"
)
GUIDStr = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
STREAM = 0x0
TEXT = 0x1
BINARY = 0x2
CLOSE = 0x8
PING = 0x9
PONG = 0xA
HEADERB1 = 1
HEADERB2 = 3
LENGTHSHORT = 4
LENGTHLONG = 5
MASK = 6
PAYLOAD = 7
def __init__(self, server, sock, address):
self.server = server
self.client = sock
self.address = address
self.handshaked = False
self.headerbuffer = ''
self.readdraftkey = False
self.draftkey = ''
self.headertoread = 2048
self.hixie76 = False
self.fin = 0
self.data = None
self.opcode = 0
self.hasmask = 0
self.maskarray = None
self.length = 0
self.lengtharray = None
self.index = 0
self.request = None
self.usingssl = False
self.state = self.HEADERB1
# restrict the size of header and payload for security reasons
self.maxheader = 65536
self.maxpayload = 4194304
def close(self):
self.client.close()
self.state = self.HEADERB1
self.hasmask = False
self.handshaked = False
self.readdraftkey = False
self.hixie76 = False
self.headertoread = 2048
self.headerbuffer = ''
self.data = ''
def handleMessage(self):
pass
def handleConnected(self):
pass
def handleClose(self):
pass
def handlePacket(self):
# close
if self.opcode == self.CLOSE:
self.sendClose()
raise Exception("received client close")
# ping
elif self.opcode == self.PING:
pass
# pong
elif self.opcode == self.PONG:
pass
# data
elif self.opcode == self.STREAM or self.opcode == self.TEXT or self.opcode == self.BINARY:
self.handleMessage()
def handleData(self):
# do the HTTP header and handshake
if self.handshaked is False:
data = self.client.recv(self.headertoread)
if data:
# accumulate
self.headerbuffer += data
if len(self.headerbuffer) >= self.maxheader:
raise Exception('header exceeded allowable size')
# we need to read the entire 8 bytes of after the HTTP header, ensure we do
if self.readdraftkey is True:
self.draftkey += self.headerbuffer
read = self.headertoread - len(self.headerbuffer)
if read != 0:
self.headertoread = read
else:
# complete hixie76 handshake
self.handshake_hixie76()
# indicates end of HTTP header
elif '\r\n\r\n' in self.headerbuffer:
self.request = HTTPRequest(self.headerbuffer)
# hixie handshake
if self.request.headers.has_key('Sec-WebSocket-Key1'.lower()) and self.request.headers.has_key('Sec-WebSocket-Key2'.lower()):
# check if we have the key in our buffer
index = self.headerbuffer.find('\r\n\r\n') + 4
# determine how much of the 8 byte key we have
read = len(self.headerbuffer) - index
# do we have all the 8 bytes we need?
if read < 8:
self.headertoread = 8 - read
self.readdraftkey = True
if read > 0:
self.draftkey += self.headerbuffer[index:index+read]
else:
# get the key
self.draftkey += self.headerbuffer[index:index+8]
# complete hixie handshake
self.handshake_hixie76()
# handshake rfc 6455
elif self.request.headers.has_key('Sec-WebSocket-Key'.lower()):
key = self.request.headers['Sec-WebSocket-Key'.lower()]
hStr = self.handshakeStr % { 'acceptstr' : base64.b64encode(hashlib.sha1(key + self.GUIDStr).digest()) }
self.sendBuffer(hStr)
self.handshaked = True
self.headerbuffer = ''
try:
self.handleConnected()
except:
pass
# hixie 75
else:
self.handshake_hixie75()
#raise Exception('Sec-WebSocket-Key does not exist')
# remote connection has been closed
else:
raise Exception("remote socket closed")
# else do normal data
else:
data = self.client.recv(2048)
if data:
for val in data:
if self.hixie76 is False:
self.parseMessage(ord(val))
else:
self.parseMessage_hixie76(ord(val))
else:
raise Exception("remote socket closed")
def handshake_hixie75(self):
typestr = 'ws'
if self.usingssl is True:
typestr = 'wss'
response = self.hixie75handshakedStr % { 'type' : typestr, 'origin' : self.request.headers['Origin'.lower()], 'host' : self.request.headers['Host'.lower()], 'location' : self.request.path }
self.sendBuffer(response)
self.handshaked = True
self.headerbuffer = ''
self.hixie76 = True
try:
self.handleConnected()
except:
pass
def handshake_hixie76(self):
k1 = self.request.headers['Sec-WebSocket-Key1'.lower()]
k2 = self.request.headers['Sec-WebSocket-Key2'.lower()]
spaces1 = k1.count(" ")
spaces2 = k2.count(" ")
num1 = int("".join([c for c in k1 if c.isdigit()])) / spaces1
num2 = int("".join([c for c in k2 if c.isdigit()])) / spaces2
key = ''
key += struct.pack('>I', num1)
key += struct.pack('>I', num2)
key += self.draftkey
typestr = 'ws'
if self.usingssl is True:
typestr = 'wss'
response = self.hixiehandshakedStr % { 'type' : typestr, 'origin' : self.request.headers['Origin'.lower()], 'host' : self.request.headers['Host'.lower()], 'location' : self.request.path }
self.sendBuffer(response)
self.sendBuffer(hashlib.md5(key).digest())
self.handshaked = True
self.hixie76 = True
self.headerbuffer = ''
try:
self.handleConnected()
except:
pass
def sendClose(self):
msg = bytearray()
if self.hixie76 is False:
msg.append(0x88)
msg.append(0x00)
self.sendBuffer(msg)
else:
pass
def sendBuffer(self, buff):
size = len(buff)
tosend = size
index = 0
while tosend > 0:
try:
# i should be able to send a bytearray
sent = self.client.send(str(buff[index:size]))
if sent == 0:
raise RuntimeError("socket connection broken")
index += sent
tosend -= sent
except socket.error as e:
# if we have full buffers then wait for them to drain and try again
if e.errno == errno.EAGAIN:
time.sleep(0.001)
else:
raise e
#if s is a string then websocket TEXT is sent else BINARY
def sendMessage(self, s):
if self.hixie76 is False:
header = bytearray()
isString = isinstance(s, str)
if isString is True:
header.append(0x81)
else:
header.append(0x82)
b2 = 0
length = len(s)
if length <= 125:
b2 |= length
header.append(b2)
elif length >= 126 and length <= 65535:
b2 |= 126
header.append(b2)
header.extend(struct.pack("!H", length))
else:
b2 |= 127
header.append(b2)
header.extend(struct.pack("!Q", length))
if length > 0:
self.sendBuffer(header + s)
else:
self.sendBuffer(header)
header = None
else:
msg = bytearray()
msg.append(0)
if len(s) > 0:
msg.extend(str(s).encode("UTF8"))
msg.append(0xFF)
self.sendBuffer(msg)
msg = None
def parseMessage_hixie76(self, byte):
if self.state == self.HEADERB1:
if byte == 0:
self.state = self.PAYLOAD
self.data = bytearray()
elif self.state == self.PAYLOAD:
if byte == 0xFF:
self.opcode = 1
self.length = len(self.data)
try:
self.handlePacket()
finally:
self.data = None
self.state = self.HEADERB1
else :
self.data.append(byte)
# if length exceeds allowable size then we except and remove the connection
if len(self.data) >= self.maxpayload:
raise Exception('payload exceeded allowable size')
def parseMessage(self, byte):
# read in the header
if self.state == self.HEADERB1:
# fin
self.fin = (byte & 0x80)
# get opcode
self.opcode = (byte & 0x0F)
self.state = self.HEADERB2
elif self.state == self.HEADERB2:
mask = byte & 0x80
length = byte & 0x7F
if mask == 128:
self.hasmask = True
else:
self.hasmask = False
if length <= 125:
self.length = length
# if we have a mask we must read it
if self.hasmask is True:
self.maskarray = bytearray()
self.state = self.MASK
else:
# if there is no mask and no payload we are done
if self.length <= 0:
try:
self.handlePacket()
finally:
self.state = self.HEADERB1
self.data = None
# we have no mask and some payload
else:
self.index = 0
self.data = bytearray()
self.state = self.PAYLOAD
elif length == 126:
self.lengtharray = bytearray()
self.state = self.LENGTHSHORT
elif length == 127:
self.lengtharray = bytearray()
self.state = self.LENGTHLONG
elif self.state == self.LENGTHSHORT:
self.lengtharray.append(byte)
if len(self.lengtharray) > 2:
raise Exception('short length exceeded allowable size')
if len(self.lengtharray) == 2:
self.length = struct.unpack_from('!H', str(self.lengtharray))[0]
if self.hasmask is True:
self.maskarray = bytearray()
self.state = self.MASK
else:
# if there is no mask and no payload we are done
if self.length <= 0:
try:
self.handlePacket()
finally:
self.state = self.HEADERB1
self.data = None
# we have no mask and some payload
else:
self.index = 0
self.data = bytearray()
self.state = self.PAYLOAD
elif self.state == self.LENGTHLONG:
self.lengtharray.append(byte)
if len(self.lengtharray) > 8:
raise Exception('long length exceeded allowable size')
if len(self.lengtharray) == 8:
self.length = struct.unpack_from('!Q', str(self.lengtharray))[0]
if self.hasmask is True:
self.maskarray = bytearray()
self.state = self.MASK
else:
# if there is no mask and no payload we are done
if self.length <= 0:
try:
self.handlePacket()
finally:
self.state = self.HEADERB1
self.data = None
# we have no mask and some payload
else:
self.index = 0
self.data = bytearray()
self.state = self.PAYLOAD
# MASK STATE
elif self.state == self.MASK:
self.maskarray.append(byte)
if len(self.maskarray) > 4:
raise Exception('mask exceeded allowable size')
if len(self.maskarray) == 4:
# if there is no mask and no payload we are done
if self.length <= 0:
try:
self.handlePacket()
finally:
self.state = self.HEADERB1
self.data = None
# we have no mask and some payload
else:
self.index = 0
self.data = bytearray()
self.state = self.PAYLOAD
# PAYLOAD STATE
elif self.state == self.PAYLOAD:
if self.hasmask is True:
self.data.append( byte ^ self.maskarray[self.index % 4] )
else:
self.data.append( byte )
# if length exceeds allowable size then we except and remove the connection
if len(self.data) >= self.maxpayload:
raise Exception('payload exceeded allowable size')
# check if we have processed length bytes; if so we are done
if (self.index+1) == self.length:
try:
self.handlePacket()
finally:
self.state = self.HEADERB1
self.data = None
else:
self.index += 1
class SimpleWebSocketServer(object):
def __init__(self, host, port, websocketclass):
self.websocketclass = websocketclass
self.serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.serversocket.bind((host, port))
self.serversocket.listen(5)
self.connections = {}
self.listeners = [self.serversocket]
def decorateSocket(self, sock):
return sock
def constructWebSocket(self, sock, address):
return self.websocketclass(self, sock, address)
def close(self):
self.serversocket.close()
for conn in self.connections.itervalues():
try:
conn.handleClose()
except:
pass
conn.close()
def serveforever(self):
while True:
try:
rList, wList, xList = select(self.listeners, [], self.listeners, 1)
for ready in rList:
if ready == self.serversocket:
try:
sock, address = self.serversocket.accept()
newsock = self.decorateSocket(sock)
newsock.setblocking(0)
fileno = newsock.fileno()
self.listeners.append(fileno)
self.connections[fileno] = self.constructWebSocket(newsock, address)
except Exception as n:
#logging.debug(str(address) + ' ' + str(n))
if sock is not None:
sock.close()
else:
client = self.connections[ready]
try:
client.handleData()
except Exception as n:
#logging.debug(str(client.address) + ' ' + str(n))
try:
client.handleClose()
except:
pass
client.close()
del self.connections[ready]
self.listeners.remove(ready)
for failed in xList:
if failed == self.serversocket:
self.close()
raise Exception("server socket failed")
else:
client = self.connections[failed]
try:
client.handleClose()
except:
pass
client.close()
del self.connections[failed]
self.listeners.remove(failed)
except:
break
class SimpleSSLWebSocketServer(SimpleWebSocketServer):
def __init__(self, host, port, websocketclass, certfile, keyfile, version = ssl.PROTOCOL_TLSv1):
SimpleWebSocketServer.__init__(self, host, port, websocketclass)
self.cerfile = certfile
self.keyfile = keyfile
self.version = version
def close(self):
super(SimpleSSLWebSocketServer, self).close()
def decorateSocket(self, sock):
sslsock = ssl.wrap_socket(sock,
server_side=True,
certfile=self.cerfile,
keyfile=self.keyfile,
ssl_version=self.version)
return sslsock
def constructWebSocket(self, sock, address):
ws = self.websocketclass(self, sock, address)
ws.usingssl = True
return ws
def serveforever(self):
super(SimpleSSLWebSocketServer, self).serveforever()

View File

@@ -14,6 +14,27 @@ settings_dic = {}
adult_setting = {}
def get_addon_version(linea_inicio=0, total_lineas=2):
'''
Devuelve el número de de versión del addon, obtenido desde el archivo addon.xml
'''
path = os.path.join(get_runtime_path(), "addon.xml")
f = open(path, "rb")
data = []
for x, line in enumerate(f):
if x < linea_inicio: continue
if len(data) == total_lineas: break
data.append(line)
f.close()
data1 = "".join(data)
# <addon id="plugin.video.alfa" name="Alfa" version="2.5.21" provider-name="Alfa Addon">
aux = re.findall('<addon id="plugin.video.alfa" name="Alfa" version="([^"]+)"', data1, re.MULTILINE | re.DOTALL)
version = "???"
if len(aux) > 0:
version = aux[0]
return version
def get_platform(full_version=False):
# full_version solo es util en xbmc/kodi
ret = {
@@ -385,10 +406,8 @@ 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.po")
load_settings()
TRANSLATION_FILE_PATH = os.path.join(get_runtime_path(), "resources", "language", settings_dic["mediaserver_language"], "strings.po")
# modo adulto:
# sistema actual 0: Nunca, 1:Siempre, 2:Solo hasta que se reinicie sesión

View File

@@ -20,7 +20,6 @@ class fileserver(Controller):
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()

View File

@@ -15,14 +15,9 @@ from platformcode import config
from core.item import Item
from core.tmdb import Tmdb
from platformcode import launcher, logger
from core import filetools
# <addon id="plugin.video.alfa" name="Alfa" version="2.3.0" provider-name="Alfa Addon">
data = filetools.read(filetools.join(config.get_runtime_path(), "addon.xml"))
aux = re.findall('<addon id="plugin.video.alfa" name="Alfa" version="([^"]+)"', data, re.MULTILINE | re.DOTALL)
version = "???"
if len(aux) > 0:
version = aux[0]
## Obtiene la versión del addon
version = config.get_addon_version()
class html(Controller):
pattern = re.compile("##")
@@ -33,7 +28,10 @@ class html(Controller):
self.platformtools = platform(self)
self.data = {}
if self.handler:
self.client_ip = handler.client.getpeername()[0]
if hasattr(handler, "client"):
self.client_ip = handler.client.getpeername()[0]
else:
self.client_ip = handler.client_address[0]
self.send_message({"action": "connect",
"data": {"version": "Alfa %s" % version,
"date": "--/--/----"}})
@@ -110,7 +108,7 @@ class platform(Platformtools):
thumbnail=channelselector.get_thumb("back.png", "banner_")))
else:
itemlist.insert(0, Item(title="Atrás", action="go_back",
thumbnail=channelselector.get_thumb("back.png")))
thumbnail=channelselector.get_thumb("back.png", "banner_")))
JsonData = {}
JsonData["action"] = "EndItems"
@@ -124,17 +122,9 @@ class platform(Platformtools):
# 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)
if not item.thumbnail and item.action == "search": item.thumbnail = channelselector.get_thumb("search.png", "banner_")
#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", "banner_")
# 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_"):

View File

@@ -94,7 +94,7 @@ function focus_element(element) {
function image_error(thumbnail) {
var src = thumbnail.src;
if (thumbnail.src.indexOf(domain) == 0) {
thumbnail.src = "https://github.com/alfa-addon/addon/raw/master/plugin.video.alfa/resources/media/general/default/thumb_folder.png";
thumbnail.src = "https://github.com/alfa-addon/addon/raw/master/plugin.video.alfa/resources/media/themes/default/thumb_folder.png"
}
else {
thumbnail.src = domain + "/proxy/" + encodeURIComponent(btoa(thumbnail.src));

View File

@@ -30,7 +30,7 @@
<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}'
websocket_host = 'ws://' + window.location.host
</script>
</head>

View File

@@ -3,11 +3,11 @@
<category label="General">
<setting label="Puertos" type="lsep" />
<setting default="8080" id="server.port" label="Puerto HTTP" type="number"/>
<setting default="8081" id="websocket.port" label="Puerto WebSocket" type="number"/>
<setting type="sep"/>
<setting id="default_action" type="enum" lvalues="30006|30007|30008" label="30005" default="0"/>
<setting id="thumbnail_type" type="enum" lvalues="30011|30012|30200" label="30010" default="2"/>
<setting id="channel_language" type="labelenum" values="all|cast|lat" label="30019" default="all"/>
<setting id="mediaserver_language" type="labelenum" values="English|Spanish|Spanish (Argentina)|Spanish (Mexico)|Italian" label="70277" default="Spanish" />
<setting id="channel_language" type="labelenum" values="all|cast|lat|it" label="30019" default="all"/>
<setting id="debug" type="bool" label="30003" default="false"/>
<setting label="Uso de servidores" type="lsep"/>
<setting id="resolve_priority" type="enum" label="Método prioritario" values="Free primero|Premium primero|Debriders primero" default="0"/>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="plugin.video.alfa" name="Alfa" version="2.5.21" provider-name="Alfa Addon">
<addon id="plugin.video.alfa" name="Alfa" version="2.5.23" provider-name="Alfa Addon">
<requires>
<import addon="xbmc.python" version="2.1.0"/>
<import addon="script.module.libtorrent" optional="true"/>
@@ -22,14 +22,14 @@
» grantorrent » descargas2020
» torrentlocura » torrentrapid
» tumejortorrent » tvsinpagar
» mispelisyseries » playview
» clipwatching » cloudvideo
» filevideo » upvid
» vidzella » vivo
» watchvideo » vshare
» mispelisyseries » mejortorrent
» allcalidad » poseidonhd
» tvvip » animeflv
» areadocumental » cuevana3
» newpct1 » peliculasdk
» animeyt » pelispedia
¤ arreglos internos y actualizado la versión mediaserver
¤ Agradecimientos a @alaquepasa y @Pixo506 por colaborar con ésta versión.
¤ Agradecimientos al equipo ISOD y @alaquepasa por colaborar con ésta versión.
</news>
<description lang="es">Navega con Kodi por páginas web para ver sus videos de manera fácil.</description>

View File

@@ -147,10 +147,12 @@ def findvideos(item):
match = scrapertools.find_multiple_matches(bloque, '(?is)(?:iframe|script) .*?src="([^"]+)')
for url in match:
titulo = "Ver en: %s"
text_color = "white"
if "goo.gl" in url:
url = httptools.downloadpage(url, follow_redirects=False, only_headers=True).headers.get("location", "")
if "youtube" in url:
titulo = "[COLOR = yellow]Ver trailer: %s[/COLOR]"
titulo = "Ver trailer: %s"
text_color = "yellow"
if "ad.js" in url or "script" in url or "jstags.js" in url:
continue
elif "vimeo" in url:
@@ -158,6 +160,7 @@ def findvideos(item):
itemlist.append(
item.clone(channel = item.channel,
action = "play",
text_color = text_color,
title = titulo,
url = url
))

View File

@@ -1,9 +1,7 @@
# -*- coding: utf-8 -*-
import re
import time
import urlparse
import urllib
from channels import renumbertools
from core import httptools
@@ -18,13 +16,10 @@ HOST = "https://animeflv.net/"
def mainlist(item):
logger.info()
itemlist = list()
itemlist.append(Item(channel=item.channel, action="novedades_episodios", title="Últimos episodios", url=HOST))
itemlist.append(Item(channel=item.channel, action="novedades_anime", title="Últimos animes", url=HOST))
itemlist.append(Item(channel=item.channel, action="listado", title="Animes", url=HOST + "browse?order=title"))
itemlist.append(Item(channel=item.channel, title="Buscar por:"))
itemlist.append(Item(channel=item.channel, action="search", title=" Título"))
itemlist.append(Item(channel=item.channel, action="search_section", title=" Género", url=HOST + "browse",
@@ -35,9 +30,7 @@ def mainlist(item):
extra="year"))
itemlist.append(Item(channel=item.channel, action="search_section", title=" Estado", url=HOST + "browse",
extra="status"))
itemlist = renumbertools.show_option(item.channel, itemlist)
return itemlist
@@ -48,36 +41,29 @@ def search(item, texto):
texto = texto.replace(" ", "+")
post = "value=%s" % texto
data = httptools.downloadpage(item.url, post=post).data
try:
dict_data = jsontools.load(data)
for e in dict_data:
if e["id"] != e["last_id"]:
_id = e["last_id"]
else:
_id = e["id"]
url = "%sanime/%s/%s" % (HOST, _id, e["slug"])
title = e["title"]
thumbnail = "%suploads/animes/covers/%s.jpg" % (HOST, e["id"])
new_item = item.clone(action="episodios", title=title, url=url, thumbnail=thumbnail)
if e["type"] != "movie":
new_item.show = title
new_item.context = renumbertools.context(item)
else:
new_item.contentType = "movie"
new_item.contentTitle = title
itemlist.append(new_item)
except:
import sys
for line in sys.exc_info():
logger.error("%s" % line)
return []
return itemlist
@@ -88,39 +74,30 @@ def search_section(item):
data = re.sub(r"\n|\r|\t|\s{2}|-\s", "", data)
patron = 'id="%s_select"[^>]+>(.*?)</select>' % item.extra
data = scrapertools.find_single_match(data, patron)
matches = re.compile('<option value="([^"]+)">(.*?)</option>', re.DOTALL).findall(data)
for _id, title in matches:
url = "%s?%s=%s&order=title" % (item.url, item.extra, _id)
itemlist.append(Item(channel=item.channel, action="listado", title=title, url=url,
context=renumbertools.context(item)))
return itemlist
def newest(categoria):
itemlist = []
if categoria == 'anime':
itemlist = novedades_episodios(Item(url=HOST))
return itemlist
def novedades_episodios(item):
logger.info()
data = httptools.downloadpage(item.url).data
data = re.sub(r"\n|\r|\t|\s{2}|-\s", "", data)
data = scrapertools.find_single_match(data, '<h2>Últimos episodios</h2>.+?<ul class="ListEpisodios[^>]+>(.*?)</ul>')
matches = re.compile('<a href="([^"]+)"[^>]+>.+?<img src="([^"]+)".+?"Capi">(.*?)</span>'
'<strong class="Title">(.*?)</strong>', re.DOTALL).findall(data)
itemlist = []
for url, thumbnail, str_episode, show in matches:
try:
episode = int(str_episode.replace("Episodio ", ""))
except ValueError:
@@ -135,28 +112,21 @@ def novedades_episodios(item):
new_item = Item(channel=item.channel, action="findvideos", title=title, url=url, show=show, thumbnail=thumbnail,
fulltitle=title)
itemlist.append(new_item)
return itemlist
def novedades_anime(item):
logger.info()
data = httptools.downloadpage(item.url).data
data = re.sub(r"\n|\r|\t|\s{2}|-\s", "", data)
data = scrapertools.find_single_match(data, '<ul class="ListAnimes[^>]+>(.*?)</ul>')
matches = re.compile('href="([^"]+)".+?<img src="([^"]+)".+?<span class=.+?>(.*?)</span>.+?<h3.+?>(.*?)</h3>.+?'
'(?:</p><p>(.*?)</p>.+?)?</article></li>', re.DOTALL).findall(data)
itemlist = []
for url, thumbnail, _type, title, plot in matches:
url = urlparse.urljoin(HOST, url)
thumbnail = urlparse.urljoin(HOST, thumbnail)
new_item = Item(channel=item.channel, action="episodios", title=title, url=url, thumbnail=thumbnail,
fulltitle=title, plot=plot)
if _type != "Película":
@@ -165,173 +135,75 @@ def novedades_anime(item):
else:
new_item.contentType = "movie"
new_item.contentTitle = title
itemlist.append(new_item)
return itemlist
def listado(item):
logger.info()
data = httptools.downloadpage(item.url).data
data = re.sub(r"\n|\r|\t|\s{2}|-\s", "", data)
url_pagination = scrapertools.find_single_match(data, '<li class="active">.*?</li><li><a href="([^"]+)">')
data = scrapertools.find_multiple_matches(data, '<ul class="ListAnimes[^>]+>(.*?)</ul>')
data = "".join(data)
matches = re.compile('<a href="([^"]+)">.+?<img src="([^"]+)".+?<span class=.+?>(.*?)</span>.+?<h3.*?>(.*?)</h3>'
'.*?</p><p>(.*?)</p>', re.DOTALL).findall(data)
itemlist = []
for url, thumbnail, _type, title, plot in matches:
url = urlparse.urljoin(HOST, url)
thumbnail = urlparse.urljoin(HOST, thumbnail)
new_item = Item(channel=item.channel, action="episodios", title=title, url=url, thumbnail=thumbnail,
fulltitle=title, plot=plot)
if _type == "Anime":
new_item.show = title
new_item.context = renumbertools.context(item)
else:
new_item.contentType = "movie"
new_item.contentTitle = title
itemlist.append(new_item)
if url_pagination:
url = urlparse.urljoin(HOST, url_pagination)
title = ">> Pagina Siguiente"
itemlist.append(Item(channel=item.channel, action="listado", title=title, url=url))
return itemlist
def episodios(item):
logger.info()
itemlist = []
data = httptools.downloadpage(item.url).data
data = re.sub(r"\n|\r|\t|\s{2}|-\s", "", data)
# fix para renumbertools
item.show = scrapertools.find_single_match(data, '<h1 class="Title">(.*?)</h1>')
if item.plot == "":
item.plot = scrapertools.find_single_match(data, 'Description[^>]+><p>(.*?)</p>')
matches = re.compile('href="([^"]+)"><figure><img class="[^"]+" data-original="([^"]+)".+?</h3>'
'\s*<p>(.*?)</p>', re.DOTALL).findall(data)
if matches:
for url, thumb, title in matches:
title = title.strip()
url = urlparse.urljoin(item.url, url)
# thumbnail = item.thumbnail
try:
episode = int(scrapertools.find_single_match(title, "^.+?\s(\d+)$"))
except ValueError:
season = 1
episode = 1
else:
season, episode = renumbertools.numbered_for_tratk(item.channel, item.show, 1, episode)
title = "%sx%s : %s" % (season, str(episode).zfill(2), item.title)
itemlist.append(item.clone(action="findvideos", title=title, url=url, thumbnail=thumb, fulltitle=title,
fanart=item.thumbnail, contentType="episode"))
else:
# no hay thumbnail
matches = re.compile('<a href="(/ver/[^"]+)"[^>]+>(.*?)<', re.DOTALL).findall(data)
for url, title in matches:
title = title.strip()
url = urlparse.urljoin(item.url, url)
thumb = item.thumbnail
try:
episode = int(scrapertools.find_single_match(title, "^.+?\s(\d+)$"))
except ValueError:
season = 1
episode = 1
else:
season, episode = renumbertools.numbered_for_tratk(item.channel, item.show, 1, episode)
title = "%sx%s : %s" % (season, str(episode).zfill(2), item.title)
itemlist.append(item.clone(action="findvideos", title=title, url=url, thumbnail=thumb, fulltitle=title,
fanart=item.thumbnail, contentType="episode"))
info = eval(scrapertools.find_single_match(data, 'anime_info = (.*?);'))
episodes = eval(scrapertools.find_single_match(data, 'var episodes = (.*?);'))
for episode in episodes:
url = '%s/ver/%s/%s-%s' % (HOST, episode[1], info[2], episode[0])
title = '1x%s Episodio %s' % (episode[0], episode[0])
itemlist.append(item.clone(title=title, url=url, action='findvideos', show=info[1]))
itemlist = itemlist[::-1]
if config.get_videolibrary_support() and len(itemlist) > 0:
itemlist.append(Item(channel=item.channel, title="Añadir esta serie a la videoteca",
action="add_serie_to_library", extra="episodios"))
return itemlist
def findvideos(item):
logger.info()
itemlist = []
data = re.sub(r"\n|\r|\t|\s{2}|-\s", "", httptools.downloadpage(item.url).data)
list_videos = scrapertools.find_multiple_matches(data, 'video\[\d\]\s=\s\'<iframe.+?src="([^"]+)"')
download_list = scrapertools.find_multiple_matches(data, 'href="http://ouo.io/s/y0d65LCP\?s=([^"]+)"')
for i in download_list:
list_videos.append(urllib.unquote_plus(i))
aux_url = []
cldup = False
for e in list_videos:
url_api = "https://s3.animeflv.com/check.php?server=%s&v=%s"
# izanagi, yourupload, hyperion
if e.startswith("https://s3.animeflv.com/embed"):
server, v = scrapertools.find_single_match(e, 'server=([^&]+)&v=(.*?)$')
data = httptools.downloadpage(url_api % (server, v)).data.replace("\\", "")
if '{"error": "Por favor intenta de nuevo en unos segundos", "sleep": 3}' in data:
time.sleep(3)
data = httptools.downloadpage(url_api % (server, v)).data.replace("\\", "")
if server != "hyperion":
url = scrapertools.find_single_match(data, '"file":"([^"]+)"')
if url:
itemlist.append(item.clone(title="Enlace encontrado en %s" % server, url=url, action="play"))
else:
# pattern = '"direct":"([^"]+)"'
# url = scrapertools.find_single_match(data, pattern)
# itemlist.append(item.clone(title="Enlace encontrado en %s" % server, url=url, action="play"))
pattern = '"label":([^,]+),"type":"video/mp4","file":"([^"]+)"'
matches = scrapertools.find_multiple_matches(data, pattern)
video_urls = []
for label, url in matches:
video_urls.append([label, "mp4", url])
if video_urls:
video_urls.sort(key=lambda u: int(u[0]))
itemlist.append(item.clone(title="Enlace encontrado en %s" % server, action="play",
video_urls=video_urls))
download_list = scrapertools.find_multiple_matches(data, 'video\[\d+\] = \'<iframe .*?src="(.*?)"')
for url in download_list:
data = httptools.downloadpage(url).data
if 'izanagi' in url:
new_url = url.replace('embed', 'check')
new_data = httptools.downloadpage(new_url).data
url = scrapertools.find_single_match(new_data, '"file":"(.*?)"')
else:
if e.startswith("https://cldup.com") and not cldup:
itemlist.append(item.clone(title="Enlace encontrado en Cldup", action="play", url=e))
cldup = True
aux_url.append(e)
itemlist.extend(servertools.find_video_items(data=",".join(aux_url)))
for videoitem in itemlist:
videoitem.fulltitle = item.fulltitle
videoitem.channel = item.channel
videoitem.thumbnail = item.thumbnail
url = scrapertools.find_single_match(data, 'var redir = "(.*?)"')
if url != '':
url = url.replace("\\","")
itemlist.append(item.clone(title='%s', url=url, action='play'))
itemlist = servertools.get_servers_itemlist(itemlist, lambda i: i.title % i.server)
return itemlist

View File

@@ -11,7 +11,7 @@ from core.item import Item
from core import tmdb
from platformcode import config,logger
import gktools
import gktools, random, time, urllib
__modo_grafico__ = config.get_setting('modo_grafico', 'animeyt')
@@ -160,20 +160,24 @@ def findvideos(item):
data = httptools.downloadpage(item.url).data
data = re.sub(r"\n|\r|\t|&nbsp;|<br>", "", data)
# ~ patron = 'Player\("(.*?)"'
patron = 'iframe src="([^"]*)"'
from collections import OrderedDict # cambiado dict por OrderedDict para mantener el mismo orden que en la web
matches = scrapertools.find_multiple_matches(data, patron)
matches = scrapertools.find_multiple_matches(data, '<li><a id="mirror(\d*)" class="link-veranime[^"]*" href="[^"]*">([^<]*)')
d_links = OrderedDict(matches)
matches = scrapertools.find_multiple_matches(data, 'if \(mirror == (\d*)\).*?iframe src="([^"]*)"')
d_frames = OrderedDict(matches)
for k in d_links:
if k in d_frames and d_frames[k] != '':
tit = scrapertools.find_single_match(d_frames[k], '/([^\./]*)\.php\?')
if tit == '':
tit = 'mega' if 'mega.nz/' in d_frames[k] else 'dailymotion' if 'dailymotion.com/' in d_frames[k] else'noname'
if tit == 'id' and 'yourupload.com/' in d_frames[k]: tit = 'yourupload'
title = 'Opción %s (%s)' % (d_links[k], tit)
itemlist.append(item.clone(channel=item.channel, folder=False, title=title, action="play", url=d_frames[k], referer=item.url))
for url in matches:
title = scrapertools.find_single_match(url, '/([^\.]*)\.php\?')
# ~ title = 'PDT'
# ~ if "cldup" in url:
# ~ title = "Opcion Cldup"
# ~ if "chumi" in url:
# ~ title = "Opcion Chumi"
if title == 'rakuten': # de momento es el único resuelto
itemlist.append(item.clone(channel=item.channel, folder=False, title=title, action="play", url=url, referer=item.url))
if item.extra != "library":
if config.get_videolibrary_support() and item.extra:
@@ -186,14 +190,321 @@ def play(item):
logger.info()
itemlist = []
if 'https://s2.animeyt.tv/rakuten.php?' in item.url:
itemlist = gktools.gk_play(item)
if item.url.startswith('https://www.dailymotion.com/'):
itemlist.append(item.clone(url=item.url, server='dailymotion'))
elif item.url.startswith('https://mega.nz/'):
itemlist.append(item.clone(url=item.url.replace('embed',''), server='mega'))
elif item.url.startswith('https://s2.animeyt.tv/rakuten.php?'):
# 1- Descargar
data, ck = gktools.get_data_and_cookie(item)
# 2- Calcular datos
gsv = scrapertools.find_single_match(data, '<meta name="google-site-verification" content="([^"]*)"')
if not gsv: return itemlist
suto = gktools.md5_dominio(item.url)
sufijo = '3497510'
token = gktools.generar_token('"'+gsv+'"', suto+'yt'+suto+sufijo)
link, subtitle = gktools.get_play_link_id(data, item.url)
url = 'https://s2.animeyt.tv/rakuten/plugins/gkpluginsphp.php'
post = "link=%s&token=%s" % (link, token)
# 3- Descargar json
data = gktools.get_data_json(url, post, ck, item.url)
# 4- Extraer enlaces
itemlist = gktools.extraer_enlaces_json(data, item.referer, subtitle)
elif item.url.startswith('https://s3.animeyt.tv/amz.php?'):
# 1- Descargar
data, ck = gktools.get_data_and_cookie(item)
# 2- Calcular datos
gsv = scrapertools.find_single_match(data, '<meta name="Animeyt-Token" content="([^"]*)"')
v_token = scrapertools.find_single_match(data, "var v_token='([^']*)'")
if not gsv or not v_token: return itemlist
suto = gktools.md5_dominio(item.url)
sufijo = '9457610'
token = gktools.generar_token('"'+gsv+'"', suto+'yt'+suto+sufijo)
url = 'https://s3.animeyt.tv/amz_animeyts.php'
post = "v_token=%s&token=%s&handler=%s" % (v_token, token, 'Animeyt')
# 3- Descargar json
data = gktools.get_data_json(url, post, ck, item.url)
# 4- Extraer enlaces
itemlist = gktools.extraer_enlaces_json(data, item.referer)
elif item.url.startswith('https://s2.animeyt.tv/lola.php?'):
# 1- Descargar
data, ck = gktools.get_data_and_cookie(item)
# 2- Calcular datos
gsv = scrapertools.find_single_match(data, '<meta name="Animeyt-Token" content="([^"]*)"')
s_cd, s_file = scrapertools.find_single_match(data, "var cd='([^']*)';\s*var file='([^']*)'")
if not gsv or not s_cd or not s_file: return itemlist
suto = gktools.md5_dominio(item.url)
sufijo = '8134976'
token = gktools.generar_token('"'+gsv+'"', suto+'yt'+suto+sufijo)
url = 'https://s2.animeyt.tv/minha_animeyt.php'
post = "cd=%s&file=%s&token=%s&handler=%s" % (s_cd, s_file, token, 'Animeyt')
# 3- Descargar json
data = gktools.get_data_json(url, post, ck, item.url)
# 4- Extraer enlaces
itemlist = gktools.extraer_enlaces_json(data, item.referer)
elif item.url.startswith('https://s4.animeyt.tv/chumi.php?'): #https://s4.animeyt.tv/chumi.php?cd=3481&file=4
# 1- Descargar
data, ck = gktools.get_data_and_cookie(item)
# 2- Calcular datos
gsv = scrapertools.find_single_match(data, '<meta name="Animeyt-Token" content="([^"]*)"')
s_cd, s_file = scrapertools.find_single_match(item.url, '\?cd=([^&]*)&file=([^&]*)')
if not gsv or not s_cd or not s_file: return itemlist
ip = gktools.toHex(gsv) + str(1000000 + random.randint(0,9000000)) + str(100000 + random.randint(0,900000))
gsv_bis = gktools.transforma_gsv(gsv, '159753')
p1 = '1705f5652bb6546ab3643ff698e' + gsv[-5:]
p2 = '8388ca3fd07' + gsv[-5:] + gsv_bis
texto = gktools.toHex(gktools.encode_rijndael(gsv, p1, p2))
suto = gktools.md5_dominio(item.url)
sufijo = '147268278' + gsv[-5:]
prefijo = gsv[:-5] + gsv_bis
token = gktools.generar_token('"'+texto+'"', prefijo+suto+'yt'+suto+sufijo)
archive = gktools.toHex(token)
url = 'https://s4.animeyt.tv/minha/minha_animeyt.php'
post = "cd=%s&id=%s&archive=%s&ip=%s&Japan=%s" % (s_cd, s_file, archive, ip, 'Asia')
# 3- Descargar json
data = gktools.get_data_json(url, post, ck, item.url)
# 4- Extraer enlaces
itemlist = gktools.extraer_enlaces_json(data, item.referer)
elif item.url.startswith('https://s3.animeyt.tv/mega.php?'): #https://s3.animeyt.tv/mega.php?v=WmpHMEVLVTNZZktyaVAwai9sYzhWV1ZRTWh0WTZlNGZ3VzFVTXhMTkx2NGlOMjRYUHhZQlMvaUFsQlJFbHBVTA==
# 1- Descargar
data, ck = gktools.get_data_and_cookie(item)
# 2- Calcular datos
gsv = scrapertools.find_single_match(data, '<meta name="Animeyt-Token" content="([^"]*)"')
s_v = scrapertools.find_single_match(item.url, '\?v=([^&]*)')
if not gsv or not s_v: return itemlist
ip = gktools.toHex(gsv) + str(1000000 + random.randint(0,9000000)) + str(100000 + random.randint(0,900000))
gsv_bis = gktools.transforma_gsv(gsv, '159753')
p1 = '1705f5652bb6546ab3643ff698e' + gsv[-5:]
p2 = '8388ca3fd07' + gsv[-5:] + gsv_bis
texto = gktools.toHex(gktools.encode_rijndael(gsv, p1, p2))
suto = gktools.md5_dominio(item.url)
sufijo = '147268278' + gsv[-5:]
prefijo = gsv[:-5] + gsv_bis
token = gktools.generar_token('"'+texto+'"', prefijo+suto+'yt'+suto+sufijo)
archive = gktools.toHex(token)
url = 'https://s3.animeyt.tv/mega_animeyts.php'
post = "v=%s&archive=%s&referer=%s&ip=%s&Japan=%s" % (s_v, archive, item.url, ip, 'Asia')
# 3- Descargar json
data = gktools.get_data_json(url, post, ck, item.url)
# 4- Extraer enlaces
itemlist = gktools.extraer_enlaces_json(data, item.referer)
elif item.url.startswith('https://s2.animeyt.tv/naruto/naruto.php?'): #https://s2.animeyt.tv/naruto/naruto.php?id=3477&file=11.mp4
# 1- Descargar
data, ck = gktools.get_data_and_cookie(item)
# 2- Calcular datos
gsv = scrapertools.find_single_match(data, '<meta name="Animeyt-Token" content="([^"]*)"')
s_id, s_file = scrapertools.find_single_match(item.url, '\?id=([^&]*)&file=([^&]*)')
if not gsv or not s_id or not s_file: return itemlist
ip = gktools.toHex(gsv) + str(1000000 + random.randint(0,9000000)) + str(100000 + random.randint(0,900000))
gsv_bis = gktools.transforma_gsv(gsv, '159753')
p1 = '1705f5652bb6546ab3643ff698e' + gsv[-5:]
p2 = '8388ca3fd07' + gsv[-5:] + gsv_bis
texto = gktools.toHex(gktools.encode_rijndael(gsv, p1, p2))
suto = gktools.md5_dominio(item.url)
sufijo = '147268278' + gsv[-5:]
prefijo = gsv[:-5] + gsv_bis
token = gktools.generar_token('"'+texto+'"', prefijo+suto+'yt'+suto+sufijo)
archive = gktools.toHex(token)
url = 'https://s2.animeyt.tv/naruto/narutos_animeyt.php'
post = "id=%s&file=%s&archive=%s&referer=%s&ip=%s&Japan=%s" % (s_id, s_file, archive, urllib.quote(item.url), ip, 'Asia')
# 3- Descargar json
data = gktools.get_data_json(url, post, ck, item.url)
# 4- Extraer enlaces
itemlist = gktools.extraer_enlaces_json(data, item.referer)
elif item.url.startswith('https://s4.animeyt.tv/facebook.php?'): #https://s4.animeyt.tv/facebook.php?cd=3481&id=4
# 1- Descargar
data, ck = gktools.get_data_and_cookie(item)
# 2- Calcular datos
gsv = scrapertools.find_single_match(data, '<meta name="Animeyt-Token" content="([^"]*)"')
s_cd, s_id = scrapertools.find_single_match(item.url, '\?cd=([^&]*)&id=([^&]*)')
if not gsv or not s_cd or not s_id: return itemlist
ip = gktools.toHex(gsv) + str(1000000 + random.randint(0,9000000)) + str(100000 + random.randint(0,900000))
gsv_bis = gktools.transforma_gsv(gsv, '159753')
p1 = '1705f5652bb6546ab3643ff698e' + gsv[-5:]
p2 = '8388ca3fd07' + gsv[-5:] + gsv_bis
texto = gktools.toHex(gktools.encode_rijndael(gsv, p1, p2))
suto = gktools.md5_dominio(item.url)
sufijo = '147268278' + gsv[-5:]
prefijo = gsv[:-5] + gsv_bis
token = gktools.generar_token('"'+texto+'"', prefijo+suto+'yt'+suto+sufijo)
archive = gktools.toHex(token)
url = 'https://s4.animeyt.tv/facebook/facebook_animeyts.php'
post = "cd=%s&id=%s&archive=%s&referer=%s&ip=%s&Japan=%s" % (s_cd, s_id, archive, urllib.quote(item.url), ip, 'Asia')
# 3- Descargar json
data = gktools.get_data_json(url, post, ck, item.url)
# 4- Extraer enlaces
itemlist = gktools.extraer_enlaces_json(data, item.referer)
elif item.url.startswith('https://s.animeyt.tv/v4/media.php?'): #https://s.animeyt.tv/v4/media.php?id=SmdMQ2Y0NUhFK2hOZlYzbVJCbnE3QT09
# 1- Descargar
data, ck = gktools.get_data_and_cookie(item)
# 2- Calcular datos
gsv = scrapertools.find_single_match(data, '<meta name="Animeyt-Token" content="([^"]*)"')
s_id = scrapertools.find_single_match(item.url, '\?id=([^&]*)')
if not gsv or not s_id: return itemlist
ip = gktools.toHex(gsv) + str(1000000 + random.randint(0,9000000)) + str(100000 + random.randint(0,900000))
gsv_bis = gktools.transforma_gsv(gsv, '159753')
p1 = '1705f5652bb6546ab3643ff698e' + gsv[-5:]
p2 = '8388ca3fd07' + gsv[-5:] + gsv_bis
texto = gktools.toHex(gktools.encode_rijndael(gsv, p1, p2))
suto = gktools.md5_dominio(item.url)
sufijo = '8049762' + gsv[-5:]
prefijo = gsv[:-5] + gsv_bis
token = gktools.generar_token('"'+texto+'"', prefijo+suto+'yt'+suto+sufijo)
archive = gktools.toHex(token)
url = 'https://s.animeyt.tv/v4/gsuite_animeyts.php'
post = "id=%s&archive=%s&ip=%s&Japan=%s" % (s_id, archive, ip, 'Asia')
# 3- Descargar json
data = gktools.get_data_json(url, post, ck, item.url)
# 4- Extraer enlaces
itemlist = gktools.extraer_enlaces_json(data, item.referer)
elif item.url.startswith('https://s10.animeyt.tv/yourupload.com/id.php?'): #https://s10.animeyt.tv/yourupload.com/id.php?id=62796D77774A4E4363326642
# 1- Descargar
data, ck = gktools.get_data_and_cookie(item)
# 2- Calcular datos
gsv = scrapertools.find_single_match(data, '<meta name="Animeyt-Token" content="([^"]*)"')
s_id = scrapertools.find_single_match(item.url, '\?id=([^&]*)')
if not gsv or not s_id: return itemlist
ip = gktools.toHex(gsv) + str(1000000 + random.randint(0,9000000)) + str(100000 + random.randint(0,900000))
gsv_bis = gktools.transforma_gsv(gsv, '159753')
p1 = '1705f5652bb6546ab3643ff698e' + gsv[-5:]
p2 = '8388ca3fd07' + gsv[-5:] + gsv_bis
texto = gktools.toHex(gktools.encode_rijndael(gsv, p1, p2))
suto = gktools.md5_dominio(item.url)
sufijo = '8049762' + gsv[-5:]
prefijo = gsv[:-5] + gsv_bis
token = gktools.generar_token('"'+texto+'"', prefijo+suto+'yt'+suto+sufijo)
archive = gktools.toHex(token)
url = 'https://s10.animeyt.tv/yourupload.com/chinese_streaming.php'
post = "id=%s&archive=%s&ip=%s&Japan=%s" % (s_id, archive, ip, 'Asia')
# 3- Descargar json
data = gktools.get_data_json(url, post, ck, item.url)
# 4- Extraer enlaces
itemlist = gktools.extraer_enlaces_json(data, item.referer)
elif item.url.startswith('https://s4.animeyt.tv/onedrive.php?'): #https://s4.animeyt.tv/onedrive.php?cd=3439&id=12
# 1- Descargar
data, ck = gktools.get_data_and_cookie(item)
# 2- Calcular datos
gsv = scrapertools.find_single_match(data, '<meta name="Animeyt-Token" content="([^"]*)"')
s_cd, s_id = scrapertools.find_single_match(item.url, '\?cd=([^&]*)&id=([^&]*)')
if not gsv or not s_cd or not s_id: return itemlist
ip = gktools.toHex(gsv) + str(1000000 + random.randint(0,9000000)) + str(100000 + random.randint(0,900000))
gsv_bis = gktools.transforma_gsv(gsv, '159753')
p1 = '1705f5652bb6546ab3643ff698e' + gsv[-5:]
p2 = '8388ca3fd07' + gsv[-5:] + gsv_bis
texto = gktools.toHex(gktools.encode_rijndael(gsv, p1, p2))
suto = gktools.md5_dominio(item.url)
sufijo = '147268278' + gsv[-5:]
prefijo = gsv[:-5] + gsv_bis
token = gktools.generar_token('"'+texto+'"', prefijo+suto+'yt'+suto+sufijo)
archive = gktools.toHex(token)
url = 'https://s4.animeyt.tv/onedrive/onedrive_animeyts.php'
post = "cd=%s&id=%s&archive=%s&ip=%s&Japan=%s" % (s_cd, s_id, archive, ip, 'Asia')
# 3- Descargar json
data = gktools.get_data_json(url, post, ck, item.url)
# 4- Extraer enlaces
itemlist = gktools.extraer_enlaces_json(data, item.referer)
# PENDIENTE ANALIZAR DEMÁS CASOS...
# ~ else:
# ~ headers = {'Referer': item.referer}
# ~ resp = httptools.downloadpage(item.url, headers=headers, cookies=False)
# ~ with open('animeyt-play-%s.html' % item.title, 'w') as f: f.write(resp.data); f.close()
return itemlist

View File

@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
import urllib
import re
from core import httptools
from core import scrapertools
@@ -25,7 +26,7 @@ def mainlist(item):
itemlist.append(item.clone(title="Novedades", action="entradas",
url= host + "/resultados-reciente.php?buscar=&genero=",
fanart="http://i.imgur.com/Q7fsFI6.png"))
itemlist.append(item.clone(title="Destacados", action="entradas",
itemlist.append(item.clone(title="Destacados", action="destacados",
url= host + "/resultados-destacados.php?buscar=&genero=",
fanart="http://i.imgur.com/Q7fsFI6.png"))
itemlist.append(item.clone(title="Categorías", action="cat", url= host + "/index.php",
@@ -37,6 +38,12 @@ def mainlist(item):
return itemlist
def get_source(url):
logger.info()
data = httptools.downloadpage(url).data
data = re.sub(r'\n|\r|\t|&nbsp;|<br>|\s{2,}|"|\(|\)', "", data)
return data
def configuracion(item):
from platformcode import platformtools
@@ -95,22 +102,19 @@ def indice(item):
def cat(item):
logger.info()
itemlist = []
data = httptools.downloadpage(item.url).data
bloque = scrapertools.find_single_match(data, '<ul class="menu">(.*?)</nav>')
matches = scrapertools.find_multiple_matches(bloque, "<li>.*?<a href='([^']+)'.*?>(.*?)</a>")
for scrapedurl, scrapedtitle in matches:
scrapedurl = host + "/" + scrapedurl
if not "span" in scrapedtitle:
scrapedtitle = "[COLOR gold] **" + scrapedtitle + "**[/COLOR]"
itemlist.append(item.clone(action="entradas", title=scrapedtitle, url=scrapedurl))
else:
scrapedtitle = scrapertools.htmlclean(scrapedtitle)
itemlist.append(item.clone(action="entradas", title=scrapedtitle, url=scrapedurl))
data = get_source(item.url)
bloques = scrapertools.find_multiple_matches(data, '</li><li class=dropdown>.*?</ul>')
for bloque in bloques:
matches = scrapertools.find_multiple_matches(bloque, "<li><a href=(.*?)>(.*?)<")
for scrapedurl, scrapedtitle in matches:
scrapedurl = host + "/" + scrapedurl
if not "TODO" in scrapedtitle:
itemlist.append(item.clone(action="entradas", title=scrapedtitle, url=scrapedurl))
return itemlist
def entradas(item):
def destacados(item):
logger.info()
itemlist = []
item.text_color = color2
@@ -161,6 +165,37 @@ def entradas(item):
return itemlist
def entradas(item):
logger.info()
itemlist = []
item.text_color = color2
data = get_source(item.url)
patron = 'class=imagen.*?href=(.*?)><img.*?src=(.*?) alt=.*?title=(.*?)/>.*?</h2>(\d{4}) (.*?)<.*?space>(.*?)<'
matches = scrapertools.find_multiple_matches(data, patron)
for scrapedurl, scrapedthumbnail, scrapedtitle, year, genero, scrapedplot in matches:
infolab = {'plot': scrapedplot, 'genre': genero}
scrapedurl = host + "/" + scrapedurl
scrapedthumbnail = host +'/'+ scrapedthumbnail
title = scrapedtitle
if not year.isspace() and year != "":
infolab['year'] = int(year)
itemlist.append(item.clone(action="findvideos", title=title, fulltitle=title,
url=scrapedurl, thumbnail=scrapedthumbnail, infoLabels=infolab, contentTitle =
title))
next_page = scrapertools.find_single_match(data, '<a class=last>.*?</a></li><li><a href=(.*?)>.*?</a>')
next_page = scrapertools.htmlclean(next_page)
if next_page:
itemlist.append(item.clone(action="entradas", title=">> Página Siguiente", url=host + next_page,
text_color=color3))
return itemlist
def findvideos(item):
logger.info()
itemlist = []

View File

@@ -0,0 +1,69 @@
{
"id": "cuevana3",
"name": "Cuevana 3",
"active": true,
"adult": false,
"language": ["lat", "cast"],
"thumbnail": "http://www.cuevana3.com/wp-content/uploads/2017/08/logo-v10.png",
"banner": "",
"version": 1,
"categories": [
"movies"
],
"settings": [
{
"id": "include_in_global_search",
"type": "bool",
"label": "Incluir en busqueda global",
"default": false,
"enabled": false,
"visible": false
},
{
"id": "filter_languages",
"type": "list",
"label": "Mostrar enlaces en idioma...",
"default": 0,
"enabled": true,
"visible": true,
"lvalues": [
"No filtrar",
"LAT",
"CAST",
"VOSE"
]
},
{
"id": "include_in_newest_peliculas",
"type": "bool",
"label": "Incluir en Novedades - Peliculas",
"default": true,
"enabled": true,
"visible": true
},
{
"id": "include_in_newest_infantiles",
"type": "bool",
"label": "Incluir en Novedades - Infantiles",
"default": true,
"enabled": true,
"visible": true
},
{
"id": "include_in_newest_terror",
"type": "bool",
"label": "Incluir en Novedades - Terror",
"default": true,
"enabled": true,
"visible": true
},
{
"id": "include_in_newest_documentales",
"type": "bool",
"label": "Incluir en Novedades - Documentales",
"default": true,
"enabled": true,
"visible": true
}
]
}

View File

@@ -0,0 +1,200 @@
# -*- coding: utf-8 -*-
# -*- Channel Cuevana 3 -*-
# -*- Created for Alfa-addon -*-
# -*- By the Alfa Develop Group -*-
import re
import urllib
from channelselector import get_thumb
from core import httptools
from core import scrapertools
from core import servertools
from core import tmdb
from core.item import Item
from platformcode import config, logger
from channels import autoplay
from channels import filtertools
host = 'http://www.cuevana3.com/'
IDIOMAS = {'Latino': 'LAT', 'Español': 'CAST', 'Subtitulado':'VOSE'}
list_language = IDIOMAS.values()
list_quality = []
list_servers = ['fastplay', 'rapidvideo', 'streamplay', 'flashx', 'streamito', 'streamango', 'vidoza']
def mainlist(item):
logger.info()
autoplay.init(item.channel, list_servers, list_quality)
itemlist = list()
itemlist.append(item.clone(title="Ultimas", action="list_all", url=host, thumbnail=get_thumb('last', auto=True)))
itemlist.append(item.clone(title="Generos", action="section", section='genre',
thumbnail=get_thumb('genres', auto=True)))
itemlist.append(item.clone(title="Castellano", action="list_all", url= host+'?s=Español',
thumbnail=get_thumb('audio', auto=True)))
itemlist.append(item.clone(title="Latino", action="list_all", url=host + '?s=Latino',
thumbnail=get_thumb('audio', auto=True)))
itemlist.append(item.clone(title="VOSE", action="list_all", url=host + '?s=Subtitulado',
thumbnail=get_thumb('audio', auto=True)))
itemlist.append(item.clone(title="Alfabetico", action="section", section='alpha',
thumbnail=get_thumb('alphabet', auto=True)))
itemlist.append(item.clone(title="Buscar", action="search", url=host+'?s=',
thumbnail=get_thumb('search', auto=True)))
autoplay.show_option(item.channel, itemlist)
return itemlist
def get_source(url):
logger.info()
data = httptools.downloadpage(url).data
data = re.sub(r'"|\n|\r|\t|&nbsp;|<br>|\s{2,}', "", data)
return data
def list_all(item):
logger.info()
itemlist = []
try:
data = get_source(item.url)
if item.section == 'alpha':
patron = '<span class=Num>\d+.*?<a href=(.*?) class.*?'
patron += 'src=(.*?) class.*?<strong>(.*?)</strong>.*?<td>(\d{4})</td>'
else:
patron = '<article id=post-.*?<a href=(.*?)>.*?src=(.*?) alt=.*?'
patron += '<h2 class=Title>(.*?)<\/h2>.*?<span class=Year>(.*?)<\/span>'
data = get_source(item.url)
matches = re.compile(patron, re.DOTALL).findall(data)
for scrapedurl, scrapedthumbnail, scrapedtitle, year in matches:
url = scrapedurl
if "|" in scrapedtitle:
scrapedtitle= scrapedtitle.split("|")
contentTitle = scrapedtitle[0].strip()
else:
contentTitle = scrapedtitle
contentTitle = re.sub('\(.*?\)','', contentTitle)
title = '%s [%s]'%(contentTitle, year)
thumbnail = 'http:'+scrapedthumbnail
itemlist.append(item.clone(action='findvideos',
title=title,
url=url,
thumbnail=thumbnail,
contentTitle=contentTitle,
infoLabels={'year':year}
))
tmdb.set_infoLabels_itemlist(itemlist, True)
# Paginación
url_next_page = scrapertools.find_single_match(data,'<a class=next.*?href=(.*?)>')
if url_next_page:
itemlist.append(item.clone(title="Siguiente >>", url=url_next_page, action='list_all', section=item.section))
except:
pass
return itemlist
def section(item):
logger.info()
itemlist = []
data = get_source(host)
action = 'list_all'
if item.section == 'quality':
patron = 'menu-item-object-category.*?menu-item-\d+><a href=(.*?)>(.*?)<\/a>'
elif item.section == 'genre':
patron = 'category menu-item-\d+><a href=(http:.*?)>(.*?)</a>'
elif item.section == 'year':
patron = 'custom menu-item-15\d+><a href=(.*?\?s.*?)>(\d{4})<\/a><\/li>'
elif item.section == 'alpha':
patron = '<li><a href=(.*?letter.*?)>(.*?)</a>'
action = 'list_all'
matches = re.compile(patron, re.DOTALL).findall(data)
for data_one, data_two in matches:
url = data_one
title = data_two
if title != 'Ver más':
new_item = Item(channel=item.channel, title= title, url=url, action=action, section=item.section)
itemlist.append(new_item)
return itemlist
def findvideos(item):
logger.info()
itemlist = []
data = get_source(item.url)
patron = 'domain=(.*?) class=.*?><span>.*?</span>.*?<span>\d+ - (.*?) - (.*?)</span>'
matches = re.compile(patron, re.DOTALL).findall(data)
for url, language, quality in matches:
if url != '' and 'youtube' not in url:
itemlist.append(item.clone(title='%s', url=url, language=IDIOMAS[language], quality=quality, action='play'))
itemlist = servertools.get_servers_itemlist(itemlist, lambda i: i.title % '%s [%s] [%s]'%(i.server.capitalize(),
i.language, i.quality))
tmdb.set_infoLabels_itemlist(itemlist, True)
try:
itemlist.append(trailer)
except:
pass
# Requerido para FilterTools
itemlist = filtertools.get_links(itemlist, item, list_language)
# Requerido para AutoPlay
autoplay.start(itemlist, item)
if config.get_videolibrary_support() and len(itemlist) > 0 and item.extra != 'findvideos':
itemlist.append(
Item(channel=item.channel, title='[COLOR yellow]Añadir esta pelicula a la videoteca[/COLOR]', url=item.url,
action="add_pelicula_to_library", extra="findvideos", contentTitle=item.contentTitle))
return itemlist
def search(item, texto):
logger.info()
texto = texto.replace(" ", "+")
item.url = item.url + texto
if texto != '':
return list_all(item)
else:
return []
def newest(categoria):
logger.info()
itemlist = []
item = Item()
try:
if categoria == 'infantiles':
item.url = host+'/category/animacion'
elif categoria == 'terror':
item.url = host+'/category/terror'
elif categoria == 'documentales':
item.url = host+'/category/documental'
itemlist = list_all(item)
if itemlist[-1].title == 'Siguiente >>':
itemlist.pop()
except:
import sys
for line in sys.exc_info():
logger.error("{0}".format(line))
return []
return itemlist

View File

@@ -12,40 +12,53 @@ from core import httptools
from core import scrapertools
from core import servertools
from core.item import Item
from platformcode import config, logger
from platformcode import config, logger, platformtools
from core import tmdb
from lib import generictools
host = 'http://descargas2020.com/'
channel_py = 'newpct1'
#Código para permitir usar un único canal para todas las webs clones de NewPct1
clone_list = config.get_setting('clonenewpct1_channels_list', "torrentrapid") #Carga lista de clones
clone_list = ast.literal_eval(clone_list) #la convierte a lista de tuplas
clone_list = config.get_setting('clonenewpct1_channels_list', channel_py) #Carga lista de clones
clone_list = ast.literal_eval(clone_list) #la convierte en array
host_index = 0
host_index = config.get_setting('clonenewpct1_channel_default', "torrentrapid") #Clone por defecto
host_index = config.get_setting('clonenewpct1_channel_default', channel_py) #Clone por defecto
i = 0
for active_clone, channel_clone, host_clone, contentType_clone, info_clone in clone_list:
if i == host_index:
#channel_clone_name = channel_clone #ACTIVAR CUANDO SE PASE A NEWPCT1
#host = 'http://%s/' % host_clone #ACTIVAR CUANDO SE PASE A NEWPCT1
i += 1
channel_clone_name = channel_clone #Nombre del Canal elegido
host = host_clone #URL del Canal elegido
break
i += 1
item = Item()
item.channel_host = host
if item.channel != channel_py:
item.channel = channel_py
item.category = channel_clone_name.capitalize()
#Carga de opciones del canal
item = Item()
if not item.channel:
item.channel = scrapertools.find_single_match(host, r'(\w+)\.com\/')
channel_clone_name = scrapertools.find_single_match(host, r'(\w+)\.com\/') #QUITAR CUANDO SE PASE A NEWPCT1
__modo_grafico__ = config.get_setting('modo_grafico', item.channel)
modo_ultima_temp = config.get_setting('seleccionar_ult_temporadda_activa', item.channel)
__modo_grafico__ = config.get_setting('modo_grafico', channel_py) #TMDB?
modo_ultima_temp = config.get_setting('seleccionar_ult_temporadda_activa', channel_py) #Actualización sólo últ. Temporada?
timeout = config.get_setting('clonenewpct1_timeout_downloadpage', channel_py) #Timeout downloadpage
if timeout == 0: timeout = None
platformtools.dialog_ok("NewPct1, ¡¡¡he vuelto como canal VIRTUAL!!!", "Hemos centralizado la gestión de los clones de NewPct1 en el canal virtual NewPct1. Los clones desaparecerán en breve.", "Para más información lee el tutorial: https://alfa-addon.com /threads/newpct1-implantando-alta-disponibilidad.1200/")
#Vayamos a la siguiente acción en el canal Newpct1
from platformcode import launcher
channel_clone_name = "descargas2020" #Nombre del Canal elegido
host = "http://descargas2020.com/"
item.category = channel_clone_name.capitalize()
item.action = "mainlist"
item.channel_host = host
launcher.run(item)
def mainlist(item):
logger.info()
if item.channel != channel_py:
return
#Renombramos el canal al nombre de clone elegido
item.channel = channel_clone_name
if item.category: item.category = channel_clone_name.capitalize()
itemlist = []
thumb_pelis = get_thumb("channels_movie.png")
@@ -58,20 +71,20 @@ def mainlist(item):
thumb_settings = get_thumb("setting_0.png")
itemlist.append(Item(channel=item.channel, action="submenu", title="Películas", url=host,
extra="peliculas", thumbnail=thumb_pelis ))
extra="peliculas", thumbnail=thumb_pelis, category=item.category))
itemlist.append(Item(channel=item.channel, action="submenu", title="Series", url=host, extra="series",
thumbnail=thumb_series))
thumbnail=thumb_series, category=item.category))
itemlist.append(Item(channel=item.channel, action="submenu", title="Documentales", url=host, extra="varios",
thumbnail=thumb_docus))
thumbnail=thumb_docus, category=item.category))
itemlist.append(
Item(channel=item.channel, action="search", title="Buscar", url=host + "buscar", thumbnail=thumb_buscar))
Item(channel=item.channel, action="search", title="Buscar", url=host + "buscar", thumbnail=thumb_buscar, category=item.category))
itemlist.append(
Item(channel=item.channel, action="", title="[COLOR yellow]Configuración de Servidores:[/COLOR]", url="", thumbnail=thumb_settings))
Item(channel=item.channel, action="", title="[COLOR yellow]Configuración de Servidores:[/COLOR]", url="", thumbnail=thumb_settings, category=item.category))
itemlist.append(
Item(channel=item.channel, action="settingCanal", title="Servidores para Ver Online y Descargas", url="", thumbnail=thumb_settings))
Item(channel=item.channel, action="settingCanal", title="Servidores para Ver Online y Descargas", url="", thumbnail=thumb_settings, category=item.category))
return itemlist
@@ -85,68 +98,60 @@ def submenu(item):
logger.info()
itemlist = []
data = ''
try:
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data)
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data)
except:
pass
host_alt = host
host_dom = host.replace("https://", "").replace("http://", "").replace("www.", "")
patron = '<li><a href="http://(?:www.)?' + host_dom + item.extra + '/">.*?<ul.*?>(.*?)</ul>'
patron = '<li><a\s?class="[^"]+"\s?href="http:[^"]+"><i\s?class=.*><\/i>.*Inicio<\/a><\/li>(.+)<\/ul>\s?<\/nav>'
#Verificamos si se ha cargado una página, y si además tiene la estructura correcta
if not data or not scrapertools.find_single_match(data, patron):
logger.error("ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL: " + item.url)
logger.error("ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL: " + item.url + data)
#Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú
item, data = generictools.fail_over_newpct1(item, patron)
if not data: #Si no ha logrado encontrar nada, salimos
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
elif item.channel_alt: #Si ha habido fail-over, lo comento
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR] [ALT ] en uso'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] caído'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR] [ALT ] en uso'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] inaccesible'))
host_alt = host.replace(item.channel_alt, item.channel)
del item.channel_alt
if item.url_alt: del item.url_alt
del item.channel_alt
#data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8")
#data = data.replace("'", '"').replace('/series"', '/series/"') #Compatibilidad con mispelisy.series.com
host_dom = host_alt.replace("https://", "").replace("http://", "").replace("www.", "")
patron = '<li><a href="http://(?:www.)?' + host_dom + item.extra + '/">.*?<ul.*?>(.*?)</ul>'
if "pelisyseries.com" in host_alt and item.extra == "varios": #compatibilidad con mispelisy.series.com
data = '<a href="' + host_alt + 'varios/" title="Documentales"><i class="icon-rocket"></i> Documentales</a>'
data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8")
data = data.replace("'", '"').replace('/series"', '/series/"') #Compatibilidad con mispelisy.series.com
if "pelisyseries.com" in item.channel_host and item.extra == "varios": #compatibilidad con mispelisy.series.com
data = '<li><a href="' + item.channel_host + 'varios/" title="Documentales">Documentales</a></li>'
else:
if data:
data = scrapertools.get_match(data, patron)
if not data:
logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
else:
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
data = scrapertools.get_match(data, patron) #Seleccionamos el trozo que nos interesa
if not data:
logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
patron = '<.*?href="([^"]+)".*?>([^>]+)</a>'
patron = '<li><a.*?href="([^"]+)"\s?.itle="[^"]+"\s?>([^>]+)<\/a><\/li>'
matches = re.compile(patron, re.DOTALL).findall(data)
if not matches:
logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
for scrapedurl, scrapedtitle in matches:
title = scrapedtitle.strip()
url = scrapedurl
itemlist.append(Item(channel=item.channel, action="listado", title=title, url=url, extra=item.extra))
itemlist.append(
Item(channel=item.channel, action="alfabeto", title=title + " [A-Z]", url=url, extra=item.extra))
#Preguntamos por las entradas que no corresponden al "extra"
if item.extra in scrapedtitle.lower() or (item.extra == "peliculas" and ("cine" in scrapedurl or "anime" in scrapedurl)) or (item.extra == "varios" and ("documentales" in scrapedurl or "varios" in scrapedurl)):
itemlist.append(item.clone(action="listado", title=title, url=scrapedurl))
itemlist.append(item.clone(action="alfabeto", title=title + " [A-Z]", url=scrapedurl))
if item.extra == "peliculas":
itemlist.append(Item(channel=item.channel, action="listado", title="Películas 4K", url=host_alt + "peliculas-hd/4kultrahd/", extra=item.extra))
itemlist.append(
Item(channel=item.channel, action="alfabeto", title="Películas 4K" + " [A-Z]", url=host_alt + "peliculas-hd/4kultrahd/", extra=item.extra))
itemlist.append(item.clone(action="listado", title="Películas 4K", url=item.channel_host + "peliculas-hd/4kultrahd/"))
itemlist.append(item.clone(action="alfabeto", title="Películas 4K" + " [A-Z]", url=item.channel_host + "peliculas-hd/4kultrahd/"))
return itemlist
@@ -155,28 +160,41 @@ def alfabeto(item):
logger.info()
itemlist = []
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data)
data = ''
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data)
data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8")
patron = '<ul class="alfabeto">(.*?)</ul>'
if data:
data = scrapertools.get_match(data, patron)
else:
return itemlist
if not data or not scrapertools.find_single_match(data, patron):
logger.error("ERROR 01: ALFABETO: La Web no responde o ha cambiado de URL: " + item.url + data)
#Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú
item, data = generictools.fail_over_newpct1(item, patron)
if not data: #Si no ha logrado encontrar nada, salimos
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: ALFABETO: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
elif item.channel_alt: #Si ha habido fail-over, lo comento
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR] [ALT ] en uso'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] inaccesible'))
if item.url_alt: del item.url_alt
del item.channel_alt
data = scrapertools.get_match(data, patron)
patron = '<a href="([^"]+)"[^>]+>([^>]+)</a>'
matches = re.compile(patron, re.DOTALL).findall(data)
if not matches:
logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log'))
logger.error("ERROR 02: ALFABETO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: ALFABETO: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
for scrapedurl, scrapedtitle in matches:
title = scrapedtitle.upper()
url = scrapedurl
itemlist.append(Item(channel=item.channel, action="listado", title=title, url=url, extra=item.extra))
itemlist.append(item.clone(action="listado", title=title, url=scrapedurl))
return itemlist
@@ -191,11 +209,21 @@ def listado(item):
if item.totalItems:
del item.totalItems
data = ''
try:
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data)
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data)
except:
pass
patron = '<ul class="' + clase + '">(.*?)</ul>' #seleccionamos el bloque que nos interesa
if not data or (not scrapertools.find_single_match(data, patron) and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data):
logger.error("ERROR 01: LISTADO: La Web no responde o ha cambiado de URL: " + item.url + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
#Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú
item, data = generictools.fail_over_newpct1(item, patron)
if not data: #Si no ha logrado encontrar nada, salimos
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: LISTADO: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
#Establecemos los valores básicos en función del tipo de contenido
@@ -218,7 +246,7 @@ def listado(item):
fichas = scrapertools.get_match(data, patron)
if not fichas and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data: #error
logger.error("ERROR 02: LISTADO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
elif '<h3><strong>( 0 ) Resultados encontrados </strong>' in data: #no hay vídeos
return itemlist
@@ -235,7 +263,7 @@ def listado(item):
matches = re.compile(patron, re.DOTALL).findall(fichas)
if not matches: #error
logger.error("ERROR 02: LISTADO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + fichas)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
#logger.debug("MATCHES: " + str(len(matches)))
@@ -460,13 +488,21 @@ def listado(item):
def listado_busqueda(item):
logger.info()
host = 'http://%s/' % scrapertools.find_single_match(item.url, '(\w+\.com)\/')
#Renombramos el canal al nombre de clone elegido. Actualizados URL
host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)')
#item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/')
if item.category and item.category != "newest":
item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize()
itemlist = []
cnt_tot = 40 # Poner el num. máximo de items por página. Dejamos que la web lo controle
cnt_title = 0 # Contador de líneas insertadas en Itemlist
cnt_pag = 0 # Contador de líneas leídas de Matches
timeout_search = 5 # Timeout un poco más largo para las búsquedas
if timeout > 5:
timeout_search = timeout # Timeout un poco más largo para las búsquedas
data = ''
if item.cnt_pag:
cnt_pag = item.cnt_pag # Se guarda en la lista de páginas anteriores en Item
@@ -493,21 +529,21 @@ def listado_busqueda(item):
#Máximo num. de líneas permitidas por TMDB. Máx de 5 páginas por Itemlist para no degradar el rendimiento
while cnt_title <= cnt_tot and cnt_next < 5:
pattern = '<ul class="%s">(.*?)</ul>' % item.pattern #seleccionamos el bloque que nos interesa
try:
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, post=item.post).data)
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, post=item.post, timeout=timeout_search).data)
except:
pass
cnt_next += 1
if not data or not scrapertools.find_single_match(data, pattern):
cnt_next += 1
pattern = '<ul class="%s">(.*?)</ul>' % item.pattern #seleccionamos el bloque que nos interesa
if not data or (not scrapertools.find_single_match(data, pattern) and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data):
logger.error("ERROR 01: LISTADO_BUSQUEDA: La Web no responde o ha cambiado de URL: " + item.url + item.post + " / DATA: " + data)
#Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú
item, data = generictools.fail_over_newpct1(item, pattern)
if not data: #Si no ha logrado encontrar nada, salimos
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO_BUSQUEDA:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: LISTADO_BUSQUEDA:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
elif item.channel_alt: #Si ha habido fail-over, lo comento
host = host.replace(item.channel_alt, item.channel)
@@ -531,7 +567,6 @@ def listado_busqueda(item):
pattern = '<ul class="%s">(.*?)</ul>' % item.pattern #seleccionamos el bloque que nos interesa
data_alt = data
data = scrapertools.get_match(data, pattern)
#pattern = '<li[^>]*><a href="(?P<url>[^"]+).*?<img.*?src="(?P<thumb>[^"]+)?".*?<h2.*?>(?P<title>.*?)?<\/h2>'
pattern = '<li[^>]*><a href="(?P<scrapedurl>[^"]+).*?' #url
pattern += 'title="(?P<scrapedtitle>[^"]+).*?' #título
pattern += '<img.*?src="(?P<scrapedthumbnail>[^"]+)?".*?' #thumb
@@ -541,7 +576,8 @@ def listado_busqueda(item):
matches_alt = re.compile(pattern, re.DOTALL).findall(data)
if not matches_alt and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data_alt: #error
logger.error("ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + data_alt)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web. Reportar el error con el log'))
item, itemlist = generictools.post_tmdb_listado(item, itemlist) #Pintamos los datos de fail-over, si los hay
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
#Ahora se hace una simulación para saber cuantas líneas podemos albergar en este Itemlist.
@@ -830,14 +866,14 @@ def listado_busqueda(item):
url_tvshow = host + calidad_mps + real_title_mps + "/" #... otras no. A probar...
#Leemos la página, a ver si es una página de episodios
data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_id).data)
data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_id, timeout=timeout).data)
data_serie = unicode(data_serie, "iso-8859-1", errors="replace").encode("utf-8")
data_serie = data_serie.replace("chapters", "buscar-list")
pattern = '<ul class="%s">(.*?)</ul>' % "buscar-list" #Patrón de lista de episodios
if not scrapertools.find_single_match(data_serie, pattern) and serieid: #no es válida la página,
#intentarlo con la otra url
data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_tvshow).data)
data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_tvshow, timeout=timeout).data)
data_serie = unicode(data_serie, "iso-8859-1", errors="replace").encode("utf-8")
data_serie = data_serie.replace("chapters", "buscar-list")
@@ -876,9 +912,10 @@ def findvideos(item):
from core import channeltools
logger.info()
#Renombramos el canal al nombre de clone elegido
item.channel = channel_clone_name
if item.category: item.category = channel_clone_name.capitalize()
#Renombramos el canal al nombre de clone elegido. Actualizados URL
host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)')
#item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/')
item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize()
itemlist = []
@@ -987,8 +1024,9 @@ def findvideos(item):
excluir_enlaces_descargas = [] #Lista vacía de servidores excluidos en Descargar
# Descarga la página
data = ''
try:
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data)
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data)
except:
pass
@@ -1001,7 +1039,7 @@ def findvideos(item):
item, data = generictools.fail_over_newpct1(item, patron)
if not data: #Si no ha logrado encontrar nada, salimos
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: FINDVIDEOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: FINDVIDEOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8")
@@ -1029,7 +1067,7 @@ def findvideos(item):
item_local.url = scrapertools.find_single_match(data, patron)
if not item_local.url: #error
logger.error("ERROR 02: FINDVIDEOS: El archivo Torrent no existe o ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: FINDVIDEOS: El archivo Torrent no existe o ha cambiado la estructura de la Web. Verificar en la Web y reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: FINDVIDEOS: El archivo Torrent no existe o ha cambiado la estructura de la Web. Verificar en la Web y reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
item_local.url = item_local.url.replace(" ", "%20") #sustituimos espacios por %20, por si acaso
#logger.debug("Patron: " + patron + " url: " + item_local.url)
@@ -1054,6 +1092,8 @@ def findvideos(item):
#logger.debug(item_local)
# VER vídeos, descargar vídeos un link, o múltiples links
data = scrapertools.find_single_match(data, '<div id="tab1" class="tab_content"(.*?<\/ul>(?:<div.*?>)?<\/div><\/div><\/div>)') #Seleccionar el bloque para evitar duplicados
host_dom = host.replace("https://", "").replace("http://", "").replace("www.", "")
data = data.replace("http://tumejorserie.com/descargar/url_encript.php?link=", "(")
data = re.sub(r'javascript:;" onClick="popup\("http:\/\/(?:www.)?' + host_dom + '\w{1,9}\/library\/include\/ajax\/get_modallinks.php\?links=', "", data)
@@ -1066,7 +1106,7 @@ def findvideos(item):
enlaces_ver = re.compile(patron, re.DOTALL).findall(data)
enlaces_descargar = enlaces_ver
#logger.debug(enlaces_ver)
#Recorre todos los links de VER, si está permitido
cnt_enl_ver = 1
cnt_enl_verif = 1
@@ -1100,7 +1140,7 @@ def findvideos(item):
if verificar_enlaces_veronline != 0: #Se quiere verificar si el link está activo?
if cnt_enl_verif <= verificar_enlaces_veronline or verificar_enlaces_veronline == -1: #contador?
#Llama a la subfunción de check_list_links(itemlist) para cada link de servidor
item_local.alive = servertools.check_video_link(enlace, servidor) #activo el link ?
item_local.alive = servertools.check_video_link(enlace, servidor, timeout=timeout) #activo el link ?
if verificar_enlaces_veronline_validos: #Los links tienen que ser válidos para contarlos?
if item_local.alive == "Ok": #Sí
cnt_enl_verif += 1 #Movemos los contadores
@@ -1190,7 +1230,7 @@ def findvideos(item):
if verificar_enlaces_descargas != 0: #Se quiere verificar si el link está activo?
if cnt_enl_verif <= verificar_enlaces_descargas or verificar_enlaces_descargas == -1: #contador?
#Llama a la subfunción de check_list_links(itemlist) para primer link de servidor
item_local.alive = servertools.check_video_link(enlace, servidor) #activo el link ?
item_local.alive = servertools.check_video_link(enlace, servidor, timeout=timeout) #activo el link ?
if verificar_enlaces_descargas_validos: #Los links tienen que ser válidos para contarlos?
if item_local.alive == "Ok": #Sí
cnt_enl_verif += 1 #Movemos los contadores
@@ -1232,9 +1272,10 @@ def findvideos(item):
def episodios(item):
logger.info()
#Renombramos el canal al nombre de clone elegido
item.channel = channel_clone_name
if item.category: item.category = channel_clone_name.capitalize()
#Renombramos el canal al nombre de clone elegido. Actualizados URL
host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)')
#item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/')
item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize()
itemlist = []
@@ -1255,7 +1296,7 @@ def episodios(item):
data = ''
try:
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url).data)
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, timeout=timeout).data)
patron = '<ul class="%s">(.*?)</ul>' % "buscar-list" # item.pattern
data_alt = ''
if data: data_alt = scrapertools.get_match(data, patron)
@@ -1276,7 +1317,7 @@ def episodios(item):
if not data: #No se ha encontrado ningún canal activo para este vídeo
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: EPISODIOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: EPISODIOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log'))
return itemlist
#Busca y pre-carga todas las páginas de episodios que componen las serie, para obtener la url de cada página
@@ -1312,7 +1353,7 @@ def episodios(item):
break
try:
if not data:
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(page).data)
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(page, timeout=timeout).data)
data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8")
data = data.replace("chapters", "buscar-list") #Compatibilidad con mispelisy.series.com
pattern = '<ul class="%s">(.*?)</ul>' % "buscar-list" # item.pattern
@@ -1321,7 +1362,7 @@ def episodios(item):
raise
except:
logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / " + str(list_pages) + " / DATA: " + str(data))
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
if "pelisyseries.com" in item.url:
@@ -1331,7 +1372,7 @@ def episodios(item):
matches = re.compile(pattern, re.DOTALL).findall(data)
if not matches: #error
logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
#logger.debug("patron: " + pattern)
@@ -1399,7 +1440,7 @@ def episodios(item):
match = [m.groupdict() for m in r.finditer(info)][0]
if not match: #error
logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + info)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
if match['season'] is None: match['season'] = season #Si no se encuentran valores, pero poner lo básico
@@ -1449,8 +1490,6 @@ def episodios(item):
if item_local.active:
del item_local.active
if item_local.category:
del item_local.category
if item_local.infoLabels['title']:
del item_local.infoLabels['title']
item_local.context = "['buscar_trailer']"
@@ -1467,6 +1506,8 @@ def episodios(item):
del item_local.update_last
if item_local.update_next:
del item_local.update_next
if item_local.channel_host:
del item_local.channel_host
itemlist.append(item_local.clone())
@@ -1501,9 +1542,6 @@ def actualizar_titulos(item):
def search(item, texto):
logger.info("search:" + texto)
# texto = texto.replace(" ", "+")
item.channel = channel_clone_name
if item.category: item.category = channel_clone_name.capitalize()
try:
item.post = "q=%s" % texto

View File

@@ -2,7 +2,7 @@
"id": "descargasmix",
"name": "DescargasMIX",
"language": ["cast", "lat"],
"active": true,
"active": false,
"adult": false,
"thumbnail": "descargasmix.png",
"banner": "descargasmix.png",
@@ -77,4 +77,4 @@
"visible": true
}
]
}
}

View File

@@ -10,14 +10,14 @@
"settings": [
{
"type": "label",
"label": "Ubicacion de archivos",
"label": "@70229",
"enabled": true,
"visible": true
},
{
"id": "library_add",
"type": "bool",
"label": " - Añadir descargas completadas a la videoteca",
"label": "@70230",
"default": true,
"enabled": true,
"visible": true
@@ -25,7 +25,7 @@
{
"id": "library_move",
"type": "bool",
"label": " - Mover el archivo descargado a la videoteca",
"label": "@70231",
"default": true,
"enabled": "eq(-1,true)",
"visible": true
@@ -33,21 +33,21 @@
{
"id": "browser",
"type": "bool",
"label": " - Visualizar archivos descargados desde descargas",
"label": "@70232",
"default": false,
"enabled": true,
"visible": true
},
{
"type": "label",
"label": "Descarga",
"label": "@70243",
"enabled": true,
"visible": true
},
{
"id": "block_size",
"type": "list",
"label": " - Tamaño por bloque",
"label": "@70233",
"lvalues": [
"128 KB",
"256 KB",
@@ -62,7 +62,7 @@
{
"id": "part_size",
"type": "list",
"label": " - Tamaño por parte",
"label": "@70234",
"lvalues": [
"1 MB",
"2 MB",
@@ -78,7 +78,7 @@
{
"id": "max_connections",
"type": "list",
"label": " - Numero máximo de conexiones simultaneas",
"label": "@70235",
"lvalues": [
"1",
"2",
@@ -98,7 +98,7 @@
{
"id": "max_buffer",
"type": "list",
"label": " - Numero máximo de partes en memoria",
"label": "@70236",
"lvalues": [
"0",
"2",
@@ -118,17 +118,17 @@
},
{
"type": "label",
"label": "Elección del servidor",
"label": "@70237",
"enabled": true,
"visible": true
},
{
"id": "server_reorder",
"type": "list",
"label": " - Orden de servidores",
"label": "@70238",
"lvalues": [
"Mantener",
"Reordenar"
"@70244",
"@70245"
],
"default": 1,
"enabled": true,
@@ -137,7 +137,7 @@
{
"id": "language",
"type": "list",
"label": " - Idioma preferido",
"label": "@70246",
"lvalues": [
"Esp, Lat, Sub, Eng, Vose",
"Esp, Sub, Lat, Eng, Vose",
@@ -145,29 +145,29 @@
"Vose, Eng, Sub, Esp, Lat"
],
"default": 0,
"enabled": "eq(-1,'Reordenar')",
"enabled": "eq(-1,@70245])",
"visible": true
},
{
"id": "quality",
"type": "list",
"label": " - Calidad preferida",
"label": "@70240",
"lvalues": [
"La mas alta",
"@70241",
"HD 1080",
"HD 720",
"SD"
],
"default": 0,
"enabled": "eq(-2,'Reordenar')",
"enabled": "eq(-2,@70245])",
"visible": true
},
{
"id": "server_speed",
"type": "bool",
"label": " - Elegir los servidores mas rapidos",
"label": "@70242",
"default": true,
"enabled": "eq(-3,'Reordenar')",
"enabled": "eq(-3,@70245])",
"visible": true
}
]

View File

@@ -89,40 +89,40 @@ def mainlist(item):
# Si hay alguno completado
if 2 in estados:
itemlist.insert(0, Item(channel=item.channel, action="clean_ready", title="Eliminar descargas completadas",
itemlist.insert(0, Item(channel=item.channel, action="clean_ready", title=config.get_localized_string(70218),
contentType=item.contentType, contentChannel=item.contentChannel,
contentSerieName=item.contentSerieName, text_color="sandybrown"))
# Si hay alguno con error
if 3 in estados:
itemlist.insert(0, Item(channel=item.channel, action="restart_error", title="Reiniciar descargas con error",
itemlist.insert(0, Item(channel=item.channel, action="restart_error", title=config.get_localized_string(70219),
contentType=item.contentType, contentChannel=item.contentChannel,
contentSerieName=item.contentSerieName, text_color="orange"))
# Si hay alguno pendiente
if 1 in estados or 0 in estados:
itemlist.insert(0, Item(channel=item.channel, action="download_all", title="Descargar todo",
itemlist.insert(0, Item(channel=item.channel, action="download_all", title=config.get_localized_string(70220),
contentType=item.contentType, contentChannel=item.contentChannel,
contentSerieName=item.contentSerieName, text_color="green"))
if len(itemlist):
itemlist.insert(0, Item(channel=item.channel, action="clean_all", title="Eliminar todo",
itemlist.insert(0, Item(channel=item.channel, action="clean_all", title=config.get_localized_string(70221),
contentType=item.contentType, contentChannel=item.contentChannel,
contentSerieName=item.contentSerieName, text_color="red"))
if not item.contentType == "tvshow" and config.get_setting("browser", "downloads") == True:
itemlist.insert(0, Item(channel=item.channel, action="browser", title="Ver archivos descargados",
itemlist.insert(0, Item(channel=item.channel, action="browser", title=config.get_localized_string(70222),
url=DOWNLOAD_PATH, text_color="yellow"))
if not item.contentType == "tvshow":
itemlist.insert(0, Item(channel=item.channel, action="settings", title="Configuración descargas...",
itemlist.insert(0, Item(channel=item.channel, action="settings", title=config.get_localized_string(70223),
text_color="blue"))
return itemlist
def settings(item):
ret = platformtools.show_channel_settings(caption="configuración -- Descargas")
ret = platformtools.show_channel_settings(caption=config.get_localized_string(70224))
platformtools.itemlist_refresh()
return ret
@@ -211,7 +211,7 @@ def menu(item):
else:
servidor = "Auto"
# Opciones disponibles para el menu
op = ["Descargar", "Eliminar de la lista", "Reiniciar descarga y eliminar datos",
op = [config.get_localized_string(70225), config.get_localized_string(70226), config.get_localized_string(70227),
"Modificar servidor: %s" % (servidor.capitalize())]
opciones = []
@@ -237,7 +237,7 @@ def menu(item):
opciones.append(op[1]) # Eliminar de la lista
# Mostramos el dialogo
seleccion = platformtools.dialog_select("Elige una opción", opciones)
seleccion = platformtools.dialog_select(config.get_localized_string(30163), opciones)
# -1 es cancelar
if seleccion == -1: return
@@ -289,12 +289,12 @@ def move_to_libray(item):
if config.get_setting("library_add", "downloads") == True:
if filetools.isfile(final_path):
if item.contentType == "movie" and item.infoLabels["tmdb_id"]:
library_item = Item(title="Descargado: %s" % item.downloadFilename, channel="downloads",
library_item = Item(title=config.get_localized_string(70228) % item.downloadFilename, channel="downloads",
action="findvideos", infoLabels=item.infoLabels, url=final_path)
videolibrarytools.save_movie(library_item)
elif item.contentType == "episode" and item.infoLabels["tmdb_id"]:
library_item = Item(title="Descargado: %s" % item.downloadFilename, channel="downloads",
library_item = Item(title=config.get_localized_string(70228) % item.downloadFilename, channel="downloads",
action="findvideos", infoLabels=item.infoLabels, url=final_path)
tvshow = Item(channel="downloads", contentType="tvshow",
infoLabels={"tmdb_id": item.infoLabels["tmdb_id"]})
@@ -474,7 +474,7 @@ def download_from_url(url, item):
block_size=2 ** (17 + int(config.get_setting("block_size", "downloads"))),
part_size=2 ** (20 + int(config.get_setting("part_size", "downloads"))),
max_buffer=2 * int(config.get_setting("max_buffer", "downloads")))
d.start_dialog("Descargas")
d.start_dialog(config.get_localized_string(60332))
# Descarga detenida. Obtenemos el estado:
# Se ha producido un error en la descarga
@@ -511,11 +511,11 @@ def download_from_server(item):
logger.info(item.tostring())
unsupported_servers = ["torrent"]
progreso = platformtools.dialog_progress("Descargas", "Probando con: %s" % item.server)
progreso = platformtools.dialog_progress(config.get_localized_string(30101), config.get_localized_string(70178) % item.server)
channel = __import__('channels.%s' % item.contentChannel, None, None, ["channels.%s" % item.contentChannel])
if hasattr(channel, "play") and not item.play_menu:
progreso.update(50, "Probando con: %s" % item.server, "Conectando con %s..." % item.contentChannel)
progreso.update(50, config.get_localized_string(70178) % item.server, config.get_localized_string(60003) % item.contentChannel)
try:
itemlist = getattr(channel, "play")(item.clone(channel=item.contentChannel, action=item.contentAction))
except:
@@ -578,10 +578,10 @@ def download_from_best_server(item):
result = {"downloadStatus": STATUS_CODES.error}
progreso = platformtools.dialog_progress("Descargas", "Obteniendo lista de servidores disponibles...")
progreso = platformtools.dialog_progress(config.get_localized_string(30101), config.get_localized_string(70179))
channel = __import__('channels.%s' % item.contentChannel, None, None, ["channels.%s" % item.contentChannel])
progreso.update(50, "Obteniendo lista de servidores disponibles:", "Conectando con %s..." % item.contentChannel)
progreso.update(50, config.get_localized_string(70184), config.get_localized_string(70180) % item.contentChannel)
if hasattr(channel, item.contentAction):
play_items = getattr(channel, item.contentAction)(
@@ -591,8 +591,8 @@ def download_from_best_server(item):
play_items = filter(lambda x: x.action == "play" and not "trailer" in x.title.lower(), play_items)
progreso.update(100, "Obteniendo lista de servidores disponibles", "Servidores disponibles: %s" % len(play_items),
"Identificando servidores...")
progreso.update(100, config.get_localized_string(70183), config.get_localized_string(70181) % len(play_items),
config.get_localized_string(70182))
if config.get_setting("server_reorder", "downloads") == 1:
play_items.sort(key=sort_method)
@@ -625,9 +625,9 @@ def select_server(item):
logger.info(
"contentAction: %s | contentChannel: %s | url: %s" % (item.contentAction, item.contentChannel, item.url))
progreso = platformtools.dialog_progress("Descargas", "Obteniendo lista de servidores disponibles...")
progreso = platformtools.dialog_progress(config.get_localized_string(30101), config.get_localized_string(70179))
channel = __import__('channels.%s' % item.contentChannel, None, None, ["channels.%s" % item.contentChannel])
progreso.update(50, "Obteniendo lista de servidores disponibles:", "Conectando con %s..." % item.contentChannel)
progreso.update(50, config.get_localized_string(70184), config.get_localized_string(70180) % item.contentChannel)
if hasattr(channel, item.contentAction):
play_items = getattr(channel, item.contentAction)(
@@ -637,14 +637,14 @@ def select_server(item):
play_items = filter(lambda x: x.action == "play" and not "trailer" in x.title.lower(), play_items)
progreso.update(100, "Obteniendo lista de servidores disponibles", "Servidores disponibles: %s" % len(play_items),
"Identificando servidores...")
progreso.update(100, config.get_localized_string(70183), config.get_localized_string(70181) % len(play_items),
config.get_localized_string(70182))
for x, i in enumerate(play_items):
if not i.server and hasattr(channel, "play"):
play_items[x] = getattr(channel, "play")(i)
seleccion = platformtools.dialog_select("Selecciona el servidor", ["Auto"] + [s.title for s in play_items])
seleccion = platformtools.dialog_select(config.get_localized_string(70192), ["Auto"] + [s.title for s in play_items])
if seleccion > 1:
update_json(item.path, {
"downloadServer": {"url": play_items[seleccion - 1].url, "server": play_items[seleccion - 1].server}})
@@ -795,7 +795,7 @@ def save_download_video(item):
write_json(item)
if not platformtools.dialog_yesno(config.get_localized_string(30101), "¿Iniciar la descarga ahora?"):
if not platformtools.dialog_yesno(config.get_localized_string(30101), config.get_localized_string(70189)):
platformtools.dialog_ok(config.get_localized_string(30101), item.contentTitle,
config.get_localized_string(30109))
else:
@@ -806,7 +806,7 @@ def save_download_movie(item):
logger.info("contentAction: %s | contentChannel: %s | contentTitle: %s" % (
item.contentAction, item.contentChannel, item.contentTitle))
progreso = platformtools.dialog_progress("Descargas", "Obteniendo datos de la pelicula")
progreso = platformtools.dialog_progress(config.get_localized_string(30101), config.get_localized_string(70191))
set_movie_title(item)
@@ -815,7 +815,7 @@ def save_download_movie(item):
progreso.close()
return save_download_video(item)
progreso.update(0, "Añadiendo pelicula...")
progreso.update(0, config.get_localized_string(60062))
item.downloadFilename = filetools.validate_path("%s [%s]" % (item.contentTitle.strip(), item.contentChannel))
@@ -823,7 +823,7 @@ def save_download_movie(item):
progreso.close()
if not platformtools.dialog_yesno(config.get_localized_string(30101), "¿Iniciar la descarga ahora?"):
if not platformtools.dialog_yesno(config.get_localized_string(30101), config.get_localized_string(70189)):
platformtools.dialog_ok(config.get_localized_string(30101), item.contentTitle,
config.get_localized_string(30109))
else:
@@ -834,17 +834,17 @@ def save_download_tvshow(item):
logger.info("contentAction: %s | contentChannel: %s | contentType: %s | contentSerieName: %s" % (
item.contentAction, item.contentChannel, item.contentType, item.contentSerieName))
progreso = platformtools.dialog_progress("Descargas", "Obteniendo datos de la serie")
progreso = platformtools.dialog_progress(config.get_localized_string(30101), config.get_localized_string(70188))
scraper.find_and_set_infoLabels(item)
item.downloadFilename = filetools.validate_path("%s [%s]" % (item.contentSerieName, item.contentChannel))
progreso.update(0, "Obteniendo episodios...", "conectando con %s..." % item.contentChannel)
progreso.update(0, config.get_localized_string(70186), config.get_localized_string(70187) % item.contentChannel)
episodes = get_episodes(item)
progreso.update(0, "Añadiendo capitulos...", " ")
progreso.update(0, config.get_localized_string(70190), " ")
for x, i in enumerate(episodes):
progreso.update(x * 100 / len(episodes),
@@ -852,7 +852,7 @@ def save_download_tvshow(item):
write_json(i)
progreso.close()
if not platformtools.dialog_yesno(config.get_localized_string(30101), "¿Iniciar la descarga ahora?"):
if not platformtools.dialog_yesno(config.get_localized_string(30101), config.get_localized_string(70189)):
platformtools.dialog_ok(config.get_localized_string(30101),
str(len(episodes)) + " capitulos de: " + item.contentSerieName,
config.get_localized_string(30109))

View File

@@ -680,6 +680,8 @@ def episodios(item):
del item_local.update_last
if item_local.update_next:
del item_local.update_next
if item_local.channel_host:
del item_local.channel_host
#Verificamos el idioma por si encontramos algo
if not item_local.language:

View File

@@ -1,7 +1,7 @@
{
"id": "guaridavalencianista",
"name": "La Guarida valencianista",
"active": true,
"active": false,
"adult": false,
"language": ["cast"],
"thumbnail": "guaridavalencianista.png",
@@ -9,4 +9,4 @@
"categories": [
"documentary"
]
}
}

View File

@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
import os
import xbmc
from core.item import Item
from platformcode import config, logger, platformtools
@@ -41,50 +40,50 @@ def mainlist(item):
logger.info()
itemlist = []
itemlist.append(Item(channel=item.channel, action="", title="FAQ:",
thumbnail=get_thumb("help.png"),
folder=False))
if config.is_xbmc():
itemlist.append(Item(channel=item.channel, action="", title="FAQ:",
thumbnail=get_thumb("help.png"),
folder=False))
itemlist.append(Item(channel=item.channel, action="faq",
title=" - ¿Cómo reportar un error?",
thumbnail=get_thumb("help.png"),
folder=False, extra="report_error"))
itemlist.append(Item(channel=item.channel, action="faq",
title=" - ¿Se pueden activar/desactivar los canales?",
thumbnail=get_thumb("help.png"),
folder=False, extra="onoff_canales"))
itemlist.append(Item(channel=item.channel, action="faq",
title=" - ¿Es posible la sincronización automática con Trakt?",
thumbnail=get_thumb("help.png"),
folder=False, extra="trakt_sync"))
itemlist.append(Item(channel=item.channel, action="faq",
title=" - ¿Es posible mostrar todos los resultados juntos en el buscador global?",
thumbnail=get_thumb("help.png"),
folder=False, extra="buscador_juntos"))
itemlist.append(Item(channel=item.channel, action="faq",
title=" - Los enlaces tardan en aparecer.",
thumbnail=get_thumb("help.png"),
folder=False, extra="tiempo_enlaces"))
itemlist.append(Item(channel=item.channel, action="faq",
title=" - La búsqueda de contenido no se hace correctamente.",
thumbnail=get_thumb("help.png"),
folder=False, extra="prob_busquedacont"))
itemlist.append(Item(channel=item.channel, action="faq",
title=" - Algún canal no funciona correctamente.",
thumbnail=get_thumb("help.png"),
folder=False, extra="canal_fallo"))
itemlist.append(Item(channel=item.channel, action="faq",
title=" - Los enlaces Torrent no funcionan.",
thumbnail=get_thumb("help.png"),
folder=False, extra="prob_torrent"))
itemlist.append(Item(channel=item.channel, action="faq",
title=" - No se actualiza correctamente la videoteca.",
thumbnail=get_thumb("help.png"),
folder=True, extra="prob_bib"))
itemlist.append(Item(channel=item.channel, action="faq",
title=" - Enlaces de interés",
thumbnail=get_thumb("help.png"),
folder=False, extra=""))
itemlist.append(Item(channel=item.channel, action="faq",
title=" - ¿Se pueden activar/desactivar los canales?",
thumbnail=get_thumb("help.png"),
folder=False, extra="onoff_canales"))
itemlist.append(Item(channel=item.channel, action="faq",
title=" - ¿Es posible la sincronización automática con Trakt?",
thumbnail=get_thumb("help.png"),
folder=False, extra="trakt_sync"))
itemlist.append(Item(channel=item.channel, action="faq",
title=" - ¿Es posible mostrar todos los resultados juntos en el buscador global?",
thumbnail=get_thumb("help.png"),
folder=False, extra="buscador_juntos"))
itemlist.append(Item(channel=item.channel, action="faq",
title=" - Los enlaces tardan en aparecer.",
thumbnail=get_thumb("help.png"),
folder=False, extra="tiempo_enlaces"))
itemlist.append(Item(channel=item.channel, action="faq",
title=" - La búsqueda de contenido no se hace correctamente.",
thumbnail=get_thumb("help.png"),
folder=False, extra="prob_busquedacont"))
itemlist.append(Item(channel=item.channel, action="faq",
title=" - Algún canal no funciona correctamente.",
thumbnail=get_thumb("help.png"),
folder=False, extra="canal_fallo"))
itemlist.append(Item(channel=item.channel, action="faq",
title=" - Los enlaces Torrent no funcionan.",
thumbnail=get_thumb("help.png"),
folder=False, extra="prob_torrent"))
itemlist.append(Item(channel=item.channel, action="faq",
title=" - No se actualiza correctamente la videoteca.",
thumbnail=get_thumb("help.png"),
folder=True, extra="prob_bib"))
itemlist.append(Item(channel=item.channel, action="faq",
title=" - Enlaces de interés",
thumbnail=get_thumb("help.png"),
folder=False, extra=""))
return itemlist
@@ -192,6 +191,7 @@ def faq(item):
search.settings("")
elif item.extra == "report_error":
import xbmc
if config.get_platform(True)['num_version'] < 14:
log_name = "xbmc.log"
else:

View File

@@ -54,8 +54,8 @@ def start(item, recomendaciones=[], from_window=False):
global SearchWindows
SearchWindows = list()
dialog = platformtools.dialog_progress("Cargando nuevos datos",
"Buscandoen Tmdb.......")
dialog = platformtools.dialog_progress(config.get_localized_string(60469),
config.get_localized_string(60470))
principal_window = main(item=item, recomendaciones=recomendaciones, dialog=dialog, from_window=from_window)
try:
@@ -101,7 +101,7 @@ class main(xbmcgui.WindowDialog):
self.item.infoLabels.pop("episode", None)
if not self.item.infoLabels["year"]:
self.dialog.close()
platformtools.dialog_notification("Sin resultados. Falta información del año del video", "No hay info de la %s solicitada" % tipo)
platformtools.dialog_notification(config.get_localized_string(60471), config.get_localized_string(60472) % tipo)
global mainWindow
self.close()
del mainWindow
@@ -113,7 +113,7 @@ class main(xbmcgui.WindowDialog):
if not self.infoLabels["tmdb_id"]:
self.dialog.close()
platformtools.dialog_notification("Sin resultados", "No hay info de la %s solicitada" % tipo)
platformtools.dialog_notification(config.get_localized_string(60473), config.get_localized_string(60474) % tipo)
global mainWindow
self.close()
del mainWindow
@@ -133,30 +133,30 @@ class main(xbmcgui.WindowDialog):
rating = "[COLOR crimson][B]%s[/B][/COLOR]" % self.infoLabels["rating"]
self.dialog.update(40,
'Registrando filmaffinity.......')
config.get_localized_string(60475))
rating_fa, plot_fa = get_filmaf(self.item, self.infoLabels)
if not self.infoLabels.get("plot") and plot_fa:
self.infoLabels["plot"] = "[COLOR moccasin][B]%s[/B][/COLOR]" % plot_fa
elif not self.infoLabels["plot"]:
self.infoLabels["plot"] = "[COLOR yellow][B]Esta pelicula no tiene informacion...[/B][/COLOR]"
self.infoLabels["plot"] = config.get_localized_string(60476)
else:
self.infoLabels["plot"] = "[COLOR moccasin][B]%s[/B][/COLOR]" % self.infoLabels.get("plot")
self.dialog.update(60, 'Indagando recomendaciones.......')
self.dialog.update(60, config.get_localized_string(60477))
thread1 = Thread(target=get_recomendations, args=[self.item, self.infoLabels, self.recomendaciones])
thread1.setDaemon(True)
thread1.start()
if self.infoLabels.get("status") == "Ended" and tipo == "serie":
status = "[COLOR aquamarine][B]Finalizada %s[/B][/COLOR]"
status = config.get_localized_string(60478)
elif self.infoLabels.get("status") and tipo == "serie":
status = "[COLOR aquamarine][B]En emisión %s[/B][/COLOR]"
status = config.get_localized_string(60479)
else:
status = "[COLOR aquamarine][B]%s[/B][/COLOR]"
if self.infoLabels.get("tagline") and tipo == "serie":
self.infoLabels["tagline"] = status % "(" + self.infoLabels["tagline"] + ")"
elif not self.infoLabels.get("tagline") and tipo == "serie":
self.infoLabels["tagline"] = status % "(Temporadas: %s)" % self.infoLabels.get("number_of_seasons",
self.infoLabels["tagline"] = status % config.get_localized_string(60480) % self.infoLabels.get("number_of_seasons",
"---")
else:
self.infoLabels["tagline"] = status % self.infoLabels.get("tagline", "")
@@ -184,7 +184,7 @@ class main(xbmcgui.WindowDialog):
if self.item.contentType != "movie":
self.dialog.update(60,
'Recopilando imágenes en FANART.TV')
config.get_localized_string(60481))
try:
###Busca música serie
titulo = re.sub('\[.*?\]', '', titulo)
@@ -210,9 +210,9 @@ class main(xbmcgui.WindowDialog):
logger.error(traceback.format_exc())
if xbmc.Player().isPlaying():
self.dialog.update(80, 'Afinado instrumentos en Vtunes')
self.dialog.update(80, config.get_localized_string(60482))
else:
self.dialog.update(80, 'Recopilando imágenes en FANART.TV')
self.dialog.update(80, config.get_localized_string(60483))
while thread2.isAlive():
xbmc.sleep(100)
@@ -337,7 +337,7 @@ class main(xbmcgui.WindowDialog):
[('conditional', 'effect=fade start=0% end=100% delay=2000 time=1500 condition=true',),
('WindowClose', 'effect=fade start=100% end=0% time=800 condition=true',)])
self.duration.setText(
"[COLOR mediumturquoise][B]Duración: %s minutos[/B][/COLOR]" % self.infoLabels["duration"])
config.get_localized_string(70252) % self.infoLabels["duration"])
self.addControl(self.rating)
if set_animation:
self.rating.setAnimations(
@@ -741,8 +741,8 @@ class main(xbmcgui.WindowDialog):
else:
for boton, peli, id, poster2 in self.idps:
if control == boton:
dialog = platformtools.dialog_progress("Cargando nueva info",
"Buscando en Tmdb.......")
dialog = platformtools.dialog_progress(config.get_localized_string(60486),
config.get_localized_string(60487))
tipo = self.item.contentType
if tipo != "movie":
tipo = "tv"
@@ -834,7 +834,7 @@ class related(xbmcgui.WindowDialog):
[('conditional', 'effect=slide delay=6000 start=2000 time=800 condition=true',),
('WindowClose', 'effect=slide end=0,-700% time=1000 condition=true',)])
self.info = "[COLOR lemonchiffon]%s[/COLOR]" % self.infoLabels.get("plot", "Sin información...")
self.info = "[COLOR lemonchiffon]%s[/COLOR]" % self.infoLabels.get("plot", config.get_localized_string(60488))
self.info_peli = xbmcgui.ControlTextBox(455, 120, 750, 234)
self.addControl(self.info_peli)
@@ -923,7 +923,7 @@ class related(xbmcgui.WindowDialog):
self.paist_peli = xbmcgui.ControlTextBox(210, 435, 400, 60, self.fonts["12"])
self.addControl(self.paist_peli)
self.paist_peli.setText("[COLOR limegreen][B]País: [/B][/COLOR]")
self.paist_peli.setText(config.get_localized_string(60490))
if set_animation:
self.paist_peli.setAnimations(
[('conditional', 'effect=slide start=0,-700 delay=5650 time=700 condition=true tween=circle easing=in',),
@@ -939,7 +939,7 @@ class related(xbmcgui.WindowDialog):
self.ft_peli = xbmcgui.ControlTextBox(210, 460, 1100, 60, self.fonts["12"])
self.addControl(self.ft_peli)
self.ft_peli.setText("[COLOR limegreen][B]Estreno: [/B][/COLOR]")
self.ft_peli.setText(config.get_localized_string(60491))
if set_animation:
self.ft_peli.setAnimations(
[('conditional', 'effect=slide start=0,-700 delay=5600 time=700 condition=true tween=circle easing=in',),
@@ -959,7 +959,7 @@ class related(xbmcgui.WindowDialog):
if self.infoLabels.get("number_of_seasons"):
self.seasons_txt = xbmcgui.ControlTextBox(210, 485, 200, 60, self.fonts["12"])
self.addControl(self.seasons_txt)
self.seasons_txt.setText("[COLOR limegreen][B]Temporadas/Episodios: [/B][/COLOR]")
self.seasons_txt.setText(config.get_localized_string(60492))
if set_animation:
self.seasons_txt.setAnimations([('conditional',
'effect=slide start=0,-700 delay=5600 time=700 condition=true tween=circle easing=in',),
@@ -1234,9 +1234,9 @@ class Busqueda(xbmcgui.WindowXMLDialog):
except:
pass
if self.item.contentType != "movie":
self.getControl(1).setLabel("[COLOR orange][B]¿Está la serie que buscas?[/B][/COLOR]")
self.getControl(1).setLabel(config.get_localized_string(60493))
else:
self.getControl(1).setLabel("[COLOR orange][B]¿Está la película que buscas?[/B][/COLOR]")
self.getControl(1).setLabel(config.get_localized_string(60494))
self.getControl(5).setLabel("[COLOR tomato][B]Cerrar[/B][/COLOR]")
self.control_list.reset()
@@ -1256,7 +1256,7 @@ class Busqueda(xbmcgui.WindowXMLDialog):
def onAction(self, action):
global BusquedaWindow
if (action == ACTION_SELECT_ITEM or action == 100) and self.getFocusId() == 6:
dialog = platformtools.dialog_progress_bg("Cargando resultados", "Espere........")
dialog = platformtools.dialog_progress_bg(config.get_localized_string(60496), config.get_localized_string(60497))
selectitem = self.getControl(6).getSelectedItem()
item = Item().fromurl(selectitem.getProperty("item_copy"))
exec "import channels." + item.channel + " as channel"
@@ -1289,8 +1289,8 @@ class GlobalSearch(xbmcgui.WindowXMLDialog):
except:
pass
self.getControl(1).setLabel("[COLOR orange][B]Selecciona...[/B][/COLOR]")
self.getControl(5).setLabel("[COLOR tomato][B]Cerrar[/B][/COLOR]")
self.getControl(1).setLabel(config.get_localized_string(60498))
self.getControl(5).setLabel(config.get_localized_string(60495))
self.control_list.reset()
if not self.lista:
global SearchWindows
@@ -1327,7 +1327,7 @@ class GlobalSearch(xbmcgui.WindowXMLDialog):
item = itemlist[0]
else:
ventana_error = xbmcgui.Dialog()
ok = ventana_error.ok("plugin", "No hay nada para reproducir")
ok = ventana_error.ok("plugin", config.get_localized_string(60500))
return
global BusquedaWindow, exit_loop, mainWindow, ActorInfoWindow, relatedWindow, ActoresWindow
@@ -1375,7 +1375,7 @@ class GlobalSearch(xbmcgui.WindowXMLDialog):
else:
try:
dialog = platformtools.dialog_progress_bg("Cargando resultados", "Espere........")
dialog = platformtools.dialog_progress_bg(config.get_localized_string(60496), config.get_localized_string(60497))
itemlist = getattr(channel, item.action)(item)
window = GlobalSearch('DialogSelect.xml', config.get_runtime_path(), itemlist=itemlist,
dialog=dialog)
@@ -1416,8 +1416,8 @@ class Actores(xbmcgui.WindowXMLDialog):
self.getControl(3).setVisible(0)
except:
pass
self.getControl(1).setLabel("[COLOR orange][B]Reparto[/B][/COLOR]")
self.getControl(5).setLabel("[COLOR red][B]Cerrar[/B][/COLOR]")
self.getControl(1).setLabel(config.get_localized_string(60501))
self.getControl(5).setLabel(config.get_localized_string(60495))
self.control_list.reset()
items = []
@@ -1470,8 +1470,8 @@ class Actores(xbmcgui.WindowXMLDialog):
name_info = selectitem.getProperty("name_info")
thumbnail = selectitem.getProperty("thumbnail")
job = selectitem.getProperty("job")
dialog = platformtools.dialog_progress("Cargando nuevos datos",
"Obteniendo datos del %s..." % job.lower())
dialog = platformtools.dialog_progress(config.get_localized_string(60502),
config.get_localized_string(60503) % job.lower())
global ActorInfoWindow
ActorInfoWindow = ActorInfo(id=id_actor, name=name_info, thumbnail=thumbnail, item=self.item,
@@ -1542,7 +1542,7 @@ class ActorInfo(xbmcgui.WindowDialog):
bio = dhe(scrapertools.htmlclean(info.strip()))
actor_tmdb.result["biography"] = bio
else:
actor_tmdb.result["biography"] = "Sin información"
actor_tmdb.result["biography"] = config.get_localized_string(60504)
elif not actor_tmdb.result.get("biography"):
actor_tmdb.result["biography"] = "Sin información"
@@ -1579,7 +1579,7 @@ class ActorInfo(xbmcgui.WindowDialog):
xbmc.executebuiltin(
'Notification([COLOR red][B]Actualiza Kodi a su última versión[/B][/COLOR], [COLOR skyblue]para mejor info[/COLOR],8000, "http://i.imgur.com/mHgwcn3.png")')
self.info_actor.setText(
"[COLOR coral][B]%s[/B][/COLOR]" % actor_tmdb.result.get("biography", "Sin información"))
"[COLOR coral][B]%s[/B][/COLOR]" % actor_tmdb.result.get("biography", config.get_localized_string(60504)))
self.titulos = []
tipo_busqueda = "cast"
@@ -1914,8 +1914,8 @@ class ActorInfo(xbmcgui.WindowDialog):
for boton, peli, id, poster2 in self.idps:
if control == boton:
dialog = platformtools.dialog_progress("Cargando nueva info",
"Buscando en Tmdb.......")
dialog = platformtools.dialog_progress(config.get_localized_string(60486),
config.get_localized_string(60487))
tipo = self.item.contentType
if tipo != "movie":
tipo = "tv"
@@ -2177,8 +2177,8 @@ class Trailer(xbmcgui.WindowXMLDialog):
def onInit(self):
self.setCoordinateResolution(0)
if not self.video_url:
platformtools.dialog_notification("[COLOR crimson][B]Error[/B][/COLOR]",
"[COLOR tomato]Vídeo no disponible[/COLOR]", 2)
platformtools.dialog_notification(config.get_localized_string(60507),
config.get_localized_string(60508), 2)
self.close()
elif self.video_url == "no_video":
self.close()

View File

@@ -495,7 +495,7 @@ def listado_busqueda(item):
matches += re.compile(patron, re.DOTALL).findall(data)
matches_cnt = len(matches)
if not matches and not 'Se han encontrado <b>0</b> resultados.' in data: #error
if not matches and not 'Se han encontrado <b>0</b> resultados.' and not "href='/juego-descargar-torrent" in data: #error
logger.error("ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
@@ -828,6 +828,21 @@ def episodios(item):
item_local.action = "findvideos"
item_local.contentType = "episode"
item_local.extra = "episodios"
if item_local.library_playcounts:
del item_local.library_playcounts
if item_local.library_urls:
del item_local.library_urls
if item_local.path:
del item_local.path
if item_local.update_last:
del item_local.update_last
if item_local.update_next:
del item_local.update_next
if item_local.channel_host:
del item_local.channel_host
item_local.title = ''
item_local.context = "['buscar_trailer']"
item_local.url = urlparse.urljoin(host, scrapedurl)

View File

@@ -12,40 +12,53 @@ from core import httptools
from core import scrapertools
from core import servertools
from core.item import Item
from platformcode import config, logger
from platformcode import config, logger, platformtools
from core import tmdb
from lib import generictools
host = 'http://mispelisyseries.com/'
channel_py = 'newpct1'
#Código para permitir usar un único canal para todas las webs clones de NewPct1
clone_list = config.get_setting('clonenewpct1_channels_list', "torrentrapid") #Carga lista de clones
clone_list = ast.literal_eval(clone_list) #la convierte a lista de tuplas
clone_list = config.get_setting('clonenewpct1_channels_list', channel_py) #Carga lista de clones
clone_list = ast.literal_eval(clone_list) #la convierte en array
host_index = 0
host_index = config.get_setting('clonenewpct1_channel_default', "torrentrapid") #Clone por defecto
host_index = config.get_setting('clonenewpct1_channel_default', channel_py) #Clone por defecto
i = 0
for active_clone, channel_clone, host_clone, contentType_clone, info_clone in clone_list:
if i == host_index:
#channel_clone_name = channel_clone #ACTIVAR CUANDO SE PASE A NEWPCT1
#host = 'http://%s/' % host_clone #ACTIVAR CUANDO SE PASE A NEWPCT1
i += 1
channel_clone_name = channel_clone #Nombre del Canal elegido
host = host_clone #URL del Canal elegido
break
i += 1
item = Item()
item.channel_host = host
if item.channel != channel_py:
item.channel = channel_py
item.category = channel_clone_name.capitalize()
#Carga de opciones del canal
item = Item()
if not item.channel:
item.channel = scrapertools.find_single_match(host, r'(\w+)\.com\/')
channel_clone_name = scrapertools.find_single_match(host, r'(\w+)\.com\/') #QUITAR CUANDO SE PASE A NEWPCT1
__modo_grafico__ = config.get_setting('modo_grafico', item.channel)
modo_ultima_temp = config.get_setting('seleccionar_ult_temporadda_activa', item.channel)
__modo_grafico__ = config.get_setting('modo_grafico', channel_py) #TMDB?
modo_ultima_temp = config.get_setting('seleccionar_ult_temporadda_activa', channel_py) #Actualización sólo últ. Temporada?
timeout = config.get_setting('clonenewpct1_timeout_downloadpage', channel_py) #Timeout downloadpage
if timeout == 0: timeout = None
platformtools.dialog_ok("NewPct1, ¡¡¡he vuelto como canal VIRTUAL!!!", "Hemos centralizado la gestión de los clones de NewPct1 en el canal virtual NewPct1. Los clones desaparecerán en breve.", "Para más información lee el tutorial: https://alfa-addon.com /threads/newpct1-implantando-alta-disponibilidad.1200/")
#Vayamos a la siguiente acción en el canal Newpct1
from platformcode import launcher
channel_clone_name = "mispelisyseries" #Nombre del Canal elegido
host = "http://mispelisyseries.com/"
item.category = channel_clone_name.capitalize()
item.action = "mainlist"
item.channel_host = host
launcher.run(item)
def mainlist(item):
logger.info()
if item.channel != channel_py:
return
#Renombramos el canal al nombre de clone elegido
item.channel = channel_clone_name
if item.category: item.category = channel_clone_name.capitalize()
itemlist = []
thumb_pelis = get_thumb("channels_movie.png")
@@ -58,20 +71,20 @@ def mainlist(item):
thumb_settings = get_thumb("setting_0.png")
itemlist.append(Item(channel=item.channel, action="submenu", title="Películas", url=host,
extra="peliculas", thumbnail=thumb_pelis ))
extra="peliculas", thumbnail=thumb_pelis, category=item.category))
itemlist.append(Item(channel=item.channel, action="submenu", title="Series", url=host, extra="series",
thumbnail=thumb_series))
thumbnail=thumb_series, category=item.category))
itemlist.append(Item(channel=item.channel, action="submenu", title="Documentales", url=host, extra="varios",
thumbnail=thumb_docus))
thumbnail=thumb_docus, category=item.category))
itemlist.append(
Item(channel=item.channel, action="search", title="Buscar", url=host + "buscar", thumbnail=thumb_buscar))
Item(channel=item.channel, action="search", title="Buscar", url=host + "buscar", thumbnail=thumb_buscar, category=item.category))
itemlist.append(
Item(channel=item.channel, action="", title="[COLOR yellow]Configuración de Servidores:[/COLOR]", url="", thumbnail=thumb_settings))
Item(channel=item.channel, action="", title="[COLOR yellow]Configuración de Servidores:[/COLOR]", url="", thumbnail=thumb_settings, category=item.category))
itemlist.append(
Item(channel=item.channel, action="settingCanal", title="Servidores para Ver Online y Descargas", url="", thumbnail=thumb_settings))
Item(channel=item.channel, action="settingCanal", title="Servidores para Ver Online y Descargas", url="", thumbnail=thumb_settings, category=item.category))
return itemlist
@@ -85,68 +98,60 @@ def submenu(item):
logger.info()
itemlist = []
data = ''
try:
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data)
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data)
except:
pass
host_alt = host
host_dom = host.replace("https://", "").replace("http://", "").replace("www.", "")
patron = '<li><a href="http://(?:www.)?' + host_dom + item.extra + '/">.*?<ul.*?>(.*?)</ul>'
patron = '<li><a\s?class="[^"]+"\s?href="http:[^"]+"><i\s?class=.*><\/i>.*Inicio<\/a><\/li>(.+)<\/ul>\s?<\/nav>'
#Verificamos si se ha cargado una página, y si además tiene la estructura correcta
if not data or not scrapertools.find_single_match(data, patron):
logger.error("ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL: " + item.url)
logger.error("ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL: " + item.url + data)
#Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú
item, data = generictools.fail_over_newpct1(item, patron)
if not data: #Si no ha logrado encontrar nada, salimos
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
elif item.channel_alt: #Si ha habido fail-over, lo comento
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR] [ALT ] en uso'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] caído'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR] [ALT ] en uso'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] inaccesible'))
host_alt = host.replace(item.channel_alt, item.channel)
del item.channel_alt
if item.url_alt: del item.url_alt
del item.channel_alt
#data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8")
#data = data.replace("'", '"').replace('/series"', '/series/"') #Compatibilidad con mispelisy.series.com
host_dom = host_alt.replace("https://", "").replace("http://", "").replace("www.", "")
patron = '<li><a href="http://(?:www.)?' + host_dom + item.extra + '/">.*?<ul.*?>(.*?)</ul>'
if "pelisyseries.com" in host_alt and item.extra == "varios": #compatibilidad con mispelisy.series.com
data = '<a href="' + host_alt + 'varios/" title="Documentales"><i class="icon-rocket"></i> Documentales</a>'
data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8")
data = data.replace("'", '"').replace('/series"', '/series/"') #Compatibilidad con mispelisy.series.com
if "pelisyseries.com" in item.channel_host and item.extra == "varios": #compatibilidad con mispelisy.series.com
data = '<li><a href="' + item.channel_host + 'varios/" title="Documentales">Documentales</a></li>'
else:
if data:
data = scrapertools.get_match(data, patron)
if not data:
logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
else:
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
data = scrapertools.get_match(data, patron) #Seleccionamos el trozo que nos interesa
if not data:
logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
patron = '<.*?href="([^"]+)".*?>([^>]+)</a>'
patron = '<li><a.*?href="([^"]+)"\s?.itle="[^"]+"\s?>([^>]+)<\/a><\/li>'
matches = re.compile(patron, re.DOTALL).findall(data)
if not matches:
logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
for scrapedurl, scrapedtitle in matches:
title = scrapedtitle.strip()
url = scrapedurl
itemlist.append(Item(channel=item.channel, action="listado", title=title, url=url, extra=item.extra))
itemlist.append(
Item(channel=item.channel, action="alfabeto", title=title + " [A-Z]", url=url, extra=item.extra))
#Preguntamos por las entradas que no corresponden al "extra"
if item.extra in scrapedtitle.lower() or (item.extra == "peliculas" and ("cine" in scrapedurl or "anime" in scrapedurl)) or (item.extra == "varios" and ("documentales" in scrapedurl or "varios" in scrapedurl)):
itemlist.append(item.clone(action="listado", title=title, url=scrapedurl))
itemlist.append(item.clone(action="alfabeto", title=title + " [A-Z]", url=scrapedurl))
if item.extra == "peliculas":
itemlist.append(Item(channel=item.channel, action="listado", title="Películas 4K", url=host_alt + "peliculas-hd/4kultrahd/", extra=item.extra))
itemlist.append(
Item(channel=item.channel, action="alfabeto", title="Películas 4K" + " [A-Z]", url=host_alt + "peliculas-hd/4kultrahd/", extra=item.extra))
itemlist.append(item.clone(action="listado", title="Películas 4K", url=item.channel_host + "peliculas-hd/4kultrahd/"))
itemlist.append(item.clone(action="alfabeto", title="Películas 4K" + " [A-Z]", url=item.channel_host + "peliculas-hd/4kultrahd/"))
return itemlist
@@ -155,28 +160,41 @@ def alfabeto(item):
logger.info()
itemlist = []
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data)
data = ''
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data)
data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8")
patron = '<ul class="alfabeto">(.*?)</ul>'
if data:
data = scrapertools.get_match(data, patron)
else:
return itemlist
if not data or not scrapertools.find_single_match(data, patron):
logger.error("ERROR 01: ALFABETO: La Web no responde o ha cambiado de URL: " + item.url + data)
#Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú
item, data = generictools.fail_over_newpct1(item, patron)
if not data: #Si no ha logrado encontrar nada, salimos
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: ALFABETO: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
elif item.channel_alt: #Si ha habido fail-over, lo comento
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR] [ALT ] en uso'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] inaccesible'))
if item.url_alt: del item.url_alt
del item.channel_alt
data = scrapertools.get_match(data, patron)
patron = '<a href="([^"]+)"[^>]+>([^>]+)</a>'
matches = re.compile(patron, re.DOTALL).findall(data)
if not matches:
logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log'))
logger.error("ERROR 02: ALFABETO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: ALFABETO: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
for scrapedurl, scrapedtitle in matches:
title = scrapedtitle.upper()
url = scrapedurl
itemlist.append(Item(channel=item.channel, action="listado", title=title, url=url, extra=item.extra))
itemlist.append(item.clone(action="listado", title=title, url=scrapedurl))
return itemlist
@@ -191,11 +209,21 @@ def listado(item):
if item.totalItems:
del item.totalItems
data = ''
try:
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data)
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data)
except:
pass
patron = '<ul class="' + clase + '">(.*?)</ul>' #seleccionamos el bloque que nos interesa
if not data or (not scrapertools.find_single_match(data, patron) and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data):
logger.error("ERROR 01: LISTADO: La Web no responde o ha cambiado de URL: " + item.url + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
#Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú
item, data = generictools.fail_over_newpct1(item, patron)
if not data: #Si no ha logrado encontrar nada, salimos
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: LISTADO: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
#Establecemos los valores básicos en función del tipo de contenido
@@ -218,7 +246,7 @@ def listado(item):
fichas = scrapertools.get_match(data, patron)
if not fichas and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data: #error
logger.error("ERROR 02: LISTADO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
elif '<h3><strong>( 0 ) Resultados encontrados </strong>' in data: #no hay vídeos
return itemlist
@@ -235,7 +263,7 @@ def listado(item):
matches = re.compile(patron, re.DOTALL).findall(fichas)
if not matches: #error
logger.error("ERROR 02: LISTADO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + fichas)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
#logger.debug("MATCHES: " + str(len(matches)))
@@ -460,13 +488,21 @@ def listado(item):
def listado_busqueda(item):
logger.info()
host = 'http://%s/' % scrapertools.find_single_match(item.url, '(\w+\.com)\/')
#Renombramos el canal al nombre de clone elegido. Actualizados URL
host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)')
#item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/')
if item.category and item.category != "newest":
item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize()
itemlist = []
cnt_tot = 40 # Poner el num. máximo de items por página. Dejamos que la web lo controle
cnt_title = 0 # Contador de líneas insertadas en Itemlist
cnt_pag = 0 # Contador de líneas leídas de Matches
timeout_search = 5 # Timeout un poco más largo para las búsquedas
if timeout > 5:
timeout_search = timeout # Timeout un poco más largo para las búsquedas
data = ''
if item.cnt_pag:
cnt_pag = item.cnt_pag # Se guarda en la lista de páginas anteriores en Item
@@ -493,21 +529,21 @@ def listado_busqueda(item):
#Máximo num. de líneas permitidas por TMDB. Máx de 5 páginas por Itemlist para no degradar el rendimiento
while cnt_title <= cnt_tot and cnt_next < 5:
pattern = '<ul class="%s">(.*?)</ul>' % item.pattern #seleccionamos el bloque que nos interesa
try:
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, post=item.post).data)
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, post=item.post, timeout=timeout_search).data)
except:
pass
cnt_next += 1
if not data or not scrapertools.find_single_match(data, pattern):
cnt_next += 1
pattern = '<ul class="%s">(.*?)</ul>' % item.pattern #seleccionamos el bloque que nos interesa
if not data or (not scrapertools.find_single_match(data, pattern) and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data):
logger.error("ERROR 01: LISTADO_BUSQUEDA: La Web no responde o ha cambiado de URL: " + item.url + item.post + " / DATA: " + data)
#Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú
item, data = generictools.fail_over_newpct1(item, pattern)
if not data: #Si no ha logrado encontrar nada, salimos
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO_BUSQUEDA:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: LISTADO_BUSQUEDA:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
elif item.channel_alt: #Si ha habido fail-over, lo comento
host = host.replace(item.channel_alt, item.channel)
@@ -531,7 +567,6 @@ def listado_busqueda(item):
pattern = '<ul class="%s">(.*?)</ul>' % item.pattern #seleccionamos el bloque que nos interesa
data_alt = data
data = scrapertools.get_match(data, pattern)
#pattern = '<li[^>]*><a href="(?P<url>[^"]+).*?<img.*?src="(?P<thumb>[^"]+)?".*?<h2.*?>(?P<title>.*?)?<\/h2>'
pattern = '<li[^>]*><a href="(?P<scrapedurl>[^"]+).*?' #url
pattern += 'title="(?P<scrapedtitle>[^"]+).*?' #título
pattern += '<img.*?src="(?P<scrapedthumbnail>[^"]+)?".*?' #thumb
@@ -541,7 +576,8 @@ def listado_busqueda(item):
matches_alt = re.compile(pattern, re.DOTALL).findall(data)
if not matches_alt and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data_alt: #error
logger.error("ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + data_alt)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web. Reportar el error con el log'))
item, itemlist = generictools.post_tmdb_listado(item, itemlist) #Pintamos los datos de fail-over, si los hay
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
#Ahora se hace una simulación para saber cuantas líneas podemos albergar en este Itemlist.
@@ -830,14 +866,14 @@ def listado_busqueda(item):
url_tvshow = host + calidad_mps + real_title_mps + "/" #... otras no. A probar...
#Leemos la página, a ver si es una página de episodios
data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_id).data)
data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_id, timeout=timeout).data)
data_serie = unicode(data_serie, "iso-8859-1", errors="replace").encode("utf-8")
data_serie = data_serie.replace("chapters", "buscar-list")
pattern = '<ul class="%s">(.*?)</ul>' % "buscar-list" #Patrón de lista de episodios
if not scrapertools.find_single_match(data_serie, pattern) and serieid: #no es válida la página,
#intentarlo con la otra url
data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_tvshow).data)
data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_tvshow, timeout=timeout).data)
data_serie = unicode(data_serie, "iso-8859-1", errors="replace").encode("utf-8")
data_serie = data_serie.replace("chapters", "buscar-list")
@@ -876,9 +912,10 @@ def findvideos(item):
from core import channeltools
logger.info()
#Renombramos el canal al nombre de clone elegido
item.channel = channel_clone_name
if item.category: item.category = channel_clone_name.capitalize()
#Renombramos el canal al nombre de clone elegido. Actualizados URL
host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)')
#item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/')
item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize()
itemlist = []
@@ -987,8 +1024,9 @@ def findvideos(item):
excluir_enlaces_descargas = [] #Lista vacía de servidores excluidos en Descargar
# Descarga la página
data = ''
try:
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data)
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data)
except:
pass
@@ -1001,7 +1039,7 @@ def findvideos(item):
item, data = generictools.fail_over_newpct1(item, patron)
if not data: #Si no ha logrado encontrar nada, salimos
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: FINDVIDEOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: FINDVIDEOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8")
@@ -1029,7 +1067,7 @@ def findvideos(item):
item_local.url = scrapertools.find_single_match(data, patron)
if not item_local.url: #error
logger.error("ERROR 02: FINDVIDEOS: El archivo Torrent no existe o ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: FINDVIDEOS: El archivo Torrent no existe o ha cambiado la estructura de la Web. Verificar en la Web y reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: FINDVIDEOS: El archivo Torrent no existe o ha cambiado la estructura de la Web. Verificar en la Web y reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
item_local.url = item_local.url.replace(" ", "%20") #sustituimos espacios por %20, por si acaso
#logger.debug("Patron: " + patron + " url: " + item_local.url)
@@ -1054,6 +1092,8 @@ def findvideos(item):
#logger.debug(item_local)
# VER vídeos, descargar vídeos un link, o múltiples links
data = scrapertools.find_single_match(data, '<div id="tab1" class="tab_content"(.*?<\/ul>(?:<div.*?>)?<\/div><\/div><\/div>)') #Seleccionar el bloque para evitar duplicados
host_dom = host.replace("https://", "").replace("http://", "").replace("www.", "")
data = data.replace("http://tumejorserie.com/descargar/url_encript.php?link=", "(")
data = re.sub(r'javascript:;" onClick="popup\("http:\/\/(?:www.)?' + host_dom + '\w{1,9}\/library\/include\/ajax\/get_modallinks.php\?links=', "", data)
@@ -1066,7 +1106,7 @@ def findvideos(item):
enlaces_ver = re.compile(patron, re.DOTALL).findall(data)
enlaces_descargar = enlaces_ver
#logger.debug(enlaces_ver)
#Recorre todos los links de VER, si está permitido
cnt_enl_ver = 1
cnt_enl_verif = 1
@@ -1100,7 +1140,7 @@ def findvideos(item):
if verificar_enlaces_veronline != 0: #Se quiere verificar si el link está activo?
if cnt_enl_verif <= verificar_enlaces_veronline or verificar_enlaces_veronline == -1: #contador?
#Llama a la subfunción de check_list_links(itemlist) para cada link de servidor
item_local.alive = servertools.check_video_link(enlace, servidor) #activo el link ?
item_local.alive = servertools.check_video_link(enlace, servidor, timeout=timeout) #activo el link ?
if verificar_enlaces_veronline_validos: #Los links tienen que ser válidos para contarlos?
if item_local.alive == "Ok": #Sí
cnt_enl_verif += 1 #Movemos los contadores
@@ -1190,7 +1230,7 @@ def findvideos(item):
if verificar_enlaces_descargas != 0: #Se quiere verificar si el link está activo?
if cnt_enl_verif <= verificar_enlaces_descargas or verificar_enlaces_descargas == -1: #contador?
#Llama a la subfunción de check_list_links(itemlist) para primer link de servidor
item_local.alive = servertools.check_video_link(enlace, servidor) #activo el link ?
item_local.alive = servertools.check_video_link(enlace, servidor, timeout=timeout) #activo el link ?
if verificar_enlaces_descargas_validos: #Los links tienen que ser válidos para contarlos?
if item_local.alive == "Ok": #Sí
cnt_enl_verif += 1 #Movemos los contadores
@@ -1232,9 +1272,10 @@ def findvideos(item):
def episodios(item):
logger.info()
#Renombramos el canal al nombre de clone elegido
item.channel = channel_clone_name
if item.category: item.category = channel_clone_name.capitalize()
#Renombramos el canal al nombre de clone elegido. Actualizados URL
host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)')
#item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/')
item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize()
itemlist = []
@@ -1255,7 +1296,7 @@ def episodios(item):
data = ''
try:
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url).data)
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, timeout=timeout).data)
patron = '<ul class="%s">(.*?)</ul>' % "buscar-list" # item.pattern
data_alt = ''
if data: data_alt = scrapertools.get_match(data, patron)
@@ -1276,7 +1317,7 @@ def episodios(item):
if not data: #No se ha encontrado ningún canal activo para este vídeo
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: EPISODIOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: EPISODIOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log'))
return itemlist
#Busca y pre-carga todas las páginas de episodios que componen las serie, para obtener la url de cada página
@@ -1312,7 +1353,7 @@ def episodios(item):
break
try:
if not data:
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(page).data)
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(page, timeout=timeout).data)
data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8")
data = data.replace("chapters", "buscar-list") #Compatibilidad con mispelisy.series.com
pattern = '<ul class="%s">(.*?)</ul>' % "buscar-list" # item.pattern
@@ -1321,7 +1362,7 @@ def episodios(item):
raise
except:
logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / " + str(list_pages) + " / DATA: " + str(data))
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
if "pelisyseries.com" in item.url:
@@ -1331,7 +1372,7 @@ def episodios(item):
matches = re.compile(pattern, re.DOTALL).findall(data)
if not matches: #error
logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
#logger.debug("patron: " + pattern)
@@ -1399,7 +1440,7 @@ def episodios(item):
match = [m.groupdict() for m in r.finditer(info)][0]
if not match: #error
logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + info)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
if match['season'] is None: match['season'] = season #Si no se encuentran valores, pero poner lo básico
@@ -1449,8 +1490,6 @@ def episodios(item):
if item_local.active:
del item_local.active
if item_local.category:
del item_local.category
if item_local.infoLabels['title']:
del item_local.infoLabels['title']
item_local.context = "['buscar_trailer']"
@@ -1467,6 +1506,8 @@ def episodios(item):
del item_local.update_last
if item_local.update_next:
del item_local.update_next
if item_local.channel_host:
del item_local.channel_host
itemlist.append(item_local.clone())
@@ -1501,9 +1542,6 @@ def actualizar_titulos(item):
def search(item, texto):
logger.info("search:" + texto)
# texto = texto.replace(" ", "+")
item.channel = channel_clone_name
if item.category: item.category = channel_clone_name.capitalize()
try:
item.post = "q=%s" % texto

View File

@@ -0,0 +1,565 @@
{
"id": "newpct1",
"name": "Newpct1",
"active": true,
"adult": false,
"language": ["*"],
"thumbnail": "newpct1.png",
"banner": "newpct1.png",
"categories": [
"movie",
"tvshow",
"anime",
"torrent",
"latino",
"documentary",
"vos",
"direct"
],
"settings": [
{
"id": "include_in_global_search",
"type": "bool",
"label": "Incluir en busqueda global",
"default": true,
"enabled": true,
"visible": true
},
{
"id": "modo_grafico",
"type": "bool",
"label": "Buscar información extra (TMDB)",
"default": true,
"enabled": true,
"visible": true
},
{
"id": "clonenewpct1_channel_default",
"type": "list",
"label": "Clone de NewPct1 por defecto",
"default": 0,
"enabled": true,
"visible": true,
"lvalues": [
"Torrentrapid",
"Torrentlocura",
"Tumejortorrent",
"Tvsinpagar",
"Descargas2020",
"Mispelisyseries"
]
},
{
"id": "clonenewpct1_channels_list",
"type": "text",
"label": "Lista de clones de NewPct1 y orden de uso",
"default": "('1', 'torrentrapid', 'http://torrentrapid.com/', 'movie, tvshow, season, episode', ''), ('1', 'torrentlocura', 'http://torrentlocura.com/', 'movie, tvshow, season, episode', ''), ('1', 'tumejortorrent', 'http://tumejortorrent.com/', 'movie, tvshow, season, episode', ''), ('1', 'tvsinpagar', 'http://www.tvsinpagar.com/', 'tvshow, season, episode', ''), ('1', 'descargas2020', 'http://descargas2020.com/', 'movie, tvshow, season, episode', ''), ('1', 'mispelisyseries', 'http://mispelisyseries.com/', 'movie', 'search')",
"enabled": true,
"visible": false
},
{
"id": "seleccionar_ult_temporadda_activa",
"type": "bool",
"label": "Seleccionar para Videoteca si estará activa solo la última Temporada",
"default": true,
"enabled": true,
"visible": true
},
{
"id": "clonenewpct1_ver_enlaces_veronline",
"type": "list",
"label": "Mostrar enlaces Ver Online",
"default": 1,
"enabled": true,
"visible": true,
"lvalues": [
"No",
"Todos",
"1",
"5",
"10",
"20"
]
},
{
"id": "clonenewpct1_verificar_enlaces_veronline",
"type": "list",
"label": "Verificar enlaces Ver Online",
"default": 1,
"enabled": true,
"visible": "!eq(-1,'No')",
"lvalues": [
"No",
"Todos",
"1",
"5",
"10",
"20"
]
},
{
"id": "clonenewpct1_verificar_enlaces_veronline_validos",
"type": "bool",
"label": "¿Contar sólo enlaces 'verificados' en Ver Online?",
"default": true,
"enabled": true,
"visible": "!eq(-1,'No') + !eq(-2,'No')"
},
{
"id": "clonenewpct1_excluir1_enlaces_veronline",
"type": "list",
"label": "Excluir Servidores para Ver Online",
"default": 9,
"max_excl": 5,
"enabled": true,
"visible": "!eq(-3,'No')",
"lvalues": [
"No",
"Bankupload",
"Clipwatching",
"Flashx",
"Katfile",
"Mega",
"Mexashare",
"Movshare",
"Mowvideo",
"Openload",
"Powvideo",
"Rapidgator",
"Streamango",
"Streamcloud",
"Streame",
"Streaminto",
"Streamplay",
"Thevideo",
"Turbobit",
"Uploadedto",
"Uptobox",
"Userscloud",
"Vidabc",
"Vidspot"
]
},
{
"id": "clonenewpct1_excluir2_enlaces_veronline",
"type": "list",
"label": "Excluir Servidores para Ver Online",
"default": 12,
"enabled": true,
"visible": "!eq(-1,'No')",
"lvalues": [
"No",
"Bankupload",
"Clipwatching",
"Flashx",
"Katfile",
"Mega",
"Mexashare",
"Movshare",
"Mowvideo",
"Openload",
"Powvideo",
"Rapidgator",
"Streamango",
"Streamcloud",
"Streame",
"Streaminto",
"Streamplay",
"Thevideo",
"Turbobit",
"Uploadedto",
"Uptobox",
"Userscloud",
"Vidabc",
"Vidspot"
]
},
{
"id": "clonenewpct1_excluir3_enlaces_veronline",
"type": "list",
"label": "Excluir Servidores para Ver Online",
"default": 20,
"enabled": true,
"visible": "!eq(-1,'No')",
"lvalues": [
"No",
"Bankupload",
"Clipwatching",
"Flashx",
"Katfile",
"Mega",
"Mexashare",
"Movshare",
"Mowvideo",
"Openload",
"Powvideo",
"Rapidgator",
"Streamango",
"Streamcloud",
"Streame",
"Streaminto",
"Streamplay",
"Thevideo",
"Turbobit",
"Uploadedto",
"Uptobox",
"Userscloud",
"Vidabc",
"Vidspot"
]
},
{
"id": "clonenewpct1_excluir4_enlaces_veronline",
"type": "list",
"label": "Excluir Servidores para Ver Online",
"default": 0,
"enabled": true,
"visible": "!eq(-1,'No')",
"lvalues": [
"No",
"Bankupload",
"Clipwatching",
"Flashx",
"Katfile",
"Mega",
"Mexashare",
"Movshare",
"Mowvideo",
"Openload",
"Powvideo",
"Rapidgator",
"Streamango",
"Streamcloud",
"Streame",
"Streaminto",
"Streamplay",
"Thevideo",
"Turbobit",
"Uploadedto",
"Uptobox",
"Userscloud",
"Vidabc",
"Vidspot"
]
},
{
"id": "clonenewpct1_excluir5_enlaces_veronline",
"type": "list",
"label": "Excluir Servidores para Ver Online",
"default": 0,
"enabled": true,
"visible": "!eq(-1,'No')",
"lvalues": [
"No",
"Bankupload",
"Clipwatching",
"Flashx",
"Katfile",
"Mega",
"Mexashare",
"Movshare",
"Mowvideo",
"Openload",
"Powvideo",
"Rapidgator",
"Streamango",
"Streamcloud",
"Streame",
"Streaminto",
"Streamplay",
"Thevideo",
"Turbobit",
"Uploadedto",
"Uptobox",
"Userscloud",
"Vidabc",
"Vidspot"
]
},
{
"id": "clonenewpct1_ver_enlaces_descargas",
"type": "list",
"label": "Mostrar enlaces Descargas",
"default": 0,
"enabled": true,
"visible": true,
"lvalues": [
"No",
"Todos",
"1",
"5",
"10",
"20",
"30",
"50",
"100"
]
},
{
"id": "clonenewpct1_verificar_enlaces_descargas",
"type": "list",
"label": "Verificar enlaces Descargas",
"default": 1,
"enabled": true,
"visible": "!eq(-1,'No')",
"lvalues": [
"No",
"Todos",
"1",
"5",
"10",
"20",
"30",
"50",
"100"
]
},
{
"id": "clonenewpct1_verificar_enlaces_descargas_validos",
"type": "bool",
"label": "¿Contar sólo enlaces 'verificados' en Descargar?",
"default": true,
"enabled": true,
"visible": "!eq(-1,'No') + !eq(-2,'No')"
},
{
"id": "clonenewpct1_excluir1_enlaces_descargas",
"type": "list",
"label": "Excluir Servidores para Ver Descargas",
"default": 0,
"enabled": true,
"visible": "!eq(-3,'No')",
"lvalues": [
"No",
"Bankupload",
"Clipwatching",
"Flashx",
"Katfile",
"Mega",
"Mexashare",
"Movshare",
"Mowvideo",
"Openload",
"Powvideo",
"Rapidgator",
"Streamango",
"Streamcloud",
"Streame",
"Streaminto",
"Streamplay",
"Thevideo",
"Turbobit",
"Uploadedto",
"Uptobox",
"Userscloud",
"Vidabc",
"Vidspot"
]
},
{
"id": "clonenewpct1_excluir2_enlaces_descargas",
"type": "list",
"label": "Excluir Servidores para Ver Descargas",
"default": 0,
"enabled": true,
"visible": "!eq(-1,'No')",
"lvalues": [
"No",
"Bankupload",
"Clipwatching",
"Flashx",
"Katfile",
"Mega",
"Mexashare",
"Movshare",
"Mowvideo",
"Openload",
"Powvideo",
"Rapidgator",
"Streamango",
"Streamcloud",
"Streame",
"Streaminto",
"Streamplay",
"Thevideo",
"Turbobit",
"Uploadedto",
"Uptobox",
"Userscloud",
"Vidabc",
"Vidspot"
]
},
{
"id": "clonenewpct1_excluir3_enlaces_descargas",
"type": "list",
"label": "Excluir Servidores para Descargas",
"default": 0,
"enabled": true,
"visible": "!eq(-1,'No')",
"lvalues": [
"No",
"Bankupload",
"Clipwatching",
"Flashx",
"Katfile",
"Mega",
"Mexashare",
"Movshare",
"Mowvideo",
"Openload",
"Powvideo",
"Rapidgator",
"Streamango",
"Streamcloud",
"Streame",
"Streaminto",
"Streamplay",
"Thevideo",
"Turbobit",
"Uploadedto",
"Uptobox",
"Userscloud",
"Vidabc",
"Vidspot"
]
},
{
"id": "clonenewpct1_excluir4_enlaces_descargas",
"type": "list",
"label": "Excluir Servidores para Descargas",
"default": 0,
"enabled": true,
"visible": "!eq(-1,'No')",
"lvalues": [
"No",
"Bankupload",
"Clipwatching",
"Flashx",
"Katfile",
"Mega",
"Mexashare",
"Movshare",
"Mowvideo",
"Openload",
"Powvideo",
"Rapidgator",
"Streamango",
"Streamcloud",
"Streame",
"Streaminto",
"Streamplay",
"Thevideo",
"Turbobit",
"Uploadedto",
"Uptobox",
"Userscloud",
"Vidabc",
"Vidspot"
]
},
{
"id": "clonenewpct1_excluir5_enlaces_descargas",
"type": "list",
"label": "Excluir Servidores para Descargas",
"default": 0,
"enabled": true,
"visible": "!eq(-1,'No')",
"lvalues": [
"No",
"Bankupload",
"Clipwatching",
"Flashx",
"Katfile",
"Mega",
"Mexashare",
"Movshare",
"Mowvideo",
"Openload",
"Powvideo",
"Rapidgator",
"Streamango",
"Streamcloud",
"Streame",
"Streaminto",
"Streamplay",
"Thevideo",
"Turbobit",
"Uploadedto",
"Uptobox",
"Userscloud",
"Vidabc",
"Vidspot"
]
},
{
"id": "include_in_newest_peliculas",
"type": "bool",
"label": "Incluir en Novedades - Peliculas",
"default": true,
"enabled": true,
"visible": false
},
{
"id": "include_in_newest_series",
"type": "bool",
"label": "Incluir en Novedades - Episodios de series",
"default": true,
"enabled": true,
"visible": false
},
{
"id": "include_in_newest_anime",
"type": "bool",
"label": "Incluir en Novedades - Anime",
"default": true,
"enabled": true,
"visible": false
},
{
"id": "include_in_newest_documentales",
"type": "bool",
"label": "Incluir en Novedades - Documentales",
"default": true,
"enabled": true,
"visible": false
},
{
"id": "include_in_newest_latino",
"type": "bool",
"label": "Incluir en Novedades - Documentales",
"default": true,
"enabled": true,
"visible": false
},
{
"id": "include_in_newest_4k",
"type": "bool",
"label": "Incluir en Novedades - 4K",
"default": true,
"enabled": true,
"visible": false
},
{
"id": "clonenewpct1_timeout_downloadpage",
"type": "list",
"label": "Timeout (segs.) en descarga de páginas o verificación de servidores",
"default": 5,
"enabled": true,
"visible": true,
"lvalues": [
"None",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10"
]
}
]
}

File diff suppressed because it is too large Load Diff

View File

@@ -11,7 +11,7 @@
{
"id": "multithread",
"type": "bool",
"label": "Buscar de manera concurrente (multiprocesos)",
"label": "@60656",
"default": true,
"enabled": true,
"visible": true
@@ -19,14 +19,14 @@
{
"id": "result_mode",
"type": "list",
"label": "Mostrar resultados:",
"label": "@60657",
"default": 2,
"enabled": true,
"visible": true,
"lvalues": [
"Agrupados por contenido",
"Agrupados por canales",
"Sin Agrupar"
"@60658",
"@60659",
"@60660"
]
},
{
@@ -37,11 +37,11 @@
"enabled": true,
"visible": true,
"lvalues": [
"Frio",
"Calido",
"Lila",
"Pastel",
"Vivos"
"@60667",
"@60668",
"@60669",
"@60670",
"@60671"
]
}
]

View File

@@ -48,69 +48,69 @@ def mainlist(item):
#if list_canales['peliculas']:
thumbnail = get_thumb("channels_movie.png")
new_item = Item(channel=item.channel, action="novedades", extra="peliculas", title="Películas",
new_item = Item(channel=item.channel, action="novedades", extra="peliculas", title=config.get_localized_string(30122),
thumbnail=thumbnail)
set_category_context(new_item)
itemlist.append(new_item)
thumbnail = get_thumb("channels_movie_4k.png")
new_item = Item(channel=item.channel, action="novedades", extra="4k", title="Películas 4K", thumbnail=thumbnail)
new_item = Item(channel=item.channel, action="novedades", extra="4k", title=config.get_localized_string(70208), thumbnail=thumbnail)
set_category_context(new_item)
itemlist.append(new_item)
#if list_canales['terror']:
thumbnail = get_thumb("channels_horror.png")
new_item = Item(channel=item.channel, action="novedades", extra="terror", title="Peliculas de miedo!",
new_item = Item(channel=item.channel, action="novedades", extra="terror", title=config.get_localized_string(70209),
thumbnail=thumbnail)
set_category_context(new_item)
itemlist.append(new_item)
#if list_canales['infantiles']:
thumbnail = get_thumb("channels_children.png")
new_item = Item(channel=item.channel, action="novedades", extra="infantiles", title="Para niños",
new_item = Item(channel=item.channel, action="novedades", extra="infantiles", title=config.get_localized_string(60510),
thumbnail=thumbnail)
set_category_context(new_item)
itemlist.append(new_item)
#if list_canales['series']:
thumbnail = get_thumb("channels_tvshow.png")
new_item = Item(channel=item.channel, action="novedades", extra="series", title="Episodios de series",
new_item = Item(channel=item.channel, action="novedades", extra="series", title=config.get_localized_string(60511),
thumbnail=thumbnail)
set_category_context(new_item)
itemlist.append(new_item)
#if list_canales['anime']:
thumbnail = get_thumb("channels_anime.png")
new_item = Item(channel=item.channel, action="novedades", extra="anime", title="Episodios de anime",
new_item = Item(channel=item.channel, action="novedades", extra="anime", title=config.get_localized_string(60512),
thumbnail=thumbnail)
set_category_context(new_item)
itemlist.append(new_item)
# if list_canales['Castellano']:
thumbnail = get_thumb("channels_spanish.png")
new_item = Item(channel=item.channel, action="novedades", extra="castellano", title="Castellano",
new_item = Item(channel=item.channel, action="novedades", extra="castellano", title=config.get_localized_string(70014),
thumbnail=thumbnail)
set_category_context(new_item)
itemlist.append(new_item)
# if list_canales['Latino']:
thumbnail = get_thumb("channels_latino.png")
new_item = Item(channel=item.channel, action="novedades", extra="latino", title="Latino",
new_item = Item(channel=item.channel, action="novedades", extra="latino", title=config.get_localized_string(59976),
thumbnail=thumbnail)
set_category_context(new_item)
itemlist.append(new_item)
# if list_canales['Torrent']:
thumbnail = get_thumb("channels_torrent.png")
new_item = Item(channel=item.channel, action="novedades", extra="torrent", title="Torrent", thumbnail=thumbnail)
new_item = Item(channel=item.channel, action="novedades", extra="torrent", title=config.get_localized_string(70171), thumbnail=thumbnail)
set_category_context(new_item)
itemlist.append(new_item)
#if list_canales['documentales']:
thumbnail = get_thumb("channels_documentary.png")
new_item = Item(channel=item.channel, action="novedades", extra="documentales", title="Documentales",
new_item = Item(channel=item.channel, action="novedades", extra="documentales", title=config.get_localized_string(60513),
thumbnail=thumbnail)
set_category_context(new_item)
itemlist.append(new_item)
@@ -119,11 +119,11 @@ def mainlist(item):
def set_category_context(item):
item.context = [{"title": "Canales incluidos en: %s" % item.title,
item.context = [{"title": config.get_localized_string(60514) % item.title,
"extra": item.extra,
"action": "setting_channel",
"channel": item.channel}]
item.category = "Novedades en %s" % item.extra
item.category = config.get_localized_string(60679) % item.extra
def get_channels_list():
@@ -233,15 +233,15 @@ def novedades(item):
logger.info("multithread= " + str(multithread))
if not multithread:
if platformtools.dialog_yesno("Búsqueda concurrente desactivada",
"La búsqueda concurrente de novedades proporciona",
"una mayor velocidad y su desactivación solo es aconsejable en caso de fallo.",
"¿Desea activar la búsqueda concurrente ahora?"):
if platformtools.dialog_yesno(config.get_localized_string(60515),
config.get_localized_string(60516),
config.get_localized_string(60517),
config.get_localized_string(60518)):
if config.set_setting("multithread", True, "news"):
multithread = True
if mode == 'normal':
progreso = platformtools.dialog_progress(item.category, "Buscando canales...")
progreso = platformtools.dialog_progress(item.category, config.get_localized_string(60519))
list_canales, any_active = get_channels_list()
@@ -278,13 +278,13 @@ def novedades(item):
t.start()
threads.append(t)
if mode == 'normal':
progreso.update(percentage, "", "Buscando en '%s'..." % channel_title)
progreso.update(percentage, "", config.get_localized_string(60520) % channel_title)
# Modo single Thread
else:
if mode == 'normal':
logger.info("Obteniendo novedades de channel_id=" + channel_id)
progreso.update(percentage, "", "Buscando en '%s'..." % channel_title)
progreso.update(percentage, "", config.get_localized_string(60520) % channel_title)
get_newest(channel_id, item.extra)
# Modo Multi Thread: esperar q todos los hilos terminen
@@ -297,8 +297,8 @@ def novedades(item):
list_pendent_names = [a.getName() for a in pendent]
if mode == 'normal':
mensaje = "Buscando en %s" % (", ".join(list_pendent_names))
progreso.update(percentage, "Finalizado en %d/%d canales..." % (len(threads) - len(pendent), len(threads)),
mensaje = config.get_localized_string(30994) % (", ".join(list_pendent_names))
progreso.update(percentage, config.get_localized_string(60521) % (len(threads) - len(pendent), len(threads)),
mensaje)
logger.debug(mensaje)
@@ -309,7 +309,7 @@ def novedades(item):
time.sleep(0.5)
pendent = [a for a in threads if a.isAlive()]
if mode == 'normal':
mensaje = "Resultados obtenidos: %s | Tiempo: %2.f segundos" % (len(list_newest), time.time() - start_time)
mensaje = config.get_localized_string(60522) % (len(list_newest), time.time() - start_time)
progreso.update(100, mensaje, " ", " ")
logger.info(mensaje)
start_time = time.time()
@@ -494,9 +494,9 @@ def group_by_content(list_result_canal):
if len(canales_no_duplicados) > 1:
canales = ', '.join([i for i in canales_no_duplicados[:-1]])
title += " (En %s y %s)" % (canales, canales_no_duplicados[-1])
title += config.get_localized_string(70210) % (canales, canales_no_duplicados[-1])
else:
title += " (En %s)" % (', '.join([i for i in canales_no_duplicados]))
title += config.get_localized_string(70211) % (', '.join([i for i in canales_no_duplicados]))
new_item = v[0].clone(channel="news", title=title, action="show_channels",
sub_list=[i.tourl() for i in v], extra=channels_id_name)
@@ -533,47 +533,47 @@ def show_channels(item):
def menu_opciones(item):
itemlist = list()
itemlist.append(Item(channel=item.channel, title="Canales incluidos en:",
itemlist.append(Item(channel=item.channel, title=config.get_localized_string(60525),
thumbnail=get_thumb("setting_0.png"),
folder=False))
itemlist.append(Item(channel=item.channel, action="setting_channel", extra="peliculas", title=" - Películas ",
itemlist.append(Item(channel=item.channel, action="setting_channel", extra="peliculas", title=config.get_localized_string(60526),
thumbnail=get_thumb("channels_movie.png"),
folder=False))
itemlist.append(Item(channel=item.channel, action="setting_channel", extra="4K", title=" - Películas 4K ",
itemlist.append(Item(channel=item.channel, action="setting_channel", extra="4K", title=config.get_localized_string(70207),
thumbnail=get_thumb("channels_movie.png"), folder=False))
itemlist.append(Item(channel=item.channel, action="setting_channel", extra="infantiles", title=" - Para niños",
itemlist.append(Item(channel=item.channel, action="setting_channel", extra="infantiles", title=config.get_localized_string(60527),
thumbnail=get_thumb("channels_children.png"),
folder=False))
itemlist.append(Item(channel=item.channel, action="setting_channel", extra="series",
title=" - Episodios de series",
title=config.get_localized_string(60528),
thumbnail=get_thumb("channels_tvshow.png"),
folder=False))
itemlist.append(Item(channel=item.channel, action="setting_channel", extra="anime",
title=" - Episodios de anime",
title=config.get_localized_string(60529),
thumbnail=get_thumb("channels_anime.png"),
folder=False))
itemlist.append(
Item(channel=item.channel, action="setting_channel", extra="castellano", title=" - Castellano",
Item(channel=item.channel, action="setting_channel", extra="castellano", title=config.get_localized_string(70212),
thumbnail=get_thumb("channels_documentary.png"), folder=False))
itemlist.append(Item(channel=item.channel, action="setting_channel", extra="latino", title=" - Latino",
itemlist.append(Item(channel=item.channel, action="setting_channel", extra="latino", title=config.get_localized_string(70213),
thumbnail=get_thumb("channels_documentary.png"), folder=False))
itemlist.append(Item(channel=item.channel, action="setting_channel", extra="Torrent", title=" - Torrent",
itemlist.append(Item(channel=item.channel, action="setting_channel", extra="Torrent", title=config.get_localized_string(70214),
thumbnail=get_thumb("channels_documentary.png"), folder=False))
itemlist.append(Item(channel=item.channel, action="setting_channel", extra="documentales",
title=" - Documentales",
title=config.get_localized_string(60530),
thumbnail=get_thumb("channels_documentary.png"),
folder=False))
itemlist.append(Item(channel=item.channel, action="settings", title="Otros ajustes",
itemlist.append(Item(channel=item.channel, action="settings", title=config.get_localized_string(60531),
thumbnail=get_thumb("setting_0.png"),
folder=False))
return itemlist
def settings(item):
return platformtools.show_channel_settings(caption="configuración -- Novedades")
return platformtools.show_channel_settings(caption=config.get_localized_string(60532))
def setting_channel(item):

View File

@@ -124,8 +124,8 @@ def buscador(item):
titulo = '%s [%s][%s]' % (scrapedtitle, ','.join([a[:3] for a in audios]), calidad)
# Parece que las pelis de adultos se mezclan en la búsqueda y lo único que las diferencia es que no tienen Calidad
if calidades or __adult_mode__ != 0:
# Parece que las pelis de adultos se mezclan en la búsqueda y lo único que las diferencia es que no tienen Calidad y Audios
if (calidad and audios) or __adult_mode__ != 0:
itemlist.append(Item(channel=item.channel,
action="findvideos", url=scrapedurl,
title=titulo, contentTitle=scrapedtitle,

View File

@@ -496,6 +496,7 @@ def findvideos(item):
elif scrapedurl.startswith("https://load.pelispedia.vip/embed/"):
if scrapedtitle == 'vid': scrapedtitle = 'vidoza'
elif scrapedtitle == 'fast': scrapedtitle = 'fastplay'
elif scrapedtitle == 'frem': scrapedtitle = 'fembed'
title = "Ver video en [" + scrapedtitle + "]"
new_item = item.clone(title=title, url=scrapedurl, action="play", referer=item.url)
itemlist.append(new_item)
@@ -512,8 +513,58 @@ def findvideos(item):
def play(item):
logger.info("url=%s" % item.url)
itemlist = []
itemlist = gktools.gk_play(item)
if item.url.startswith("https://pelispedia.video/v.php"):
# 1- Descargar
data, ck = gktools.get_data_and_cookie(item)
# 2- Calcular datos
gsv = scrapertools.find_single_match(data, '<meta name="google-site-verification" content="([^"]*)"')
if not gsv: return itemlist
suto = gktools.md5_dominio(item.url)
sufijo = '2653'
token = gktools.generar_token('"'+gsv+'"', suto+'yt'+suto+sufijo)
link, subtitle = gktools.get_play_link_id(data, item.url)
url = 'https://pelispedia.video/plugins/ymovies.php' # cloupedia.php gkpedia.php
post = "link=%s&token=%s" % (link, token)
# 3- Descargar json
data = gktools.get_data_json(url, post, ck)
# 4- Extraer enlaces
itemlist = gktools.extraer_enlaces_json(data, item.referer, subtitle)
elif item.url.startswith("https://load.pelispedia.vip/embed/"):
# 1- Descargar
data, ck = gktools.get_data_and_cookie(item)
# 2- Calcular datos
gsv = scrapertools.find_single_match(data, '<meta name="google-site-verification" content="([^"]*)"')
if not gsv: return itemlist
suto = gktools.md5_dominio(item.url)
sufijo = '785446346'
token = gktools.generar_token(gsv, suto+'yt'+suto+sufijo)
url = item.url.replace('/embed/', '/stream/') + '/' + token
# 3- Descargar página
data = gktools.get_data_with_cookie(url, ck, item.url)
# 4- Extraer enlaces
url = scrapertools.find_single_match(data, '<meta (?:name|property)="og:url" content="([^"]+)"')
srv = scrapertools.find_single_match(data, '<meta (?:name|property)="og:sitename" content="([^"]+)"')
if srv == '' and 'rapidvideo.com/' in url: srv = 'rapidvideo'
if url != '' and srv != '':
itemlist.append(item.clone(url=url, server=srv.lower()))
return itemlist

View File

@@ -256,24 +256,30 @@ def findvideos(item):
for url in urls:
final_url = httptools.downloadpage('https:'+url).data
if 'vip' in url:
if language == 'VOSE':
sub = scrapertools.find_single_match(url, 'sub=(.*?)&')
subs = 'https:%s' % sub
if 'index' in url:
file_id = scrapertools.find_single_match(url, 'file=(.*?)&')
if language=='VOSE':
sub = scrapertools.find_single_match(url, 'sub=(.*?)&')
subs = 'https:%s' % sub
post = {'link':file_id}
post = {'link': file_id}
post = urllib.urlencode(post)
hidden_url = 'https://streamango.poseidonhd.com/repro//plugins/gkpluginsphp.php'
hidden_url = 'https://streamango.poseidonhd.com/repro/plugins/gkpluginsphp.php'
data_url = httptools.downloadpage(hidden_url, post=post).data
dict_vip_url = jsontools.load(data_url)
url = dict_vip_url['link']
else:
url = 'https:%s' % url
new_url = url.replace('embed','stream')
url = httptools.downloadpage(new_url, follow_redirects=False).headers.get('location')
#title = '%s [%s]' % (item.title, language)
itemlist.append(item.clone(title='[%s] [%s]', url=url, action='play', subtitle=subs,
language=language, quality=quality, infoLabels = item.infoLabels))
file_id = scrapertools.find_single_match(url, 'url=(.*?)&')
post = {'url': file_id}
post = urllib.urlencode(post)
hidden_url = 'https://streamango.poseidonhd.com/repro/r.php'
data_url = httptools.downloadpage(hidden_url, post=post, follow_redirects=False)
url = data_url.headers['location']
itemlist.append(item.clone(title = '[%s] [%s]', url=url, action='play', subtitle=subs,
language=language, quality=quality, infoLabels=item.infoLabels))
itemlist = servertools.get_servers_itemlist(itemlist, lambda x: x.title % (x.server.capitalize(), x.language))
# Requerido para Filtrar enlaces
@@ -289,6 +295,8 @@ def findvideos(item):
autoplay.start(itemlist, item)
itemlist = sorted(itemlist, key=lambda it: it.language)
if item.contentType != 'episode':
if config.get_videolibrary_support() and len(itemlist) > 0 and item.extra != 'findvideos':
itemlist.append(

View File

@@ -1,54 +1,56 @@
{
"id": "search",
"name": "Buscador global",
"active": false,
"adult": false,
"language": ["*"],
"categories": [
"movie"
],
"settings": [
{
"id": "multithread",
"type": "bool",
"label": "Buscador MultiThread",
"default": true,
"enabled": true,
"visible": true
},
{
"id": "result_mode",
"type": "list",
"label": "Mostrar resultados:",
"default": 0,
"enabled": true,
"visible": true,
"lvalues": [
"Por canales",
"Todo junto"
]
},
{
"id": "saved_searches_limit",
"type": "list",
"label": "Busquedas guardadas:",
"default": 0,
"enabled": true,
"visible": true,
"lvalues": [
"10",
"20",
"30",
"40"
]
},
{
"id": "last_search",
"type": "bool",
"label": "Recordar última búsqueda",
"default": true,
"enabled": true,
"visible": true
}
]
{
"id": "search",
"name": "@60672",
"active": false,
"adult": false,
"language": [
"it"
],
"categories": [
"movie"
],
"settings": [
{
"id": "multithread",
"type": "bool",
"label": "@60673",
"default": true,
"enabled": true,
"visible": true
},
{
"id": "result_mode",
"type": "list",
"label": "@60674",
"default": 0,
"enabled": true,
"visible": true,
"lvalues": [
"@60675",
"@60676"
]
},
{
"id": "saved_searches_limit",
"type": "list",
"label": "@60677",
"default": 0,
"enabled": true,
"visible": true,
"lvalues": [
"10",
"20",
"30",
"40"
]
},
{
"id": "last_search",
"type": "bool",
"label": "@60678",
"default": true,
"enabled": true,
"visible": true
}
]
}

View File

@@ -18,39 +18,39 @@ def mainlist(item):
item.channel = "search"
itemlist = list()
context = [{"title": "Elegir canales incluidos",
context = [{"title": config.get_localized_string(70273),
"action": "setting_channel",
"channel": item.channel}]
itemlist.append(Item(channel=item.channel, action="search",
title="Buscar por titulo", context=context,
title=config.get_localized_string(70276), context=context,
thumbnail=get_thumb("search.png")))
thumbnail = get_thumb("search_star.png")
itemlist.append(Item(channel='tvmoviedb', title="Buscar actor/actriz", action="search_",
itemlist.append(Item(channel='tvmoviedb', title=config.get_localized_string(59999), action="search_",
search={'url': 'search/person', 'language': 'es', 'page': 1}, star=True,
thumbnail=thumbnail))
itemlist.append(Item(channel=item.channel, action="search",
title="Buscar por categorias (búsqueda avanzada)", extra="categorias",
title=config.get_localized_string(59998), extra="categorias",
context=context,
thumbnail=get_thumb("search.png")))
itemlist.append(Item(channel=item.channel, action="opciones", title="Opciones",
itemlist.append(Item(channel=item.channel, action="opciones", title=config.get_localized_string(59997),
thumbnail=get_thumb("search.png")))
itemlist.append(Item(channel="tvmoviedb", action="mainlist", title="Búsqueda alternativa",
itemlist.append(Item(channel="tvmoviedb", action="mainlist", title=config.get_localized_string(70274),
thumbnail=get_thumb("search.png")))
saved_searches_list = get_saved_searches()
context2 = context[:]
context2.append({"title": "Borrar búsquedas guardadas",
context2.append({"title": config.get_localized_string(59996),
"action": "clear_saved_searches",
"channel": item.channel})
logger.info("saved_searches_list=%s" % saved_searches_list)
if saved_searches_list:
itemlist.append(Item(channel=item.channel, action="",
title="Búsquedas guardadas:", context=context2,
title=config.get_localized_string(59995), context=context2,
thumbnail=get_thumb("search.png")))
for saved_search_text in saved_searches_list:
itemlist.append(Item(channel=item.channel, action="do_search",
@@ -65,17 +65,17 @@ def mainlist(item):
def opciones(item):
itemlist = list()
itemlist.append(Item(channel=item.channel, action="setting_channel",
title="Elegir canales incluidos en la búsqueda", folder=False,
title=config.get_localized_string(59994), folder=False,
thumbnail=get_thumb("search.png")))
itemlist.append(Item(channel=item.channel, action="clear_saved_searches", title="Borrar búsquedas guardadas",
itemlist.append(Item(channel=item.channel, action="clear_saved_searches", title=config.get_localized_string(59996),
folder=False, thumbnail=get_thumb("search.png")))
itemlist.append(Item(channel=item.channel, action="settings", title="Otros ajustes", folder=False,
itemlist.append(Item(channel=item.channel, action="settings", title=config.get_localized_string(60531), folder=False,
thumbnail=get_thumb("search.png")))
return itemlist
def settings(item):
return platformtools.show_channel_settings(caption="configuración -- Buscador")
return platformtools.show_channel_settings(caption=config.get_localized_string(59993))
def setting_channel(item):
@@ -119,12 +119,12 @@ def setting_channel(item):
list_controls.append(control)
if config.get_setting("custom_button_value", item.channel):
custom_button_label = "Ninguno"
custom_button_label = config.get_localized_string(59992)
else:
custom_button_label = "Todos"
custom_button_label = config.get_localized_string(59991)
return platformtools.show_channel_settings(list_controls=list_controls,
caption="Canales incluidos en la búsqueda",
caption=config.get_localized_string(59990),
callback="save_settings", item=item,
custom_button={'visible': True,
'function': "cb_custom_button",
@@ -133,10 +133,10 @@ def setting_channel(item):
def save_settings(item, dict_values):
progreso = platformtools.dialog_progress("Guardando configuración...", "Espere un momento por favor.")
progreso = platformtools.dialog_progress(config.get_localized_string(59988), config.get_localized_string(59989))
n = len(dict_values)
for i, v in enumerate(dict_values):
progreso.update((i * 100) / n, "Guardando configuración...")
progreso.update((i * 100) / n, config.get_localized_string(59988))
config.set_setting("include_in_global_search", dict_values[v], v)
progreso.close()
@@ -151,9 +151,9 @@ def cb_custom_button(item, dict_values):
dict_values[v] = not value
if config.set_setting("custom_button_value", not value, item.channel) == True:
return {"label": "Ninguno"}
return {"label": config.get_localized_string(59992)}
else:
return {"label": "Todos"}
return {"label": config.get_localized_string(59991)}
def searchbycat(item):
@@ -181,13 +181,13 @@ def searchbycat(item):
list_controls.append(control)
control = {'id': "torrent",
'type': "bool",
'label': 'Incluir en la búsqueda canales Torrent',
'label': config.get_localized_string(70275),
'default': True,
'enabled': True,
'visible': True}
list_controls.append(control)
return platformtools.show_channel_settings(list_controls=list_controls, caption="Elegir categorías",
return platformtools.show_channel_settings(list_controls=list_controls, caption=config.get_localized_string(59974),
callback="search_cb", item=item)
@@ -229,7 +229,7 @@ def show_result(item):
tecleado = None
if item.adult and config.get_setting("adult_request_password"):
# Solicitar contraseña
tecleado = platformtools.dialog_input("", "Contraseña para canales de adultos", True)
tecleado = platformtools.dialog_input("", config.get_localized_string(60334), True)
if tecleado is None or tecleado != config.get_setting("adult_password"):
return []
@@ -288,7 +288,7 @@ def do_search(item, categories=None):
if item.contextual==True:
categories = ["Películas"]
setting_item = Item(channel=item.channel, title="Elegir canales incluidos en la búsqueda", folder=False,
setting_item = Item(channel=item.channel, title=config.get_localized_string(59994), folder=False,
thumbnail=get_thumb("search.png"))
setting_channel(setting_item)
@@ -315,7 +315,7 @@ def do_search(item, categories=None):
# Para Kodi es necesario esperar antes de cargar el progreso, de lo contrario
# el cuadro de progreso queda "detras" del cuadro "cargando..." y no se le puede dar a cancelar
time.sleep(0.5)
progreso = platformtools.dialog_progress("Buscando '%s'..." % tecleado, "")
progreso = platformtools.dialog_progress(config.get_localized_string(30993) % tecleado, "")
channel_files = sorted(glob.glob(channels_path), key=lambda x: os.path.basename(x))
import math
@@ -396,7 +396,7 @@ def do_search(item, categories=None):
logger.info("%s incluido en la búsqueda" % basename_without_extension)
progreso.update(percentage,
"Buscando en %s..." % channel_parameters["title"])
config.get_localized_string(60520) % channel_parameters["title"])
except:
logger.error("No se puede buscar en: %s" % channel_parameters["title"])
@@ -417,7 +417,7 @@ def do_search(item, categories=None):
list_pendent_names = [a.getName() for a in pendent]
mensaje = "Buscando en %s" % (", ".join(list_pendent_names))
progreso.update(percentage, "Finalizado en %d/%d canales..." % (len(threads) - len(pendent), len(threads)),
progreso.update(percentage, config.get_localized_string(60521) % (len(threads) - len(pendent), len(threads)),
mensaje)
logger.debug(mensaje)
@@ -460,7 +460,7 @@ def do_search(item, categories=None):
itemlist.append(i.clone(title=title, from_action=i.action, from_channel=i.channel,
channel="search", action="show_result", adult=element["adult"]))
title = "Buscando: '%s' | Encontrado: %d vídeos | Tiempo: %2.f segundos" % (
title = config.get_localized_string(59972) % (
tecleado, total, time.time() - start_time)
itemlist.insert(0, Item(title=title, text_color='yellow'))
@@ -506,7 +506,7 @@ def save_search(text):
def clear_saved_searches(item):
config.set_setting("saved_searches_list", list(), "search")
platformtools.dialog_ok("Buscador", "Búsquedas borradas correctamente")
platformtools.dialog_ok(config.get_localized_string(60329), config.get_localized_string(60424))
def get_saved_searches():

File diff suppressed because it is too large Load Diff

View File

@@ -12,40 +12,53 @@ from core import httptools
from core import scrapertools
from core import servertools
from core.item import Item
from platformcode import config, logger
from platformcode import config, logger, platformtools
from core import tmdb
from lib import generictools
host = 'http://torrentlocura.com/'
channel_py = 'newpct1'
#Código para permitir usar un único canal para todas las webs clones de NewPct1
clone_list = config.get_setting('clonenewpct1_channels_list', "torrentrapid") #Carga lista de clones
clone_list = ast.literal_eval(clone_list) #la convierte a lista de tuplas
clone_list = config.get_setting('clonenewpct1_channels_list', channel_py) #Carga lista de clones
clone_list = ast.literal_eval(clone_list) #la convierte en array
host_index = 0
host_index = config.get_setting('clonenewpct1_channel_default', "torrentrapid") #Clone por defecto
host_index = config.get_setting('clonenewpct1_channel_default', channel_py) #Clone por defecto
i = 0
for active_clone, channel_clone, host_clone, contentType_clone, info_clone in clone_list:
if i == host_index:
#channel_clone_name = channel_clone #ACTIVAR CUANDO SE PASE A NEWPCT1
#host = 'http://%s/' % host_clone #ACTIVAR CUANDO SE PASE A NEWPCT1
i += 1
channel_clone_name = channel_clone #Nombre del Canal elegido
host = host_clone #URL del Canal elegido
break
i += 1
item = Item()
item.channel_host = host
if item.channel != channel_py:
item.channel = channel_py
item.category = channel_clone_name.capitalize()
#Carga de opciones del canal
item = Item()
if not item.channel:
item.channel = scrapertools.find_single_match(host, r'(\w+)\.com\/')
channel_clone_name = scrapertools.find_single_match(host, r'(\w+)\.com\/') #QUITAR CUANDO SE PASE A NEWPCT1
__modo_grafico__ = config.get_setting('modo_grafico', item.channel)
modo_ultima_temp = config.get_setting('seleccionar_ult_temporadda_activa', item.channel)
__modo_grafico__ = config.get_setting('modo_grafico', channel_py) #TMDB?
modo_ultima_temp = config.get_setting('seleccionar_ult_temporadda_activa', channel_py) #Actualización sólo últ. Temporada?
timeout = config.get_setting('clonenewpct1_timeout_downloadpage', channel_py) #Timeout downloadpage
if timeout == 0: timeout = None
platformtools.dialog_ok("NewPct1, ¡¡¡he vuelto como canal VIRTUAL!!!", "Hemos centralizado la gestión de los clones de NewPct1 en el canal virtual NewPct1. Los clones desaparecerán en breve.", "Para más información lee el tutorial: https://alfa-addon.com /threads/newpct1-implantando-alta-disponibilidad.1200/")
#Vayamos a la siguiente acción en el canal Newpct1
from platformcode import launcher
channel_clone_name = "torrentlocura" #Nombre del Canal elegido
host = "http://torrentlocura.com/"
item.category = channel_clone_name.capitalize()
item.action = "mainlist"
item.channel_host = host
launcher.run(item)
def mainlist(item):
logger.info()
if item.channel != channel_py:
return
#Renombramos el canal al nombre de clone elegido
item.channel = channel_clone_name
if item.category: item.category = channel_clone_name.capitalize()
itemlist = []
thumb_pelis = get_thumb("channels_movie.png")
@@ -58,20 +71,20 @@ def mainlist(item):
thumb_settings = get_thumb("setting_0.png")
itemlist.append(Item(channel=item.channel, action="submenu", title="Películas", url=host,
extra="peliculas", thumbnail=thumb_pelis ))
extra="peliculas", thumbnail=thumb_pelis, category=item.category))
itemlist.append(Item(channel=item.channel, action="submenu", title="Series", url=host, extra="series",
thumbnail=thumb_series))
thumbnail=thumb_series, category=item.category))
itemlist.append(Item(channel=item.channel, action="submenu", title="Documentales", url=host, extra="varios",
thumbnail=thumb_docus))
thumbnail=thumb_docus, category=item.category))
itemlist.append(
Item(channel=item.channel, action="search", title="Buscar", url=host + "buscar", thumbnail=thumb_buscar))
Item(channel=item.channel, action="search", title="Buscar", url=host + "buscar", thumbnail=thumb_buscar, category=item.category))
itemlist.append(
Item(channel=item.channel, action="", title="[COLOR yellow]Configuración de Servidores:[/COLOR]", url="", thumbnail=thumb_settings))
Item(channel=item.channel, action="", title="[COLOR yellow]Configuración de Servidores:[/COLOR]", url="", thumbnail=thumb_settings, category=item.category))
itemlist.append(
Item(channel=item.channel, action="settingCanal", title="Servidores para Ver Online y Descargas", url="", thumbnail=thumb_settings))
Item(channel=item.channel, action="settingCanal", title="Servidores para Ver Online y Descargas", url="", thumbnail=thumb_settings, category=item.category))
return itemlist
@@ -85,68 +98,60 @@ def submenu(item):
logger.info()
itemlist = []
data = ''
try:
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data)
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data)
except:
pass
host_alt = host
host_dom = host.replace("https://", "").replace("http://", "").replace("www.", "")
patron = '<li><a href="http://(?:www.)?' + host_dom + item.extra + '/">.*?<ul.*?>(.*?)</ul>'
patron = '<li><a\s?class="[^"]+"\s?href="http:[^"]+"><i\s?class=.*><\/i>.*Inicio<\/a><\/li>(.+)<\/ul>\s?<\/nav>'
#Verificamos si se ha cargado una página, y si además tiene la estructura correcta
if not data or not scrapertools.find_single_match(data, patron):
logger.error("ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL: " + item.url)
logger.error("ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL: " + item.url + data)
#Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú
item, data = generictools.fail_over_newpct1(item, patron)
if not data: #Si no ha logrado encontrar nada, salimos
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
elif item.channel_alt: #Si ha habido fail-over, lo comento
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR] [ALT ] en uso'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] caído'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR] [ALT ] en uso'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] inaccesible'))
host_alt = host.replace(item.channel_alt, item.channel)
del item.channel_alt
if item.url_alt: del item.url_alt
del item.channel_alt
#data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8")
#data = data.replace("'", '"').replace('/series"', '/series/"') #Compatibilidad con mispelisy.series.com
host_dom = host_alt.replace("https://", "").replace("http://", "").replace("www.", "")
patron = '<li><a href="http://(?:www.)?' + host_dom + item.extra + '/">.*?<ul.*?>(.*?)</ul>'
if "pelisyseries.com" in host_alt and item.extra == "varios": #compatibilidad con mispelisy.series.com
data = '<a href="' + host_alt + 'varios/" title="Documentales"><i class="icon-rocket"></i> Documentales</a>'
data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8")
data = data.replace("'", '"').replace('/series"', '/series/"') #Compatibilidad con mispelisy.series.com
if "pelisyseries.com" in item.channel_host and item.extra == "varios": #compatibilidad con mispelisy.series.com
data = '<li><a href="' + item.channel_host + 'varios/" title="Documentales">Documentales</a></li>'
else:
if data:
data = scrapertools.get_match(data, patron)
if not data:
logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
else:
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
data = scrapertools.get_match(data, patron) #Seleccionamos el trozo que nos interesa
if not data:
logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
patron = '<.*?href="([^"]+)".*?>([^>]+)</a>'
patron = '<li><a.*?href="([^"]+)"\s?.itle="[^"]+"\s?>([^>]+)<\/a><\/li>'
matches = re.compile(patron, re.DOTALL).findall(data)
if not matches:
logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
for scrapedurl, scrapedtitle in matches:
title = scrapedtitle.strip()
url = scrapedurl
itemlist.append(Item(channel=item.channel, action="listado", title=title, url=url, extra=item.extra))
itemlist.append(
Item(channel=item.channel, action="alfabeto", title=title + " [A-Z]", url=url, extra=item.extra))
#Preguntamos por las entradas que no corresponden al "extra"
if item.extra in scrapedtitle.lower() or (item.extra == "peliculas" and ("cine" in scrapedurl or "anime" in scrapedurl)) or (item.extra == "varios" and ("documentales" in scrapedurl or "varios" in scrapedurl)):
itemlist.append(item.clone(action="listado", title=title, url=scrapedurl))
itemlist.append(item.clone(action="alfabeto", title=title + " [A-Z]", url=scrapedurl))
if item.extra == "peliculas":
itemlist.append(Item(channel=item.channel, action="listado", title="Películas 4K", url=host_alt + "peliculas-hd/4kultrahd/", extra=item.extra))
itemlist.append(
Item(channel=item.channel, action="alfabeto", title="Películas 4K" + " [A-Z]", url=host_alt + "peliculas-hd/4kultrahd/", extra=item.extra))
itemlist.append(item.clone(action="listado", title="Películas 4K", url=item.channel_host + "peliculas-hd/4kultrahd/"))
itemlist.append(item.clone(action="alfabeto", title="Películas 4K" + " [A-Z]", url=item.channel_host + "peliculas-hd/4kultrahd/"))
return itemlist
@@ -155,28 +160,41 @@ def alfabeto(item):
logger.info()
itemlist = []
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data)
data = ''
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data)
data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8")
patron = '<ul class="alfabeto">(.*?)</ul>'
if data:
data = scrapertools.get_match(data, patron)
else:
return itemlist
if not data or not scrapertools.find_single_match(data, patron):
logger.error("ERROR 01: ALFABETO: La Web no responde o ha cambiado de URL: " + item.url + data)
#Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú
item, data = generictools.fail_over_newpct1(item, patron)
if not data: #Si no ha logrado encontrar nada, salimos
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: ALFABETO: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
elif item.channel_alt: #Si ha habido fail-over, lo comento
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR] [ALT ] en uso'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] inaccesible'))
if item.url_alt: del item.url_alt
del item.channel_alt
data = scrapertools.get_match(data, patron)
patron = '<a href="([^"]+)"[^>]+>([^>]+)</a>'
matches = re.compile(patron, re.DOTALL).findall(data)
if not matches:
logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log'))
logger.error("ERROR 02: ALFABETO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: ALFABETO: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
for scrapedurl, scrapedtitle in matches:
title = scrapedtitle.upper()
url = scrapedurl
itemlist.append(Item(channel=item.channel, action="listado", title=title, url=url, extra=item.extra))
itemlist.append(item.clone(action="listado", title=title, url=scrapedurl))
return itemlist
@@ -191,11 +209,21 @@ def listado(item):
if item.totalItems:
del item.totalItems
data = ''
try:
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data)
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data)
except:
pass
patron = '<ul class="' + clase + '">(.*?)</ul>' #seleccionamos el bloque que nos interesa
if not data or (not scrapertools.find_single_match(data, patron) and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data):
logger.error("ERROR 01: LISTADO: La Web no responde o ha cambiado de URL: " + item.url + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
#Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú
item, data = generictools.fail_over_newpct1(item, patron)
if not data: #Si no ha logrado encontrar nada, salimos
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: LISTADO: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
#Establecemos los valores básicos en función del tipo de contenido
@@ -218,7 +246,7 @@ def listado(item):
fichas = scrapertools.get_match(data, patron)
if not fichas and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data: #error
logger.error("ERROR 02: LISTADO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
elif '<h3><strong>( 0 ) Resultados encontrados </strong>' in data: #no hay vídeos
return itemlist
@@ -235,7 +263,7 @@ def listado(item):
matches = re.compile(patron, re.DOTALL).findall(fichas)
if not matches: #error
logger.error("ERROR 02: LISTADO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + fichas)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
#logger.debug("MATCHES: " + str(len(matches)))
@@ -460,13 +488,21 @@ def listado(item):
def listado_busqueda(item):
logger.info()
host = 'http://%s/' % scrapertools.find_single_match(item.url, '(\w+\.com)\/')
#Renombramos el canal al nombre de clone elegido. Actualizados URL
host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)')
#item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/')
if item.category and item.category != "newest":
item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize()
itemlist = []
cnt_tot = 40 # Poner el num. máximo de items por página. Dejamos que la web lo controle
cnt_title = 0 # Contador de líneas insertadas en Itemlist
cnt_pag = 0 # Contador de líneas leídas de Matches
timeout_search = 5 # Timeout un poco más largo para las búsquedas
if timeout > 5:
timeout_search = timeout # Timeout un poco más largo para las búsquedas
data = ''
if item.cnt_pag:
cnt_pag = item.cnt_pag # Se guarda en la lista de páginas anteriores en Item
@@ -493,21 +529,21 @@ def listado_busqueda(item):
#Máximo num. de líneas permitidas por TMDB. Máx de 5 páginas por Itemlist para no degradar el rendimiento
while cnt_title <= cnt_tot and cnt_next < 5:
pattern = '<ul class="%s">(.*?)</ul>' % item.pattern #seleccionamos el bloque que nos interesa
try:
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, post=item.post).data)
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, post=item.post, timeout=timeout_search).data)
except:
pass
cnt_next += 1
if not data or not scrapertools.find_single_match(data, pattern):
cnt_next += 1
pattern = '<ul class="%s">(.*?)</ul>' % item.pattern #seleccionamos el bloque que nos interesa
if not data or (not scrapertools.find_single_match(data, pattern) and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data):
logger.error("ERROR 01: LISTADO_BUSQUEDA: La Web no responde o ha cambiado de URL: " + item.url + item.post + " / DATA: " + data)
#Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú
item, data = generictools.fail_over_newpct1(item, pattern)
if not data: #Si no ha logrado encontrar nada, salimos
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO_BUSQUEDA:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: LISTADO_BUSQUEDA:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
elif item.channel_alt: #Si ha habido fail-over, lo comento
host = host.replace(item.channel_alt, item.channel)
@@ -531,7 +567,6 @@ def listado_busqueda(item):
pattern = '<ul class="%s">(.*?)</ul>' % item.pattern #seleccionamos el bloque que nos interesa
data_alt = data
data = scrapertools.get_match(data, pattern)
#pattern = '<li[^>]*><a href="(?P<url>[^"]+).*?<img.*?src="(?P<thumb>[^"]+)?".*?<h2.*?>(?P<title>.*?)?<\/h2>'
pattern = '<li[^>]*><a href="(?P<scrapedurl>[^"]+).*?' #url
pattern += 'title="(?P<scrapedtitle>[^"]+).*?' #título
pattern += '<img.*?src="(?P<scrapedthumbnail>[^"]+)?".*?' #thumb
@@ -541,7 +576,8 @@ def listado_busqueda(item):
matches_alt = re.compile(pattern, re.DOTALL).findall(data)
if not matches_alt and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data_alt: #error
logger.error("ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + data_alt)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web. Reportar el error con el log'))
item, itemlist = generictools.post_tmdb_listado(item, itemlist) #Pintamos los datos de fail-over, si los hay
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
#Ahora se hace una simulación para saber cuantas líneas podemos albergar en este Itemlist.
@@ -830,14 +866,14 @@ def listado_busqueda(item):
url_tvshow = host + calidad_mps + real_title_mps + "/" #... otras no. A probar...
#Leemos la página, a ver si es una página de episodios
data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_id).data)
data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_id, timeout=timeout).data)
data_serie = unicode(data_serie, "iso-8859-1", errors="replace").encode("utf-8")
data_serie = data_serie.replace("chapters", "buscar-list")
pattern = '<ul class="%s">(.*?)</ul>' % "buscar-list" #Patrón de lista de episodios
if not scrapertools.find_single_match(data_serie, pattern) and serieid: #no es válida la página,
#intentarlo con la otra url
data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_tvshow).data)
data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_tvshow, timeout=timeout).data)
data_serie = unicode(data_serie, "iso-8859-1", errors="replace").encode("utf-8")
data_serie = data_serie.replace("chapters", "buscar-list")
@@ -876,9 +912,10 @@ def findvideos(item):
from core import channeltools
logger.info()
#Renombramos el canal al nombre de clone elegido
item.channel = channel_clone_name
if item.category: item.category = channel_clone_name.capitalize()
#Renombramos el canal al nombre de clone elegido. Actualizados URL
host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)')
#item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/')
item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize()
itemlist = []
@@ -987,8 +1024,9 @@ def findvideos(item):
excluir_enlaces_descargas = [] #Lista vacía de servidores excluidos en Descargar
# Descarga la página
data = ''
try:
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data)
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data)
except:
pass
@@ -1001,7 +1039,7 @@ def findvideos(item):
item, data = generictools.fail_over_newpct1(item, patron)
if not data: #Si no ha logrado encontrar nada, salimos
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: FINDVIDEOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: FINDVIDEOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8")
@@ -1029,7 +1067,7 @@ def findvideos(item):
item_local.url = scrapertools.find_single_match(data, patron)
if not item_local.url: #error
logger.error("ERROR 02: FINDVIDEOS: El archivo Torrent no existe o ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: FINDVIDEOS: El archivo Torrent no existe o ha cambiado la estructura de la Web. Verificar en la Web y reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: FINDVIDEOS: El archivo Torrent no existe o ha cambiado la estructura de la Web. Verificar en la Web y reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
item_local.url = item_local.url.replace(" ", "%20") #sustituimos espacios por %20, por si acaso
#logger.debug("Patron: " + patron + " url: " + item_local.url)
@@ -1054,6 +1092,8 @@ def findvideos(item):
#logger.debug(item_local)
# VER vídeos, descargar vídeos un link, o múltiples links
data = scrapertools.find_single_match(data, '<div id="tab1" class="tab_content"(.*?<\/ul>(?:<div.*?>)?<\/div><\/div><\/div>)') #Seleccionar el bloque para evitar duplicados
host_dom = host.replace("https://", "").replace("http://", "").replace("www.", "")
data = data.replace("http://tumejorserie.com/descargar/url_encript.php?link=", "(")
data = re.sub(r'javascript:;" onClick="popup\("http:\/\/(?:www.)?' + host_dom + '\w{1,9}\/library\/include\/ajax\/get_modallinks.php\?links=', "", data)
@@ -1066,7 +1106,7 @@ def findvideos(item):
enlaces_ver = re.compile(patron, re.DOTALL).findall(data)
enlaces_descargar = enlaces_ver
#logger.debug(enlaces_ver)
#Recorre todos los links de VER, si está permitido
cnt_enl_ver = 1
cnt_enl_verif = 1
@@ -1100,7 +1140,7 @@ def findvideos(item):
if verificar_enlaces_veronline != 0: #Se quiere verificar si el link está activo?
if cnt_enl_verif <= verificar_enlaces_veronline or verificar_enlaces_veronline == -1: #contador?
#Llama a la subfunción de check_list_links(itemlist) para cada link de servidor
item_local.alive = servertools.check_video_link(enlace, servidor) #activo el link ?
item_local.alive = servertools.check_video_link(enlace, servidor, timeout=timeout) #activo el link ?
if verificar_enlaces_veronline_validos: #Los links tienen que ser válidos para contarlos?
if item_local.alive == "Ok": #Sí
cnt_enl_verif += 1 #Movemos los contadores
@@ -1190,7 +1230,7 @@ def findvideos(item):
if verificar_enlaces_descargas != 0: #Se quiere verificar si el link está activo?
if cnt_enl_verif <= verificar_enlaces_descargas or verificar_enlaces_descargas == -1: #contador?
#Llama a la subfunción de check_list_links(itemlist) para primer link de servidor
item_local.alive = servertools.check_video_link(enlace, servidor) #activo el link ?
item_local.alive = servertools.check_video_link(enlace, servidor, timeout=timeout) #activo el link ?
if verificar_enlaces_descargas_validos: #Los links tienen que ser válidos para contarlos?
if item_local.alive == "Ok": #Sí
cnt_enl_verif += 1 #Movemos los contadores
@@ -1232,9 +1272,10 @@ def findvideos(item):
def episodios(item):
logger.info()
#Renombramos el canal al nombre de clone elegido
item.channel = channel_clone_name
if item.category: item.category = channel_clone_name.capitalize()
#Renombramos el canal al nombre de clone elegido. Actualizados URL
host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)')
#item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/')
item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize()
itemlist = []
@@ -1255,7 +1296,7 @@ def episodios(item):
data = ''
try:
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url).data)
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, timeout=timeout).data)
patron = '<ul class="%s">(.*?)</ul>' % "buscar-list" # item.pattern
data_alt = ''
if data: data_alt = scrapertools.get_match(data, patron)
@@ -1276,7 +1317,7 @@ def episodios(item):
if not data: #No se ha encontrado ningún canal activo para este vídeo
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: EPISODIOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: EPISODIOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log'))
return itemlist
#Busca y pre-carga todas las páginas de episodios que componen las serie, para obtener la url de cada página
@@ -1312,7 +1353,7 @@ def episodios(item):
break
try:
if not data:
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(page).data)
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(page, timeout=timeout).data)
data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8")
data = data.replace("chapters", "buscar-list") #Compatibilidad con mispelisy.series.com
pattern = '<ul class="%s">(.*?)</ul>' % "buscar-list" # item.pattern
@@ -1321,7 +1362,7 @@ def episodios(item):
raise
except:
logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / " + str(list_pages) + " / DATA: " + str(data))
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
if "pelisyseries.com" in item.url:
@@ -1331,7 +1372,7 @@ def episodios(item):
matches = re.compile(pattern, re.DOTALL).findall(data)
if not matches: #error
logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
#logger.debug("patron: " + pattern)
@@ -1399,7 +1440,7 @@ def episodios(item):
match = [m.groupdict() for m in r.finditer(info)][0]
if not match: #error
logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + info)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
if match['season'] is None: match['season'] = season #Si no se encuentran valores, pero poner lo básico
@@ -1449,8 +1490,6 @@ def episodios(item):
if item_local.active:
del item_local.active
if item_local.category:
del item_local.category
if item_local.infoLabels['title']:
del item_local.infoLabels['title']
item_local.context = "['buscar_trailer']"
@@ -1467,6 +1506,8 @@ def episodios(item):
del item_local.update_last
if item_local.update_next:
del item_local.update_next
if item_local.channel_host:
del item_local.channel_host
itemlist.append(item_local.clone())
@@ -1501,9 +1542,6 @@ def actualizar_titulos(item):
def search(item, texto):
logger.info("search:" + texto)
# texto = texto.replace(" ", "+")
item.channel = channel_clone_name
if item.category: item.category = channel_clone_name.capitalize()
try:
item.post = "q=%s" % texto

View File

@@ -53,7 +53,7 @@
"id": "clonenewpct1_channels_list",
"type": "text",
"label": "Lista de clones de NewPct1 y orden de uso",
"default": "('1', 'torrentrapid', 'torrentrapid.com', 'movie, tvshow, season, episode', ''), ('1', 'torrentlocura', 'torrentlocura.com', 'movie, tvshow, season, episode', ''), ('1', 'tumejortorrent', 'tumejortorrent.com', 'movie, tvshow, season, episode', ''), ('1', 'tvsinpagar', 'www.tvsinpagar.com', 'tvshow, season, episode', ''), ('1', 'descargas2020', 'descargas2020.com', 'movie, tvshow, season, episode', ''), ('1', 'mispelisyseries', 'mispelisyseries.com', 'movie, tvshow, season, episode', '')",
"default": "('1', 'torrentrapid', 'http://torrentrapid.com/', 'movie, tvshow, season, episode', ''), ('1', 'torrentlocura', 'http://torrentlocura.com/', 'movie, tvshow, season, episode', ''), ('1', 'tumejortorrent', 'http://tumejortorrent.com/', 'movie, tvshow, season, episode', ''), ('1', 'tvsinpagar', 'http://www.tvsinpagar.com/', 'tvshow, season, episode', ''), ('1', 'descargas2020', 'http://descargas2020.com/', 'movie, tvshow, season, episode', ''), ('1', 'mispelisyseries', 'http://mispelisyseries.com/', 'movie', 'search')",
"enabled": true,
"visible": false
},
@@ -539,6 +539,27 @@
"default": true,
"enabled": true,
"visible": false
},
{
"id": "clonenewpct1_timeout_downloadpage",
"type": "list",
"label": "Timeout (segs.) en descarga de páginas o verificación de servidores",
"default": 5,
"enabled": true,
"visible": true,
"lvalues": [
"None",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10"
]
}
]
}

View File

@@ -12,40 +12,53 @@ from core import httptools
from core import scrapertools
from core import servertools
from core.item import Item
from platformcode import config, logger
from platformcode import config, logger, platformtools
from core import tmdb
from lib import generictools
host = 'http://torrentrapid.com/'
channel_py = 'newpct1'
#Código para permitir usar un único canal para todas las webs clones de NewPct1
clone_list = config.get_setting('clonenewpct1_channels_list', "torrentrapid") #Carga lista de clones
clone_list = ast.literal_eval(clone_list) #la convierte a lista de tuplas
clone_list = config.get_setting('clonenewpct1_channels_list', channel_py) #Carga lista de clones
clone_list = ast.literal_eval(clone_list) #la convierte en array
host_index = 0
host_index = config.get_setting('clonenewpct1_channel_default', "torrentrapid") #Clone por defecto
host_index = config.get_setting('clonenewpct1_channel_default', channel_py) #Clone por defecto
i = 0
for active_clone, channel_clone, host_clone, contentType_clone, info_clone in clone_list:
if i == host_index:
#channel_clone_name = channel_clone #ACTIVAR CUANDO SE PASE A NEWPCT1
#host = 'http://%s/' % host_clone #ACTIVAR CUANDO SE PASE A NEWPCT1
i += 1
channel_clone_name = channel_clone #Nombre del Canal elegido
host = host_clone #URL del Canal elegido
break
i += 1
item = Item()
item.channel_host = host
if item.channel != channel_py:
item.channel = channel_py
item.category = channel_clone_name.capitalize()
#Carga de opciones del canal
item = Item()
if not item.channel:
item.channel = scrapertools.find_single_match(host, r'(\w+)\.com\/')
channel_clone_name = scrapertools.find_single_match(host, r'(\w+)\.com\/') #QUITAR CUANDO SE PASE A NEWPCT1
__modo_grafico__ = config.get_setting('modo_grafico', item.channel)
modo_ultima_temp = config.get_setting('seleccionar_ult_temporadda_activa', item.channel)
__modo_grafico__ = config.get_setting('modo_grafico', channel_py) #TMDB?
modo_ultima_temp = config.get_setting('seleccionar_ult_temporadda_activa', channel_py) #Actualización sólo últ. Temporada?
timeout = config.get_setting('clonenewpct1_timeout_downloadpage', channel_py) #Timeout downloadpage
if timeout == 0: timeout = None
platformtools.dialog_ok("NewPct1, ¡¡¡he vuelto como canal VIRTUAL!!!", "Hemos centralizado la gestión de los clones de NewPct1 en el canal virtual NewPct1. Los clones desaparecerán en breve.", "Para más información lee el tutorial: https://alfa-addon.com /threads/newpct1-implantando-alta-disponibilidad.1200/")
#Vayamos a la siguiente acción en el canal Newpct1
from platformcode import launcher
channel_clone_name = "torrentrapid" #Nombre del Canal elegido
host = "http://torrentrapid.com/"
item.category = channel_clone_name.capitalize()
item.action = "mainlist"
item.channel_host = host
launcher.run(item)
def mainlist(item):
logger.info()
if item.channel != channel_py:
return
#Renombramos el canal al nombre de clone elegido
item.channel = channel_clone_name
if item.category: item.category = channel_clone_name.capitalize()
itemlist = []
thumb_pelis = get_thumb("channels_movie.png")
@@ -58,20 +71,20 @@ def mainlist(item):
thumb_settings = get_thumb("setting_0.png")
itemlist.append(Item(channel=item.channel, action="submenu", title="Películas", url=host,
extra="peliculas", thumbnail=thumb_pelis ))
extra="peliculas", thumbnail=thumb_pelis, category=item.category))
itemlist.append(Item(channel=item.channel, action="submenu", title="Series", url=host, extra="series",
thumbnail=thumb_series))
thumbnail=thumb_series, category=item.category))
itemlist.append(Item(channel=item.channel, action="submenu", title="Documentales", url=host, extra="varios",
thumbnail=thumb_docus))
thumbnail=thumb_docus, category=item.category))
itemlist.append(
Item(channel=item.channel, action="search", title="Buscar", url=host + "buscar", thumbnail=thumb_buscar))
Item(channel=item.channel, action="search", title="Buscar", url=host + "buscar", thumbnail=thumb_buscar, category=item.category))
itemlist.append(
Item(channel=item.channel, action="", title="[COLOR yellow]Configuración de Servidores:[/COLOR]", url="", thumbnail=thumb_settings))
Item(channel=item.channel, action="", title="[COLOR yellow]Configuración de Servidores:[/COLOR]", url="", thumbnail=thumb_settings, category=item.category))
itemlist.append(
Item(channel=item.channel, action="settingCanal", title="Servidores para Ver Online y Descargas", url="", thumbnail=thumb_settings))
Item(channel=item.channel, action="settingCanal", title="Servidores para Ver Online y Descargas", url="", thumbnail=thumb_settings, category=item.category))
return itemlist
@@ -85,68 +98,60 @@ def submenu(item):
logger.info()
itemlist = []
data = ''
try:
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data)
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data)
except:
pass
host_alt = host
host_dom = host.replace("https://", "").replace("http://", "").replace("www.", "")
patron = '<li><a href="http://(?:www.)?' + host_dom + item.extra + '/">.*?<ul.*?>(.*?)</ul>'
patron = '<li><a\s?class="[^"]+"\s?href="http:[^"]+"><i\s?class=.*><\/i>.*Inicio<\/a><\/li>(.+)<\/ul>\s?<\/nav>'
#Verificamos si se ha cargado una página, y si además tiene la estructura correcta
if not data or not scrapertools.find_single_match(data, patron):
logger.error("ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL: " + item.url)
logger.error("ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL: " + item.url + data)
#Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú
item, data = generictools.fail_over_newpct1(item, patron)
if not data: #Si no ha logrado encontrar nada, salimos
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
elif item.channel_alt: #Si ha habido fail-over, lo comento
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR] [ALT ] en uso'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] caído'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR] [ALT ] en uso'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] inaccesible'))
host_alt = host.replace(item.channel_alt, item.channel)
del item.channel_alt
if item.url_alt: del item.url_alt
del item.channel_alt
#data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8")
#data = data.replace("'", '"').replace('/series"', '/series/"') #Compatibilidad con mispelisy.series.com
host_dom = host_alt.replace("https://", "").replace("http://", "").replace("www.", "")
patron = '<li><a href="http://(?:www.)?' + host_dom + item.extra + '/">.*?<ul.*?>(.*?)</ul>'
if "pelisyseries.com" in host_alt and item.extra == "varios": #compatibilidad con mispelisy.series.com
data = '<a href="' + host_alt + 'varios/" title="Documentales"><i class="icon-rocket"></i> Documentales</a>'
data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8")
data = data.replace("'", '"').replace('/series"', '/series/"') #Compatibilidad con mispelisy.series.com
if "pelisyseries.com" in item.channel_host and item.extra == "varios": #compatibilidad con mispelisy.series.com
data = '<li><a href="' + item.channel_host + 'varios/" title="Documentales">Documentales</a></li>'
else:
if data:
data = scrapertools.get_match(data, patron)
if not data:
logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
else:
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
data = scrapertools.get_match(data, patron) #Seleccionamos el trozo que nos interesa
if not data:
logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
patron = '<.*?href="([^"]+)".*?>([^>]+)</a>'
patron = '<li><a.*?href="([^"]+)"\s?.itle="[^"]+"\s?>([^>]+)<\/a><\/li>'
matches = re.compile(patron, re.DOTALL).findall(data)
if not matches:
logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
for scrapedurl, scrapedtitle in matches:
title = scrapedtitle.strip()
url = scrapedurl
itemlist.append(Item(channel=item.channel, action="listado", title=title, url=url, extra=item.extra))
itemlist.append(
Item(channel=item.channel, action="alfabeto", title=title + " [A-Z]", url=url, extra=item.extra))
#Preguntamos por las entradas que no corresponden al "extra"
if item.extra in scrapedtitle.lower() or (item.extra == "peliculas" and ("cine" in scrapedurl or "anime" in scrapedurl)) or (item.extra == "varios" and ("documentales" in scrapedurl or "varios" in scrapedurl)):
itemlist.append(item.clone(action="listado", title=title, url=scrapedurl))
itemlist.append(item.clone(action="alfabeto", title=title + " [A-Z]", url=scrapedurl))
if item.extra == "peliculas":
itemlist.append(Item(channel=item.channel, action="listado", title="Películas 4K", url=host_alt + "peliculas-hd/4kultrahd/", extra=item.extra))
itemlist.append(
Item(channel=item.channel, action="alfabeto", title="Películas 4K" + " [A-Z]", url=host_alt + "peliculas-hd/4kultrahd/", extra=item.extra))
itemlist.append(item.clone(action="listado", title="Películas 4K", url=item.channel_host + "peliculas-hd/4kultrahd/"))
itemlist.append(item.clone(action="alfabeto", title="Películas 4K" + " [A-Z]", url=item.channel_host + "peliculas-hd/4kultrahd/"))
return itemlist
@@ -155,28 +160,41 @@ def alfabeto(item):
logger.info()
itemlist = []
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data)
data = ''
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data)
data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8")
patron = '<ul class="alfabeto">(.*?)</ul>'
if data:
data = scrapertools.get_match(data, patron)
else:
return itemlist
if not data or not scrapertools.find_single_match(data, patron):
logger.error("ERROR 01: ALFABETO: La Web no responde o ha cambiado de URL: " + item.url + data)
#Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú
item, data = generictools.fail_over_newpct1(item, patron)
if not data: #Si no ha logrado encontrar nada, salimos
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: ALFABETO: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
elif item.channel_alt: #Si ha habido fail-over, lo comento
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR] [ALT ] en uso'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] inaccesible'))
if item.url_alt: del item.url_alt
del item.channel_alt
data = scrapertools.get_match(data, patron)
patron = '<a href="([^"]+)"[^>]+>([^>]+)</a>'
matches = re.compile(patron, re.DOTALL).findall(data)
if not matches:
logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log'))
logger.error("ERROR 02: ALFABETO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: ALFABETO: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
for scrapedurl, scrapedtitle in matches:
title = scrapedtitle.upper()
url = scrapedurl
itemlist.append(Item(channel=item.channel, action="listado", title=title, url=url, extra=item.extra))
itemlist.append(item.clone(action="listado", title=title, url=scrapedurl))
return itemlist
@@ -191,11 +209,21 @@ def listado(item):
if item.totalItems:
del item.totalItems
data = ''
try:
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data)
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data)
except:
pass
patron = '<ul class="' + clase + '">(.*?)</ul>' #seleccionamos el bloque que nos interesa
if not data or (not scrapertools.find_single_match(data, patron) and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data):
logger.error("ERROR 01: LISTADO: La Web no responde o ha cambiado de URL: " + item.url + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
#Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú
item, data = generictools.fail_over_newpct1(item, patron)
if not data: #Si no ha logrado encontrar nada, salimos
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: LISTADO: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
#Establecemos los valores básicos en función del tipo de contenido
@@ -218,7 +246,7 @@ def listado(item):
fichas = scrapertools.get_match(data, patron)
if not fichas and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data: #error
logger.error("ERROR 02: LISTADO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
elif '<h3><strong>( 0 ) Resultados encontrados </strong>' in data: #no hay vídeos
return itemlist
@@ -235,7 +263,7 @@ def listado(item):
matches = re.compile(patron, re.DOTALL).findall(fichas)
if not matches: #error
logger.error("ERROR 02: LISTADO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + fichas)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
#logger.debug("MATCHES: " + str(len(matches)))
@@ -460,13 +488,21 @@ def listado(item):
def listado_busqueda(item):
logger.info()
host = 'http://%s/' % scrapertools.find_single_match(item.url, '(\w+\.com)\/')
#Renombramos el canal al nombre de clone elegido. Actualizados URL
host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)')
#item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/')
if item.category and item.category != "newest":
item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize()
itemlist = []
cnt_tot = 40 # Poner el num. máximo de items por página. Dejamos que la web lo controle
cnt_title = 0 # Contador de líneas insertadas en Itemlist
cnt_pag = 0 # Contador de líneas leídas de Matches
timeout_search = 5 # Timeout un poco más largo para las búsquedas
if timeout > 5:
timeout_search = timeout # Timeout un poco más largo para las búsquedas
data = ''
if item.cnt_pag:
cnt_pag = item.cnt_pag # Se guarda en la lista de páginas anteriores en Item
@@ -493,21 +529,21 @@ def listado_busqueda(item):
#Máximo num. de líneas permitidas por TMDB. Máx de 5 páginas por Itemlist para no degradar el rendimiento
while cnt_title <= cnt_tot and cnt_next < 5:
pattern = '<ul class="%s">(.*?)</ul>' % item.pattern #seleccionamos el bloque que nos interesa
try:
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, post=item.post).data)
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, post=item.post, timeout=timeout_search).data)
except:
pass
cnt_next += 1
if not data or not scrapertools.find_single_match(data, pattern):
cnt_next += 1
pattern = '<ul class="%s">(.*?)</ul>' % item.pattern #seleccionamos el bloque que nos interesa
if not data or (not scrapertools.find_single_match(data, pattern) and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data):
logger.error("ERROR 01: LISTADO_BUSQUEDA: La Web no responde o ha cambiado de URL: " + item.url + item.post + " / DATA: " + data)
#Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú
item, data = generictools.fail_over_newpct1(item, pattern)
if not data: #Si no ha logrado encontrar nada, salimos
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO_BUSQUEDA:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: LISTADO_BUSQUEDA:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
elif item.channel_alt: #Si ha habido fail-over, lo comento
host = host.replace(item.channel_alt, item.channel)
@@ -531,7 +567,6 @@ def listado_busqueda(item):
pattern = '<ul class="%s">(.*?)</ul>' % item.pattern #seleccionamos el bloque que nos interesa
data_alt = data
data = scrapertools.get_match(data, pattern)
#pattern = '<li[^>]*><a href="(?P<url>[^"]+).*?<img.*?src="(?P<thumb>[^"]+)?".*?<h2.*?>(?P<title>.*?)?<\/h2>'
pattern = '<li[^>]*><a href="(?P<scrapedurl>[^"]+).*?' #url
pattern += 'title="(?P<scrapedtitle>[^"]+).*?' #título
pattern += '<img.*?src="(?P<scrapedthumbnail>[^"]+)?".*?' #thumb
@@ -541,7 +576,8 @@ def listado_busqueda(item):
matches_alt = re.compile(pattern, re.DOTALL).findall(data)
if not matches_alt and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data_alt: #error
logger.error("ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + data_alt)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web. Reportar el error con el log'))
item, itemlist = generictools.post_tmdb_listado(item, itemlist) #Pintamos los datos de fail-over, si los hay
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
#Ahora se hace una simulación para saber cuantas líneas podemos albergar en este Itemlist.
@@ -830,14 +866,14 @@ def listado_busqueda(item):
url_tvshow = host + calidad_mps + real_title_mps + "/" #... otras no. A probar...
#Leemos la página, a ver si es una página de episodios
data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_id).data)
data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_id, timeout=timeout).data)
data_serie = unicode(data_serie, "iso-8859-1", errors="replace").encode("utf-8")
data_serie = data_serie.replace("chapters", "buscar-list")
pattern = '<ul class="%s">(.*?)</ul>' % "buscar-list" #Patrón de lista de episodios
if not scrapertools.find_single_match(data_serie, pattern) and serieid: #no es válida la página,
#intentarlo con la otra url
data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_tvshow).data)
data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_tvshow, timeout=timeout).data)
data_serie = unicode(data_serie, "iso-8859-1", errors="replace").encode("utf-8")
data_serie = data_serie.replace("chapters", "buscar-list")
@@ -876,9 +912,10 @@ def findvideos(item):
from core import channeltools
logger.info()
#Renombramos el canal al nombre de clone elegido
item.channel = channel_clone_name
if item.category: item.category = channel_clone_name.capitalize()
#Renombramos el canal al nombre de clone elegido. Actualizados URL
host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)')
#item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/')
item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize()
itemlist = []
@@ -987,8 +1024,9 @@ def findvideos(item):
excluir_enlaces_descargas = [] #Lista vacía de servidores excluidos en Descargar
# Descarga la página
data = ''
try:
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data)
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data)
except:
pass
@@ -1001,7 +1039,7 @@ def findvideos(item):
item, data = generictools.fail_over_newpct1(item, patron)
if not data: #Si no ha logrado encontrar nada, salimos
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: FINDVIDEOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: FINDVIDEOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8")
@@ -1029,7 +1067,7 @@ def findvideos(item):
item_local.url = scrapertools.find_single_match(data, patron)
if not item_local.url: #error
logger.error("ERROR 02: FINDVIDEOS: El archivo Torrent no existe o ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: FINDVIDEOS: El archivo Torrent no existe o ha cambiado la estructura de la Web. Verificar en la Web y reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: FINDVIDEOS: El archivo Torrent no existe o ha cambiado la estructura de la Web. Verificar en la Web y reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
item_local.url = item_local.url.replace(" ", "%20") #sustituimos espacios por %20, por si acaso
#logger.debug("Patron: " + patron + " url: " + item_local.url)
@@ -1054,6 +1092,8 @@ def findvideos(item):
#logger.debug(item_local)
# VER vídeos, descargar vídeos un link, o múltiples links
data = scrapertools.find_single_match(data, '<div id="tab1" class="tab_content"(.*?<\/ul>(?:<div.*?>)?<\/div><\/div><\/div>)') #Seleccionar el bloque para evitar duplicados
host_dom = host.replace("https://", "").replace("http://", "").replace("www.", "")
data = data.replace("http://tumejorserie.com/descargar/url_encript.php?link=", "(")
data = re.sub(r'javascript:;" onClick="popup\("http:\/\/(?:www.)?' + host_dom + '\w{1,9}\/library\/include\/ajax\/get_modallinks.php\?links=', "", data)
@@ -1066,7 +1106,7 @@ def findvideos(item):
enlaces_ver = re.compile(patron, re.DOTALL).findall(data)
enlaces_descargar = enlaces_ver
#logger.debug(enlaces_ver)
#Recorre todos los links de VER, si está permitido
cnt_enl_ver = 1
cnt_enl_verif = 1
@@ -1100,7 +1140,7 @@ def findvideos(item):
if verificar_enlaces_veronline != 0: #Se quiere verificar si el link está activo?
if cnt_enl_verif <= verificar_enlaces_veronline or verificar_enlaces_veronline == -1: #contador?
#Llama a la subfunción de check_list_links(itemlist) para cada link de servidor
item_local.alive = servertools.check_video_link(enlace, servidor) #activo el link ?
item_local.alive = servertools.check_video_link(enlace, servidor, timeout=timeout) #activo el link ?
if verificar_enlaces_veronline_validos: #Los links tienen que ser válidos para contarlos?
if item_local.alive == "Ok": #Sí
cnt_enl_verif += 1 #Movemos los contadores
@@ -1190,7 +1230,7 @@ def findvideos(item):
if verificar_enlaces_descargas != 0: #Se quiere verificar si el link está activo?
if cnt_enl_verif <= verificar_enlaces_descargas or verificar_enlaces_descargas == -1: #contador?
#Llama a la subfunción de check_list_links(itemlist) para primer link de servidor
item_local.alive = servertools.check_video_link(enlace, servidor) #activo el link ?
item_local.alive = servertools.check_video_link(enlace, servidor, timeout=timeout) #activo el link ?
if verificar_enlaces_descargas_validos: #Los links tienen que ser válidos para contarlos?
if item_local.alive == "Ok": #Sí
cnt_enl_verif += 1 #Movemos los contadores
@@ -1232,9 +1272,10 @@ def findvideos(item):
def episodios(item):
logger.info()
#Renombramos el canal al nombre de clone elegido
item.channel = channel_clone_name
if item.category: item.category = channel_clone_name.capitalize()
#Renombramos el canal al nombre de clone elegido. Actualizados URL
host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)')
#item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/')
item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize()
itemlist = []
@@ -1255,7 +1296,7 @@ def episodios(item):
data = ''
try:
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url).data)
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, timeout=timeout).data)
patron = '<ul class="%s">(.*?)</ul>' % "buscar-list" # item.pattern
data_alt = ''
if data: data_alt = scrapertools.get_match(data, patron)
@@ -1276,7 +1317,7 @@ def episodios(item):
if not data: #No se ha encontrado ningún canal activo para este vídeo
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: EPISODIOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: EPISODIOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log'))
return itemlist
#Busca y pre-carga todas las páginas de episodios que componen las serie, para obtener la url de cada página
@@ -1312,7 +1353,7 @@ def episodios(item):
break
try:
if not data:
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(page).data)
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(page, timeout=timeout).data)
data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8")
data = data.replace("chapters", "buscar-list") #Compatibilidad con mispelisy.series.com
pattern = '<ul class="%s">(.*?)</ul>' % "buscar-list" # item.pattern
@@ -1321,7 +1362,7 @@ def episodios(item):
raise
except:
logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / " + str(list_pages) + " / DATA: " + str(data))
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
if "pelisyseries.com" in item.url:
@@ -1331,7 +1372,7 @@ def episodios(item):
matches = re.compile(pattern, re.DOTALL).findall(data)
if not matches: #error
logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
#logger.debug("patron: " + pattern)
@@ -1399,7 +1440,7 @@ def episodios(item):
match = [m.groupdict() for m in r.finditer(info)][0]
if not match: #error
logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + info)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
if match['season'] is None: match['season'] = season #Si no se encuentran valores, pero poner lo básico
@@ -1449,8 +1490,6 @@ def episodios(item):
if item_local.active:
del item_local.active
if item_local.category:
del item_local.category
if item_local.infoLabels['title']:
del item_local.infoLabels['title']
item_local.context = "['buscar_trailer']"
@@ -1467,6 +1506,8 @@ def episodios(item):
del item_local.update_last
if item_local.update_next:
del item_local.update_next
if item_local.channel_host:
del item_local.channel_host
itemlist.append(item_local.clone())
@@ -1501,9 +1542,6 @@ def actualizar_titulos(item):
def search(item, texto):
logger.info("search:" + texto)
# texto = texto.replace(" ", "+")
item.channel = channel_clone_name
if item.category: item.category = channel_clone_name.capitalize()
try:
item.post = "q=%s" % texto

View File

@@ -12,40 +12,53 @@ from core import httptools
from core import scrapertools
from core import servertools
from core.item import Item
from platformcode import config, logger
from platformcode import config, logger, platformtools
from core import tmdb
from lib import generictools
host = 'http://tumejortorrent.com/'
channel_py = 'newpct1'
#Código para permitir usar un único canal para todas las webs clones de NewPct1
clone_list = config.get_setting('clonenewpct1_channels_list', "torrentrapid") #Carga lista de clones
clone_list = ast.literal_eval(clone_list) #la convierte a lista de tuplas
clone_list = config.get_setting('clonenewpct1_channels_list', channel_py) #Carga lista de clones
clone_list = ast.literal_eval(clone_list) #la convierte en array
host_index = 0
host_index = config.get_setting('clonenewpct1_channel_default', "torrentrapid") #Clone por defecto
host_index = config.get_setting('clonenewpct1_channel_default', channel_py) #Clone por defecto
i = 0
for active_clone, channel_clone, host_clone, contentType_clone, info_clone in clone_list:
if i == host_index:
#channel_clone_name = channel_clone #ACTIVAR CUANDO SE PASE A NEWPCT1
#host = 'http://%s/' % host_clone #ACTIVAR CUANDO SE PASE A NEWPCT1
i += 1
channel_clone_name = channel_clone #Nombre del Canal elegido
host = host_clone #URL del Canal elegido
break
i += 1
item = Item()
item.channel_host = host
if item.channel != channel_py:
item.channel = channel_py
item.category = channel_clone_name.capitalize()
#Carga de opciones del canal
item = Item()
if not item.channel:
item.channel = scrapertools.find_single_match(host, r'(\w+)\.com\/')
channel_clone_name = scrapertools.find_single_match(host, r'(\w+)\.com\/') #QUITAR CUANDO SE PASE A NEWPCT1
__modo_grafico__ = config.get_setting('modo_grafico', item.channel)
modo_ultima_temp = config.get_setting('seleccionar_ult_temporadda_activa', item.channel)
__modo_grafico__ = config.get_setting('modo_grafico', channel_py) #TMDB?
modo_ultima_temp = config.get_setting('seleccionar_ult_temporadda_activa', channel_py) #Actualización sólo últ. Temporada?
timeout = config.get_setting('clonenewpct1_timeout_downloadpage', channel_py) #Timeout downloadpage
if timeout == 0: timeout = None
platformtools.dialog_ok("NewPct1, ¡¡¡he vuelto como canal VIRTUAL!!!", "Hemos centralizado la gestión de los clones de NewPct1 en el canal virtual NewPct1. Los clones desaparecerán en breve.", "Para más información lee el tutorial: https://alfa-addon.com /threads/newpct1-implantando-alta-disponibilidad.1200/")
#Vayamos a la siguiente acción en el canal Newpct1
from platformcode import launcher
channel_clone_name = "tumejortorrent" #Nombre del Canal elegido
host = "http://tumejortorrent.com/"
item.category = channel_clone_name.capitalize()
item.action = "mainlist"
item.channel_host = host
launcher.run(item)
def mainlist(item):
logger.info()
if item.channel != channel_py:
return
#Renombramos el canal al nombre de clone elegido
item.channel = channel_clone_name
if item.category: item.category = channel_clone_name.capitalize()
itemlist = []
thumb_pelis = get_thumb("channels_movie.png")
@@ -58,20 +71,20 @@ def mainlist(item):
thumb_settings = get_thumb("setting_0.png")
itemlist.append(Item(channel=item.channel, action="submenu", title="Películas", url=host,
extra="peliculas", thumbnail=thumb_pelis ))
extra="peliculas", thumbnail=thumb_pelis, category=item.category))
itemlist.append(Item(channel=item.channel, action="submenu", title="Series", url=host, extra="series",
thumbnail=thumb_series))
thumbnail=thumb_series, category=item.category))
itemlist.append(Item(channel=item.channel, action="submenu", title="Documentales", url=host, extra="varios",
thumbnail=thumb_docus))
thumbnail=thumb_docus, category=item.category))
itemlist.append(
Item(channel=item.channel, action="search", title="Buscar", url=host + "buscar", thumbnail=thumb_buscar))
Item(channel=item.channel, action="search", title="Buscar", url=host + "buscar", thumbnail=thumb_buscar, category=item.category))
itemlist.append(
Item(channel=item.channel, action="", title="[COLOR yellow]Configuración de Servidores:[/COLOR]", url="", thumbnail=thumb_settings))
Item(channel=item.channel, action="", title="[COLOR yellow]Configuración de Servidores:[/COLOR]", url="", thumbnail=thumb_settings, category=item.category))
itemlist.append(
Item(channel=item.channel, action="settingCanal", title="Servidores para Ver Online y Descargas", url="", thumbnail=thumb_settings))
Item(channel=item.channel, action="settingCanal", title="Servidores para Ver Online y Descargas", url="", thumbnail=thumb_settings, category=item.category))
return itemlist
@@ -85,68 +98,60 @@ def submenu(item):
logger.info()
itemlist = []
data = ''
try:
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data)
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data)
except:
pass
host_alt = host
host_dom = host.replace("https://", "").replace("http://", "").replace("www.", "")
patron = '<li><a href="http://(?:www.)?' + host_dom + item.extra + '/">.*?<ul.*?>(.*?)</ul>'
patron = '<li><a\s?class="[^"]+"\s?href="http:[^"]+"><i\s?class=.*><\/i>.*Inicio<\/a><\/li>(.+)<\/ul>\s?<\/nav>'
#Verificamos si se ha cargado una página, y si además tiene la estructura correcta
if not data or not scrapertools.find_single_match(data, patron):
logger.error("ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL: " + item.url)
logger.error("ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL: " + item.url + data)
#Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú
item, data = generictools.fail_over_newpct1(item, patron)
if not data: #Si no ha logrado encontrar nada, salimos
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
elif item.channel_alt: #Si ha habido fail-over, lo comento
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR] [ALT ] en uso'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] caído'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR] [ALT ] en uso'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] inaccesible'))
host_alt = host.replace(item.channel_alt, item.channel)
del item.channel_alt
if item.url_alt: del item.url_alt
del item.channel_alt
#data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8")
#data = data.replace("'", '"').replace('/series"', '/series/"') #Compatibilidad con mispelisy.series.com
host_dom = host_alt.replace("https://", "").replace("http://", "").replace("www.", "")
patron = '<li><a href="http://(?:www.)?' + host_dom + item.extra + '/">.*?<ul.*?>(.*?)</ul>'
if "pelisyseries.com" in host_alt and item.extra == "varios": #compatibilidad con mispelisy.series.com
data = '<a href="' + host_alt + 'varios/" title="Documentales"><i class="icon-rocket"></i> Documentales</a>'
data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8")
data = data.replace("'", '"').replace('/series"', '/series/"') #Compatibilidad con mispelisy.series.com
if "pelisyseries.com" in item.channel_host and item.extra == "varios": #compatibilidad con mispelisy.series.com
data = '<li><a href="' + item.channel_host + 'varios/" title="Documentales">Documentales</a></li>'
else:
if data:
data = scrapertools.get_match(data, patron)
if not data:
logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
else:
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
data = scrapertools.get_match(data, patron) #Seleccionamos el trozo que nos interesa
if not data:
logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
patron = '<.*?href="([^"]+)".*?>([^>]+)</a>'
patron = '<li><a.*?href="([^"]+)"\s?.itle="[^"]+"\s?>([^>]+)<\/a><\/li>'
matches = re.compile(patron, re.DOTALL).findall(data)
if not matches:
logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
for scrapedurl, scrapedtitle in matches:
title = scrapedtitle.strip()
url = scrapedurl
itemlist.append(Item(channel=item.channel, action="listado", title=title, url=url, extra=item.extra))
itemlist.append(
Item(channel=item.channel, action="alfabeto", title=title + " [A-Z]", url=url, extra=item.extra))
#Preguntamos por las entradas que no corresponden al "extra"
if item.extra in scrapedtitle.lower() or (item.extra == "peliculas" and ("cine" in scrapedurl or "anime" in scrapedurl)) or (item.extra == "varios" and ("documentales" in scrapedurl or "varios" in scrapedurl)):
itemlist.append(item.clone(action="listado", title=title, url=scrapedurl))
itemlist.append(item.clone(action="alfabeto", title=title + " [A-Z]", url=scrapedurl))
if item.extra == "peliculas":
itemlist.append(Item(channel=item.channel, action="listado", title="Películas 4K", url=host_alt + "peliculas-hd/4kultrahd/", extra=item.extra))
itemlist.append(
Item(channel=item.channel, action="alfabeto", title="Películas 4K" + " [A-Z]", url=host_alt + "peliculas-hd/4kultrahd/", extra=item.extra))
itemlist.append(item.clone(action="listado", title="Películas 4K", url=item.channel_host + "peliculas-hd/4kultrahd/"))
itemlist.append(item.clone(action="alfabeto", title="Películas 4K" + " [A-Z]", url=item.channel_host + "peliculas-hd/4kultrahd/"))
return itemlist
@@ -155,28 +160,41 @@ def alfabeto(item):
logger.info()
itemlist = []
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data)
data = ''
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data)
data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8")
patron = '<ul class="alfabeto">(.*?)</ul>'
if data:
data = scrapertools.get_match(data, patron)
else:
return itemlist
if not data or not scrapertools.find_single_match(data, patron):
logger.error("ERROR 01: ALFABETO: La Web no responde o ha cambiado de URL: " + item.url + data)
#Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú
item, data = generictools.fail_over_newpct1(item, patron)
if not data: #Si no ha logrado encontrar nada, salimos
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: ALFABETO: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
elif item.channel_alt: #Si ha habido fail-over, lo comento
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR] [ALT ] en uso'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] inaccesible'))
if item.url_alt: del item.url_alt
del item.channel_alt
data = scrapertools.get_match(data, patron)
patron = '<a href="([^"]+)"[^>]+>([^>]+)</a>'
matches = re.compile(patron, re.DOTALL).findall(data)
if not matches:
logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log'))
logger.error("ERROR 02: ALFABETO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: ALFABETO: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
for scrapedurl, scrapedtitle in matches:
title = scrapedtitle.upper()
url = scrapedurl
itemlist.append(Item(channel=item.channel, action="listado", title=title, url=url, extra=item.extra))
itemlist.append(item.clone(action="listado", title=title, url=scrapedurl))
return itemlist
@@ -191,11 +209,21 @@ def listado(item):
if item.totalItems:
del item.totalItems
data = ''
try:
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data)
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data)
except:
pass
patron = '<ul class="' + clase + '">(.*?)</ul>' #seleccionamos el bloque que nos interesa
if not data or (not scrapertools.find_single_match(data, patron) and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data):
logger.error("ERROR 01: LISTADO: La Web no responde o ha cambiado de URL: " + item.url + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
#Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú
item, data = generictools.fail_over_newpct1(item, patron)
if not data: #Si no ha logrado encontrar nada, salimos
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: LISTADO: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
#Establecemos los valores básicos en función del tipo de contenido
@@ -218,7 +246,7 @@ def listado(item):
fichas = scrapertools.get_match(data, patron)
if not fichas and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data: #error
logger.error("ERROR 02: LISTADO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
elif '<h3><strong>( 0 ) Resultados encontrados </strong>' in data: #no hay vídeos
return itemlist
@@ -235,7 +263,7 @@ def listado(item):
matches = re.compile(patron, re.DOTALL).findall(fichas)
if not matches: #error
logger.error("ERROR 02: LISTADO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + fichas)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
#logger.debug("MATCHES: " + str(len(matches)))
@@ -460,13 +488,21 @@ def listado(item):
def listado_busqueda(item):
logger.info()
host = 'http://%s/' % scrapertools.find_single_match(item.url, '(\w+\.com)\/')
#Renombramos el canal al nombre de clone elegido. Actualizados URL
host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)')
#item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/')
if item.category and item.category != "newest":
item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize()
itemlist = []
cnt_tot = 40 # Poner el num. máximo de items por página. Dejamos que la web lo controle
cnt_title = 0 # Contador de líneas insertadas en Itemlist
cnt_pag = 0 # Contador de líneas leídas de Matches
timeout_search = 5 # Timeout un poco más largo para las búsquedas
if timeout > 5:
timeout_search = timeout # Timeout un poco más largo para las búsquedas
data = ''
if item.cnt_pag:
cnt_pag = item.cnt_pag # Se guarda en la lista de páginas anteriores en Item
@@ -493,21 +529,21 @@ def listado_busqueda(item):
#Máximo num. de líneas permitidas por TMDB. Máx de 5 páginas por Itemlist para no degradar el rendimiento
while cnt_title <= cnt_tot and cnt_next < 5:
pattern = '<ul class="%s">(.*?)</ul>' % item.pattern #seleccionamos el bloque que nos interesa
try:
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, post=item.post).data)
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, post=item.post, timeout=timeout_search).data)
except:
pass
cnt_next += 1
if not data or not scrapertools.find_single_match(data, pattern):
cnt_next += 1
pattern = '<ul class="%s">(.*?)</ul>' % item.pattern #seleccionamos el bloque que nos interesa
if not data or (not scrapertools.find_single_match(data, pattern) and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data):
logger.error("ERROR 01: LISTADO_BUSQUEDA: La Web no responde o ha cambiado de URL: " + item.url + item.post + " / DATA: " + data)
#Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú
item, data = generictools.fail_over_newpct1(item, pattern)
if not data: #Si no ha logrado encontrar nada, salimos
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO_BUSQUEDA:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: LISTADO_BUSQUEDA:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
elif item.channel_alt: #Si ha habido fail-over, lo comento
host = host.replace(item.channel_alt, item.channel)
@@ -531,7 +567,6 @@ def listado_busqueda(item):
pattern = '<ul class="%s">(.*?)</ul>' % item.pattern #seleccionamos el bloque que nos interesa
data_alt = data
data = scrapertools.get_match(data, pattern)
#pattern = '<li[^>]*><a href="(?P<url>[^"]+).*?<img.*?src="(?P<thumb>[^"]+)?".*?<h2.*?>(?P<title>.*?)?<\/h2>'
pattern = '<li[^>]*><a href="(?P<scrapedurl>[^"]+).*?' #url
pattern += 'title="(?P<scrapedtitle>[^"]+).*?' #título
pattern += '<img.*?src="(?P<scrapedthumbnail>[^"]+)?".*?' #thumb
@@ -541,7 +576,8 @@ def listado_busqueda(item):
matches_alt = re.compile(pattern, re.DOTALL).findall(data)
if not matches_alt and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data_alt: #error
logger.error("ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + data_alt)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web. Reportar el error con el log'))
item, itemlist = generictools.post_tmdb_listado(item, itemlist) #Pintamos los datos de fail-over, si los hay
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
#Ahora se hace una simulación para saber cuantas líneas podemos albergar en este Itemlist.
@@ -830,14 +866,14 @@ def listado_busqueda(item):
url_tvshow = host + calidad_mps + real_title_mps + "/" #... otras no. A probar...
#Leemos la página, a ver si es una página de episodios
data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_id).data)
data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_id, timeout=timeout).data)
data_serie = unicode(data_serie, "iso-8859-1", errors="replace").encode("utf-8")
data_serie = data_serie.replace("chapters", "buscar-list")
pattern = '<ul class="%s">(.*?)</ul>' % "buscar-list" #Patrón de lista de episodios
if not scrapertools.find_single_match(data_serie, pattern) and serieid: #no es válida la página,
#intentarlo con la otra url
data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_tvshow).data)
data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_tvshow, timeout=timeout).data)
data_serie = unicode(data_serie, "iso-8859-1", errors="replace").encode("utf-8")
data_serie = data_serie.replace("chapters", "buscar-list")
@@ -876,9 +912,10 @@ def findvideos(item):
from core import channeltools
logger.info()
#Renombramos el canal al nombre de clone elegido
item.channel = channel_clone_name
if item.category: item.category = channel_clone_name.capitalize()
#Renombramos el canal al nombre de clone elegido. Actualizados URL
host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)')
#item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/')
item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize()
itemlist = []
@@ -987,8 +1024,9 @@ def findvideos(item):
excluir_enlaces_descargas = [] #Lista vacía de servidores excluidos en Descargar
# Descarga la página
data = ''
try:
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data)
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data)
except:
pass
@@ -1001,7 +1039,7 @@ def findvideos(item):
item, data = generictools.fail_over_newpct1(item, patron)
if not data: #Si no ha logrado encontrar nada, salimos
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: FINDVIDEOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: FINDVIDEOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8")
@@ -1029,7 +1067,7 @@ def findvideos(item):
item_local.url = scrapertools.find_single_match(data, patron)
if not item_local.url: #error
logger.error("ERROR 02: FINDVIDEOS: El archivo Torrent no existe o ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: FINDVIDEOS: El archivo Torrent no existe o ha cambiado la estructura de la Web. Verificar en la Web y reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: FINDVIDEOS: El archivo Torrent no existe o ha cambiado la estructura de la Web. Verificar en la Web y reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
item_local.url = item_local.url.replace(" ", "%20") #sustituimos espacios por %20, por si acaso
#logger.debug("Patron: " + patron + " url: " + item_local.url)
@@ -1054,6 +1092,8 @@ def findvideos(item):
#logger.debug(item_local)
# VER vídeos, descargar vídeos un link, o múltiples links
data = scrapertools.find_single_match(data, '<div id="tab1" class="tab_content"(.*?<\/ul>(?:<div.*?>)?<\/div><\/div><\/div>)') #Seleccionar el bloque para evitar duplicados
host_dom = host.replace("https://", "").replace("http://", "").replace("www.", "")
data = data.replace("http://tumejorserie.com/descargar/url_encript.php?link=", "(")
data = re.sub(r'javascript:;" onClick="popup\("http:\/\/(?:www.)?' + host_dom + '\w{1,9}\/library\/include\/ajax\/get_modallinks.php\?links=', "", data)
@@ -1066,7 +1106,7 @@ def findvideos(item):
enlaces_ver = re.compile(patron, re.DOTALL).findall(data)
enlaces_descargar = enlaces_ver
#logger.debug(enlaces_ver)
#Recorre todos los links de VER, si está permitido
cnt_enl_ver = 1
cnt_enl_verif = 1
@@ -1100,7 +1140,7 @@ def findvideos(item):
if verificar_enlaces_veronline != 0: #Se quiere verificar si el link está activo?
if cnt_enl_verif <= verificar_enlaces_veronline or verificar_enlaces_veronline == -1: #contador?
#Llama a la subfunción de check_list_links(itemlist) para cada link de servidor
item_local.alive = servertools.check_video_link(enlace, servidor) #activo el link ?
item_local.alive = servertools.check_video_link(enlace, servidor, timeout=timeout) #activo el link ?
if verificar_enlaces_veronline_validos: #Los links tienen que ser válidos para contarlos?
if item_local.alive == "Ok": #Sí
cnt_enl_verif += 1 #Movemos los contadores
@@ -1190,7 +1230,7 @@ def findvideos(item):
if verificar_enlaces_descargas != 0: #Se quiere verificar si el link está activo?
if cnt_enl_verif <= verificar_enlaces_descargas or verificar_enlaces_descargas == -1: #contador?
#Llama a la subfunción de check_list_links(itemlist) para primer link de servidor
item_local.alive = servertools.check_video_link(enlace, servidor) #activo el link ?
item_local.alive = servertools.check_video_link(enlace, servidor, timeout=timeout) #activo el link ?
if verificar_enlaces_descargas_validos: #Los links tienen que ser válidos para contarlos?
if item_local.alive == "Ok": #Sí
cnt_enl_verif += 1 #Movemos los contadores
@@ -1232,9 +1272,10 @@ def findvideos(item):
def episodios(item):
logger.info()
#Renombramos el canal al nombre de clone elegido
item.channel = channel_clone_name
if item.category: item.category = channel_clone_name.capitalize()
#Renombramos el canal al nombre de clone elegido. Actualizados URL
host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)')
#item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/')
item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize()
itemlist = []
@@ -1255,7 +1296,7 @@ def episodios(item):
data = ''
try:
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url).data)
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, timeout=timeout).data)
patron = '<ul class="%s">(.*?)</ul>' % "buscar-list" # item.pattern
data_alt = ''
if data: data_alt = scrapertools.get_match(data, patron)
@@ -1276,7 +1317,7 @@ def episodios(item):
if not data: #No se ha encontrado ningún canal activo para este vídeo
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: EPISODIOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: EPISODIOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log'))
return itemlist
#Busca y pre-carga todas las páginas de episodios que componen las serie, para obtener la url de cada página
@@ -1312,7 +1353,7 @@ def episodios(item):
break
try:
if not data:
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(page).data)
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(page, timeout=timeout).data)
data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8")
data = data.replace("chapters", "buscar-list") #Compatibilidad con mispelisy.series.com
pattern = '<ul class="%s">(.*?)</ul>' % "buscar-list" # item.pattern
@@ -1321,7 +1362,7 @@ def episodios(item):
raise
except:
logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / " + str(list_pages) + " / DATA: " + str(data))
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
if "pelisyseries.com" in item.url:
@@ -1331,7 +1372,7 @@ def episodios(item):
matches = re.compile(pattern, re.DOTALL).findall(data)
if not matches: #error
logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
#logger.debug("patron: " + pattern)
@@ -1399,7 +1440,7 @@ def episodios(item):
match = [m.groupdict() for m in r.finditer(info)][0]
if not match: #error
logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + info)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
if match['season'] is None: match['season'] = season #Si no se encuentran valores, pero poner lo básico
@@ -1449,8 +1490,6 @@ def episodios(item):
if item_local.active:
del item_local.active
if item_local.category:
del item_local.category
if item_local.infoLabels['title']:
del item_local.infoLabels['title']
item_local.context = "['buscar_trailer']"
@@ -1467,6 +1506,8 @@ def episodios(item):
del item_local.update_last
if item_local.update_next:
del item_local.update_next
if item_local.channel_host:
del item_local.channel_host
itemlist.append(item_local.clone())
@@ -1501,9 +1542,6 @@ def actualizar_titulos(item):
def search(item, texto):
logger.info("search:" + texto)
# texto = texto.replace(" ", "+")
item.channel = channel_clone_name
if item.category: item.category = channel_clone_name.capitalize()
try:
item.post = "q=%s" % texto

View File

@@ -12,40 +12,53 @@ from core import httptools
from core import scrapertools
from core import servertools
from core.item import Item
from platformcode import config, logger
from platformcode import config, logger, platformtools
from core import tmdb
from lib import generictools
host = 'http://www.tvsinpagar.com/'
channel_py = 'newpct1'
#Código para permitir usar un único canal para todas las webs clones de NewPct1
clone_list = config.get_setting('clonenewpct1_channels_list', "torrentrapid") #Carga lista de clones
clone_list = ast.literal_eval(clone_list) #la convierte a lista de tuplas
clone_list = config.get_setting('clonenewpct1_channels_list', channel_py) #Carga lista de clones
clone_list = ast.literal_eval(clone_list) #la convierte en array
host_index = 0
host_index = config.get_setting('clonenewpct1_channel_default', "torrentrapid") #Clone por defecto
host_index = config.get_setting('clonenewpct1_channel_default', channel_py) #Clone por defecto
i = 0
for active_clone, channel_clone, host_clone, contentType_clone, info_clone in clone_list:
if i == host_index:
#channel_clone_name = channel_clone #ACTIVAR CUANDO SE PASE A NEWPCT1
#host = 'http://%s/' % host_clone #ACTIVAR CUANDO SE PASE A NEWPCT1
i += 1
channel_clone_name = channel_clone #Nombre del Canal elegido
host = host_clone #URL del Canal elegido
break
i += 1
item = Item()
item.channel_host = host
if item.channel != channel_py:
item.channel = channel_py
item.category = channel_clone_name.capitalize()
#Carga de opciones del canal
item = Item()
if not item.channel:
item.channel = scrapertools.find_single_match(host, r'(\w+)\.com\/')
channel_clone_name = scrapertools.find_single_match(host, r'(\w+)\.com\/') #QUITAR CUANDO SE PASE A NEWPCT1
__modo_grafico__ = config.get_setting('modo_grafico', item.channel)
modo_ultima_temp = config.get_setting('seleccionar_ult_temporadda_activa', item.channel)
__modo_grafico__ = config.get_setting('modo_grafico', channel_py) #TMDB?
modo_ultima_temp = config.get_setting('seleccionar_ult_temporadda_activa', channel_py) #Actualización sólo últ. Temporada?
timeout = config.get_setting('clonenewpct1_timeout_downloadpage', channel_py) #Timeout downloadpage
if timeout == 0: timeout = None
platformtools.dialog_ok("NewPct1, ¡¡¡he vuelto como canal VIRTUAL!!!", "Hemos centralizado la gestión de los clones de NewPct1 en el canal virtual NewPct1. Los clones desaparecerán en breve.", "Para más información lee el tutorial: https://alfa-addon.com /threads/newpct1-implantando-alta-disponibilidad.1200/")
#Vayamos a la siguiente acción en el canal Newpct1
from platformcode import launcher
channel_clone_name = "tvsinpagar" #Nombre del Canal elegido
host = "http://www.tvsinpagar.com/"
item.category = channel_clone_name.capitalize()
item.action = "mainlist"
item.channel_host = host
launcher.run(item)
def mainlist(item):
logger.info()
if item.channel != channel_py:
return
#Renombramos el canal al nombre de clone elegido
item.channel = channel_clone_name
if item.category: item.category = channel_clone_name.capitalize()
itemlist = []
thumb_pelis = get_thumb("channels_movie.png")
@@ -58,20 +71,20 @@ def mainlist(item):
thumb_settings = get_thumb("setting_0.png")
itemlist.append(Item(channel=item.channel, action="submenu", title="Películas", url=host,
extra="peliculas", thumbnail=thumb_pelis ))
extra="peliculas", thumbnail=thumb_pelis, category=item.category))
itemlist.append(Item(channel=item.channel, action="submenu", title="Series", url=host, extra="series",
thumbnail=thumb_series))
thumbnail=thumb_series, category=item.category))
itemlist.append(Item(channel=item.channel, action="submenu", title="Documentales", url=host, extra="varios",
thumbnail=thumb_docus))
thumbnail=thumb_docus, category=item.category))
itemlist.append(
Item(channel=item.channel, action="search", title="Buscar", url=host + "buscar", thumbnail=thumb_buscar))
Item(channel=item.channel, action="search", title="Buscar", url=host + "buscar", thumbnail=thumb_buscar, category=item.category))
itemlist.append(
Item(channel=item.channel, action="", title="[COLOR yellow]Configuración de Servidores:[/COLOR]", url="", thumbnail=thumb_settings))
Item(channel=item.channel, action="", title="[COLOR yellow]Configuración de Servidores:[/COLOR]", url="", thumbnail=thumb_settings, category=item.category))
itemlist.append(
Item(channel=item.channel, action="settingCanal", title="Servidores para Ver Online y Descargas", url="", thumbnail=thumb_settings))
Item(channel=item.channel, action="settingCanal", title="Servidores para Ver Online y Descargas", url="", thumbnail=thumb_settings, category=item.category))
return itemlist
@@ -85,68 +98,60 @@ def submenu(item):
logger.info()
itemlist = []
data = ''
try:
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data)
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data)
except:
pass
host_alt = host
host_dom = host.replace("https://", "").replace("http://", "").replace("www.", "")
patron = '<li><a href="http://(?:www.)?' + host_dom + item.extra + '/">.*?<ul.*?>(.*?)</ul>'
patron = '<li><a\s?class="[^"]+"\s?href="http:[^"]+"><i\s?class=.*><\/i>.*Inicio<\/a><\/li>(.+)<\/ul>\s?<\/nav>'
#Verificamos si se ha cargado una página, y si además tiene la estructura correcta
if not data or not scrapertools.find_single_match(data, patron):
logger.error("ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL: " + item.url)
logger.error("ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL: " + item.url + data)
#Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú
item, data = generictools.fail_over_newpct1(item, patron)
if not data: #Si no ha logrado encontrar nada, salimos
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: SUBMENU: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
elif item.channel_alt: #Si ha habido fail-over, lo comento
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR] [ALT ] en uso'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] caído'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR] [ALT ] en uso'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] inaccesible'))
host_alt = host.replace(item.channel_alt, item.channel)
del item.channel_alt
if item.url_alt: del item.url_alt
del item.channel_alt
#data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8")
#data = data.replace("'", '"').replace('/series"', '/series/"') #Compatibilidad con mispelisy.series.com
host_dom = host_alt.replace("https://", "").replace("http://", "").replace("www.", "")
patron = '<li><a href="http://(?:www.)?' + host_dom + item.extra + '/">.*?<ul.*?>(.*?)</ul>'
if "pelisyseries.com" in host_alt and item.extra == "varios": #compatibilidad con mispelisy.series.com
data = '<a href="' + host_alt + 'varios/" title="Documentales"><i class="icon-rocket"></i> Documentales</a>'
data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8")
data = data.replace("'", '"').replace('/series"', '/series/"') #Compatibilidad con mispelisy.series.com
if "pelisyseries.com" in item.channel_host and item.extra == "varios": #compatibilidad con mispelisy.series.com
data = '<li><a href="' + item.channel_host + 'varios/" title="Documentales">Documentales</a></li>'
else:
if data:
data = scrapertools.get_match(data, patron)
if not data:
logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
else:
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
data = scrapertools.get_match(data, patron) #Seleccionamos el trozo que nos interesa
if not data:
logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
patron = '<.*?href="([^"]+)".*?>([^>]+)</a>'
patron = '<li><a.*?href="([^"]+)"\s?.itle="[^"]+"\s?>([^>]+)<\/a><\/li>'
matches = re.compile(patron, re.DOTALL).findall(data)
if not matches:
logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
for scrapedurl, scrapedtitle in matches:
title = scrapedtitle.strip()
url = scrapedurl
itemlist.append(Item(channel=item.channel, action="listado", title=title, url=url, extra=item.extra))
itemlist.append(
Item(channel=item.channel, action="alfabeto", title=title + " [A-Z]", url=url, extra=item.extra))
#Preguntamos por las entradas que no corresponden al "extra"
if item.extra in scrapedtitle.lower() or (item.extra == "peliculas" and ("cine" in scrapedurl or "anime" in scrapedurl)) or (item.extra == "varios" and ("documentales" in scrapedurl or "varios" in scrapedurl)):
itemlist.append(item.clone(action="listado", title=title, url=scrapedurl))
itemlist.append(item.clone(action="alfabeto", title=title + " [A-Z]", url=scrapedurl))
if item.extra == "peliculas":
itemlist.append(Item(channel=item.channel, action="listado", title="Películas 4K", url=host_alt + "peliculas-hd/4kultrahd/", extra=item.extra))
itemlist.append(
Item(channel=item.channel, action="alfabeto", title="Películas 4K" + " [A-Z]", url=host_alt + "peliculas-hd/4kultrahd/", extra=item.extra))
itemlist.append(item.clone(action="listado", title="Películas 4K", url=item.channel_host + "peliculas-hd/4kultrahd/"))
itemlist.append(item.clone(action="alfabeto", title="Películas 4K" + " [A-Z]", url=item.channel_host + "peliculas-hd/4kultrahd/"))
return itemlist
@@ -155,28 +160,41 @@ def alfabeto(item):
logger.info()
itemlist = []
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data)
data = ''
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data)
data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8")
patron = '<ul class="alfabeto">(.*?)</ul>'
if data:
data = scrapertools.get_match(data, patron)
else:
return itemlist
if not data or not scrapertools.find_single_match(data, patron):
logger.error("ERROR 01: ALFABETO: La Web no responde o ha cambiado de URL: " + item.url + data)
#Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú
item, data = generictools.fail_over_newpct1(item, patron)
if not data: #Si no ha logrado encontrar nada, salimos
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: ALFABETO: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
elif item.channel_alt: #Si ha habido fail-over, lo comento
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR] [ALT ] en uso'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel_alt.capitalize() + '[/COLOR] inaccesible'))
if item.url_alt: del item.url_alt
del item.channel_alt
data = scrapertools.get_match(data, patron)
patron = '<a href="([^"]+)"[^>]+>([^>]+)</a>'
matches = re.compile(patron, re.DOTALL).findall(data)
if not matches:
logger.error("ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: SUBMENU: Ha cambiado la estructura de la Web. Reportar el error con el log'))
logger.error("ERROR 02: ALFABETO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: ALFABETO: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
for scrapedurl, scrapedtitle in matches:
title = scrapedtitle.upper()
url = scrapedurl
itemlist.append(Item(channel=item.channel, action="listado", title=title, url=url, extra=item.extra))
itemlist.append(item.clone(action="listado", title=title, url=scrapedurl))
return itemlist
@@ -191,11 +209,21 @@ def listado(item):
if item.totalItems:
del item.totalItems
data = ''
try:
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data)
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data)
except:
pass
patron = '<ul class="' + clase + '">(.*?)</ul>' #seleccionamos el bloque que nos interesa
if not data or (not scrapertools.find_single_match(data, patron) and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data):
logger.error("ERROR 01: LISTADO: La Web no responde o ha cambiado de URL: " + item.url + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
#Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú
item, data = generictools.fail_over_newpct1(item, patron)
if not data: #Si no ha logrado encontrar nada, salimos
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: LISTADO: La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
#Establecemos los valores básicos en función del tipo de contenido
@@ -218,7 +246,7 @@ def listado(item):
fichas = scrapertools.get_match(data, patron)
if not fichas and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data: #error
logger.error("ERROR 02: LISTADO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
elif '<h3><strong>( 0 ) Resultados encontrados </strong>' in data: #no hay vídeos
return itemlist
@@ -235,7 +263,7 @@ def listado(item):
matches = re.compile(patron, re.DOTALL).findall(fichas)
if not matches: #error
logger.error("ERROR 02: LISTADO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + fichas)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
#logger.debug("MATCHES: " + str(len(matches)))
@@ -460,13 +488,21 @@ def listado(item):
def listado_busqueda(item):
logger.info()
host = 'http://%s/' % scrapertools.find_single_match(item.url, '(\w+\.com)\/')
#Renombramos el canal al nombre de clone elegido. Actualizados URL
host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)')
#item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/')
if item.category and item.category != "newest":
item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize()
itemlist = []
cnt_tot = 40 # Poner el num. máximo de items por página. Dejamos que la web lo controle
cnt_title = 0 # Contador de líneas insertadas en Itemlist
cnt_pag = 0 # Contador de líneas leídas de Matches
timeout_search = 5 # Timeout un poco más largo para las búsquedas
if timeout > 5:
timeout_search = timeout # Timeout un poco más largo para las búsquedas
data = ''
if item.cnt_pag:
cnt_pag = item.cnt_pag # Se guarda en la lista de páginas anteriores en Item
@@ -493,21 +529,21 @@ def listado_busqueda(item):
#Máximo num. de líneas permitidas por TMDB. Máx de 5 páginas por Itemlist para no degradar el rendimiento
while cnt_title <= cnt_tot and cnt_next < 5:
pattern = '<ul class="%s">(.*?)</ul>' % item.pattern #seleccionamos el bloque que nos interesa
try:
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, post=item.post).data)
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, post=item.post, timeout=timeout_search).data)
except:
pass
cnt_next += 1
if not data or not scrapertools.find_single_match(data, pattern):
cnt_next += 1
pattern = '<ul class="%s">(.*?)</ul>' % item.pattern #seleccionamos el bloque que nos interesa
if not data or (not scrapertools.find_single_match(data, pattern) and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data):
logger.error("ERROR 01: LISTADO_BUSQUEDA: La Web no responde o ha cambiado de URL: " + item.url + item.post + " / DATA: " + data)
#Si no hay datos consistentes, llamamos al método de fail_over para que encuentre un canal que esté activo y pueda gestionar el submenú
item, data = generictools.fail_over_newpct1(item, pattern)
if not data: #Si no ha logrado encontrar nada, salimos
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO_BUSQUEDA:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: LISTADO_BUSQUEDA:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
elif item.channel_alt: #Si ha habido fail-over, lo comento
host = host.replace(item.channel_alt, item.channel)
@@ -531,7 +567,6 @@ def listado_busqueda(item):
pattern = '<ul class="%s">(.*?)</ul>' % item.pattern #seleccionamos el bloque que nos interesa
data_alt = data
data = scrapertools.get_match(data, pattern)
#pattern = '<li[^>]*><a href="(?P<url>[^"]+).*?<img.*?src="(?P<thumb>[^"]+)?".*?<h2.*?>(?P<title>.*?)?<\/h2>'
pattern = '<li[^>]*><a href="(?P<scrapedurl>[^"]+).*?' #url
pattern += 'title="(?P<scrapedtitle>[^"]+).*?' #título
pattern += '<img.*?src="(?P<scrapedthumbnail>[^"]+)?".*?' #thumb
@@ -541,7 +576,8 @@ def listado_busqueda(item):
matches_alt = re.compile(pattern, re.DOTALL).findall(data)
if not matches_alt and not '<h3><strong>( 0 ) Resultados encontrados </strong>' in data_alt: #error
logger.error("ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + data_alt)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: LISTADO_BUSQUEDA: Ha cambiado la estructura de la Web. Reportar el error con el log'))
item, itemlist = generictools.post_tmdb_listado(item, itemlist) #Pintamos los datos de fail-over, si los hay
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
#Ahora se hace una simulación para saber cuantas líneas podemos albergar en este Itemlist.
@@ -830,14 +866,14 @@ def listado_busqueda(item):
url_tvshow = host + calidad_mps + real_title_mps + "/" #... otras no. A probar...
#Leemos la página, a ver si es una página de episodios
data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_id).data)
data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_id, timeout=timeout).data)
data_serie = unicode(data_serie, "iso-8859-1", errors="replace").encode("utf-8")
data_serie = data_serie.replace("chapters", "buscar-list")
pattern = '<ul class="%s">(.*?)</ul>' % "buscar-list" #Patrón de lista de episodios
if not scrapertools.find_single_match(data_serie, pattern) and serieid: #no es válida la página,
#intentarlo con la otra url
data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_tvshow).data)
data_serie = data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(url_tvshow, timeout=timeout).data)
data_serie = unicode(data_serie, "iso-8859-1", errors="replace").encode("utf-8")
data_serie = data_serie.replace("chapters", "buscar-list")
@@ -876,9 +912,10 @@ def findvideos(item):
from core import channeltools
logger.info()
#Renombramos el canal al nombre de clone elegido
item.channel = channel_clone_name
if item.category: item.category = channel_clone_name.capitalize()
#Renombramos el canal al nombre de clone elegido. Actualizados URL
host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)')
#item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/')
item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize()
itemlist = []
@@ -987,8 +1024,9 @@ def findvideos(item):
excluir_enlaces_descargas = [] #Lista vacía de servidores excluidos en Descargar
# Descarga la página
data = ''
try:
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url).data)
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data)
except:
pass
@@ -1001,7 +1039,7 @@ def findvideos(item):
item, data = generictools.fail_over_newpct1(item, patron)
if not data: #Si no ha logrado encontrar nada, salimos
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: FINDVIDEOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: FINDVIDEOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8")
@@ -1029,7 +1067,7 @@ def findvideos(item):
item_local.url = scrapertools.find_single_match(data, patron)
if not item_local.url: #error
logger.error("ERROR 02: FINDVIDEOS: El archivo Torrent no existe o ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: FINDVIDEOS: El archivo Torrent no existe o ha cambiado la estructura de la Web. Verificar en la Web y reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: FINDVIDEOS: El archivo Torrent no existe o ha cambiado la estructura de la Web. Verificar en la Web y reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
item_local.url = item_local.url.replace(" ", "%20") #sustituimos espacios por %20, por si acaso
#logger.debug("Patron: " + patron + " url: " + item_local.url)
@@ -1054,6 +1092,8 @@ def findvideos(item):
#logger.debug(item_local)
# VER vídeos, descargar vídeos un link, o múltiples links
data = scrapertools.find_single_match(data, '<div id="tab1" class="tab_content"(.*?<\/ul>(?:<div.*?>)?<\/div><\/div><\/div>)') #Seleccionar el bloque para evitar duplicados
host_dom = host.replace("https://", "").replace("http://", "").replace("www.", "")
data = data.replace("http://tumejorserie.com/descargar/url_encript.php?link=", "(")
data = re.sub(r'javascript:;" onClick="popup\("http:\/\/(?:www.)?' + host_dom + '\w{1,9}\/library\/include\/ajax\/get_modallinks.php\?links=', "", data)
@@ -1066,7 +1106,7 @@ def findvideos(item):
enlaces_ver = re.compile(patron, re.DOTALL).findall(data)
enlaces_descargar = enlaces_ver
#logger.debug(enlaces_ver)
#Recorre todos los links de VER, si está permitido
cnt_enl_ver = 1
cnt_enl_verif = 1
@@ -1100,7 +1140,7 @@ def findvideos(item):
if verificar_enlaces_veronline != 0: #Se quiere verificar si el link está activo?
if cnt_enl_verif <= verificar_enlaces_veronline or verificar_enlaces_veronline == -1: #contador?
#Llama a la subfunción de check_list_links(itemlist) para cada link de servidor
item_local.alive = servertools.check_video_link(enlace, servidor) #activo el link ?
item_local.alive = servertools.check_video_link(enlace, servidor, timeout=timeout) #activo el link ?
if verificar_enlaces_veronline_validos: #Los links tienen que ser válidos para contarlos?
if item_local.alive == "Ok": #Sí
cnt_enl_verif += 1 #Movemos los contadores
@@ -1190,7 +1230,7 @@ def findvideos(item):
if verificar_enlaces_descargas != 0: #Se quiere verificar si el link está activo?
if cnt_enl_verif <= verificar_enlaces_descargas or verificar_enlaces_descargas == -1: #contador?
#Llama a la subfunción de check_list_links(itemlist) para primer link de servidor
item_local.alive = servertools.check_video_link(enlace, servidor) #activo el link ?
item_local.alive = servertools.check_video_link(enlace, servidor, timeout=timeout) #activo el link ?
if verificar_enlaces_descargas_validos: #Los links tienen que ser válidos para contarlos?
if item_local.alive == "Ok": #Sí
cnt_enl_verif += 1 #Movemos los contadores
@@ -1232,9 +1272,10 @@ def findvideos(item):
def episodios(item):
logger.info()
#Renombramos el canal al nombre de clone elegido
item.channel = channel_clone_name
if item.category: item.category = channel_clone_name.capitalize()
#Renombramos el canal al nombre de clone elegido. Actualizados URL
host = scrapertools.find_single_match(item.url, '(http.?\:\/\/(?:www.)?\w+\.\w+\/)')
#item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/')
item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize()
itemlist = []
@@ -1255,7 +1296,7 @@ def episodios(item):
data = ''
try:
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url).data)
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(item.url, timeout=timeout).data)
patron = '<ul class="%s">(.*?)</ul>' % "buscar-list" # item.pattern
data_alt = ''
if data: data_alt = scrapertools.get_match(data, patron)
@@ -1276,7 +1317,7 @@ def episodios(item):
if not data: #No se ha encontrado ningún canal activo para este vídeo
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR]: Ningún canal NewPct1 activo'))
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: EPISODIOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 01: EPISODIOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log'))
return itemlist
#Busca y pre-carga todas las páginas de episodios que componen las serie, para obtener la url de cada página
@@ -1312,7 +1353,7 @@ def episodios(item):
break
try:
if not data:
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(page).data)
data = re.sub(r"\n|\r|\t|\s{2,}", "", httptools.downloadpage(page, timeout=timeout).data)
data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8")
data = data.replace("chapters", "buscar-list") #Compatibilidad con mispelisy.series.com
pattern = '<ul class="%s">(.*?)</ul>' % "buscar-list" # item.pattern
@@ -1321,7 +1362,7 @@ def episodios(item):
raise
except:
logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / " + str(list_pages) + " / DATA: " + str(data))
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
if "pelisyseries.com" in item.url:
@@ -1331,7 +1372,7 @@ def episodios(item):
matches = re.compile(pattern, re.DOTALL).findall(data)
if not matches: #error
logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + data)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
#logger.debug("patron: " + pattern)
@@ -1399,7 +1440,7 @@ def episodios(item):
match = [m.groupdict() for m in r.finditer(info)][0]
if not match: #error
logger.error("ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web " + " / PATRON: " + pattern + " / DATA: " + info)
itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
itemlist.append(item.clone(action='', title=item.category + ': ERROR 02: EPISODIOS: Ha cambiado la estructura de la Web. Reportar el error con el log'))
return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos
if match['season'] is None: match['season'] = season #Si no se encuentran valores, pero poner lo básico
@@ -1449,8 +1490,6 @@ def episodios(item):
if item_local.active:
del item_local.active
if item_local.category:
del item_local.category
if item_local.infoLabels['title']:
del item_local.infoLabels['title']
item_local.context = "['buscar_trailer']"
@@ -1467,6 +1506,8 @@ def episodios(item):
del item_local.update_last
if item_local.update_next:
del item_local.update_next
if item_local.channel_host:
del item_local.channel_host
itemlist.append(item_local.clone())
@@ -1501,9 +1542,6 @@ def actualizar_titulos(item):
def search(item, texto):
logger.info("search:" + texto)
# texto = texto.replace(" ", "+")
item.channel = channel_clone_name
if item.category: item.category = channel_clone_name.capitalize()
try:
item.post = "q=%s" % texto

View File

@@ -3,7 +3,6 @@
import os
import re
import sys
import unicodedata
import urllib
import time
@@ -15,10 +14,10 @@ from core import servertools
from core import tmdb
from core.item import Item
from platformcode import config, logger
from platformcode import platformtools
host = "http://tv-vip.com"
def mainlist(item):
logger.info()
item.viewmode = "movie"
@@ -511,13 +510,13 @@ def series_library(item):
# Funcion unicamente para añadir/actualizar series a la libreria
lista_episodios = []
show = item.show.strip()
data_serie = anti_cloudflare(item.url, host=host, headers=headers)
data_serie = httptools.downloadpage(item.url).data
data_serie = jsontools.load(data_serie)
# Para series que en la web se listan divididas por temporadas
if data_serie["sortedPlaylistChilds"]:
for season_name in data_serie["sortedPlaylistChilds"]:
url_season = host + "/json/playlist/%s/index.json" % season_name['id']
data = anti_cloudflare(url_season, host=host, headers=headers)
data = httptools.downloadpage(url_season).data
data = jsontools.load(data)
if data["sortedRepoChilds"]:
for child in data["sortedRepoChilds"]:
@@ -612,8 +611,9 @@ def play(item):
uri_request = host + "/video-prod/s/uri?uri=%s&_=%s" % (uri, int(time.time()))
data = httptools.downloadpage(uri_request).data
data = jsontools.load(data)
url = item.url.replace(".tv-vip.com/transcoder/", ".tv-vip.info/c/transcoder/") + "?tt=" + str(data['tt']) + \
url = item.url.replace(".tv-vip.com/transcoder/", ".tv-vip.in/c/transcoder/") + "?tt=" + str(data['tt']) + \
"&mm=" + data['mm'] + "&bb=" + data['bb']
url += "|User-Agent=Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Mobile Safari/537.36"
itemlist.append(item.clone(action="play", server="directo", url=url, folder=False))
return itemlist
@@ -622,7 +622,7 @@ def listas(item):
logger.info()
# Para añadir listas a la videoteca en carpeta CINE
itemlist = []
data = anti_cloudflare(item.url, host=host, headers=headers)
data = httptools.downloadpage(item.url).data
data = jsontools.load(data)
head = header_string + get_cookie_value()
for child in data["sortedRepoChilds"]:

View File

@@ -3,6 +3,6 @@
"name": "Tengo una URL",
"active": false,
"adult": false,
"thumbnail": "url.png",
"banner": "url.png"
"thumbnail": "tengourl.png",
"banner": "tengourl.png"
}

View File

@@ -1,21 +1,19 @@
# -*- coding: utf-8 -*-
from core import httptools
from core import scrapertools
from core import servertools
from core.item import Item
from platformcode import logger
from platformcode import config, logger
def mainlist(item):
logger.info()
itemlist = []
itemlist.append(Item(channel=item.channel, action="search",
title="Entra aquí y teclea la URL [Enlace a servidor online/descarga]"))
itemlist.append(
Item(channel=item.channel, action="search", title="Entra aquí y teclea la URL [Enlace directo a un vídeo]"))
itemlist.append(Item(channel=item.channel, action="search",
title="Entra aquí y teclea la URL [Búsqueda de enlaces en una url]"))
itemlist.append(Item(channel=item.channel, action="search", title=config.get_localized_string(60089)))
itemlist.append(Item(channel=item.channel, action="search", title=config.get_localized_string(60090)))
itemlist.append(Item(channel=item.channel, action="search", title=config.get_localized_string(60091)))
return itemlist
@@ -24,7 +22,7 @@ def mainlist(item):
def search(item, texto):
logger.info("texto=" + texto)
if not texto.startswith("http://"):
if not texto.startswith("http"):
texto = "http://" + texto
itemlist = []
@@ -35,16 +33,15 @@ def search(item, texto):
item.channel = "url"
item.action = "play"
elif "directo" in item.title:
itemlist.append(
Item(channel=item.channel, action="play", url=texto, server="directo", title="Ver enlace directo"))
itemlist.append(Item(channel=item.channel, action="play", url=texto, server="directo", title=config.get_localized_string(60092)))
else:
data = scrapertools.downloadpage(texto)
data = httptools.downloadpage(texto).data
itemlist = servertools.find_video_items(data=data)
for item in itemlist:
item.channel = "url"
item.action = "play"
if len(itemlist) == 0:
itemlist.append(Item(channel=item.channel, action="search", title="No hay ningún vídeo compatible en esa URL"))
itemlist.append(Item(channel=item.channel, action="search", title=config.get_localized_string(60093)))
return itemlist

View File

@@ -8,38 +8,38 @@
{
"id": "update",
"type": "list",
"label": "Actualizar la videoteca",
"label": "@60601",
"default": 1,
"visible": true,
"lvalues": [
"Nunca",
"Al iniciar Kodi",
"Una sola vez al día",
"Al iniciar Kodi y al menos una vez al día"
"@60602",
"@60603",
"@60604",
"@60605"
]
},
{
"id": "update_wait",
"type": "list",
"label": " Esperar antes de actualizar al iniciar kodi",
"label": "@60606",
"default": 0,
"visible": true,
"enabled": "eq(-1,Al iniciar Kodi)|eq(-1,Al iniciar Kodi y al menos una vez al día)",
"enabled": "eq(-1,@60603])|eq(-1,@60605])",
"lvalues": [
"No",
"10 seg",
"20 seg",
"30 seg",
"60 seg"
"@60609",
"@60610",
"@60611",
"@60612"
]
},
{
"id": "everyday_delay",
"type": "list",
"label": " Iniciar actualización programada a partir de las",
"label": "@60613",
"default": 1,
"visible": true,
"enabled": "eq(-2,Una sola vez al día)|eq(-2,Al iniciar Kodi y al menos una vez al día)",
"enabled": "eq(-2,@60604])|eq(-2,@60605])",
"lvalues": [
"00:00",
"04:00",
@@ -50,37 +50,37 @@
{
"id": "updatetvshows_interval",
"type": "list",
"label": " Buscar nuevos episodios en las series activas",
"label": "@60614",
"default": 0,
"visible": true,
"enabled": "!eq(-3,Nunca)",
"enabled": "!eq(-3,@60615])",
"lvalues": [
"Siempre",
"Según su emisión"
"@60616",
"@60617"
]
},
{
"id": "search_new_content",
"type": "list",
"label": " Realizar búsqueda de contenido en",
"label": "@60618",
"default": 0,
"enabled": "!eq(-4,Nunca)",
"enabled": "!eq(-4,@60615])",
"lvalues": [
"La carpeta de cada serie",
"Toda la videoteca"
"@60619",
"@60620"
]
},
{
"id": "addition",
"type": "label",
"label": "Añadir a la videoteca",
"label": "@70092",
"enabled": true,
"visible": true
},
{
"id": "enable_filter",
"type": "bool",
"label": " Excluir los streams que contienen etiquetas específicas",
"label": "@70090",
"enabled": true,
"visible": true,
"default": false
@@ -88,31 +88,32 @@
{
"id": "filters",
"type": "text",
"label": " Etiquetas",
"label": "@70091",
"visible": true,
"enabled": "eq(-1,true)"
},
{
"id": "window_type",
"type": "list",
"label": "Mostrar los enlaces en",
"default": 1,
"label": "@60621",
"default": 0,
"enabled": true,
"visible": true,
"lvalues": [
"Ventana convencional",
"Ventana emergente"
"@60622",
"@60623"
]
},
{
"id": "max_links",
"type": "list",
"label": " Numero máximo de enlaces a mostrar (recomendable para equipos lentos)",
"label": "@60624",
"default": 0,
"enabled": true,
"visible": true,
"lvalues": [
"Todos",
"@60625",
"30",
"60",
"90",
@@ -125,7 +126,7 @@
{
"id": "white_list_order",
"type": "bool",
"label": " Ordenar segun el orden de la lista blanca",
"label": "@60626",
"enabled": true,
"visible": true,
"default": false
@@ -133,7 +134,7 @@
{
"id": "quit_channel_name",
"type": "bool",
"label": " Quitar el nombre del canal del principio",
"label": "@60627",
"enabled": true,
"visible": true,
"default": false
@@ -141,7 +142,7 @@
{
"id": "replace_VD",
"type": "bool",
"label": " Ventana emergente: Reemplazar \"Ver en\" por \"[V]\" y \"Descargar en\" por \"[D]\"",
"label": "@60628",
"enabled": true,
"visible": true,
"default": false
@@ -149,33 +150,33 @@
{
"id": "db_mode",
"type": "list",
"label": "Ubicación de Base de datos",
"label": "@60629",
"default": 0,
"enabled": true,
"visible": true,
"lvalues": [
"Local",
"Remota"
"@60630",
"@60631"
]
},
{
"id": "xbmc_host",
"type": "text",
"label": " Nombre Servidor",
"label": "@60632",
"visible": true,
"enabled": "eq(-1,Remota)"
},
{
"id": "xbmc_puerto",
"type": "text",
"label": " Puerto Servidor",
"label": "@60633",
"enabled": "!eq(-1,'')",
"visible": true
},
{
"id": "mark_as_watched",
"type": "bool",
"label": "Marcar automáticamente como visto",
"label": "@60634",
"default": true,
"enabled": true,
"visible": true
@@ -183,7 +184,7 @@
{
"id": "watched_setting",
"type": "list",
"label": " Tiempo necesario del video",
"label": "@60635",
"default": 3,
"visible": true,
"enabled": "eq(-1,true)",
@@ -192,20 +193,20 @@
"30%",
"50%",
"80%",
"0 seg"
"@60636"
]
},
{
"id": "sync_trakt",
"type": "label",
"label": "Sincronización con Trakt",
"label": "@60637",
"enabled": true,
"visible": true
},
{
"id": "sync_trakt_watched",
"type": "bool",
"label": " Tras marcar como visto el episodio",
"label": "@60638",
"default": false,
"visible": true,
"enabled": "eq(-3,true)"
@@ -213,7 +214,7 @@
{
"id": "sync_trakt_notification",
"type": "bool",
"label": " Mostrar notificación",
"label": "@60639",
"default": true,
"visible": true,
"enabled": "eq(-1,true)"
@@ -221,7 +222,7 @@
{
"id": "sync_trakt_new_tvshow",
"type": "bool",
"label": " Al añadir una serie a la videoteca",
"label": "@60640",
"default": false,
"enabled": true,
"visible": true
@@ -229,7 +230,7 @@
{
"id": "sync_trakt_new_tvshow_wait",
"type": "bool",
"label": " Esperar a que se añada la serie a la videoteca",
"label": "@60641",
"default": true,
"visible": true,
"enabled": "eq(-1,true)"
@@ -237,57 +238,47 @@
{
"id": "show_all_seasons",
"type": "bool",
"label": "Mostrar la opción \"Todas las temporadas\"",
"label": "@60642",
"default": true
},
{
"id": "no_pile_on_seasons",
"type": "list",
"label": "No apilar temporadas de series",
"label": "@60643",
"default": 1,
"lvalues": [
"Nunca",
"Sólo si hay una temporada",
"Siempre"
"@60648",
"@60644",
"@60616"
]
},
{
"id": "ask_channel",
"type": "bool",
"label": "Mostrar cuadro de selección de canales",
"label": "@60645",
"default": false
},
{
"id": "original_title_folder",
"type": "list",
"label": "Crear directorios en el sistema usando",
"label": "@60646",
"default": 0,
"lvalues": [
"Título localizado",
"Título original"
]
},
{
"id": "lowerize_title",
"type": "list",
"label": "Crear directorios con letras en miúsculas",
"default": 0,
"lvalues": [
"Si",
"No"
"@60647",
"@60649"
]
},
{
"id": "lab_1",
"type": "label",
"label": "Al añadir contenido, obtener información de:",
"label": "@60650",
"enabled": true,
"visible": true
},
{
"id": "scraper_movies",
"type": "list",
"label": " Peliculas:",
"label": "@60651",
"enabled": false,
"default": 0,
"lvalues": [
@@ -298,7 +289,7 @@
{
"id": "scraper_tvshows",
"type": "list",
"label": " Series:",
"label": "@60652",
"default": 0,
"lvalues": [
"TheMovieDB.org",
@@ -308,7 +299,7 @@
{
"id": "tvdb_retry_eng",
"type": "bool",
"label": " Si no hay resultados buscar también en Inglés",
"label": "@60653",
"default": true,
"enabled": "eq(-1,TheTvDB.com)",
"visible": true

View File

@@ -15,10 +15,10 @@ def mainlist(item):
logger.info()
itemlist = list()
itemlist.append(Item(channel=item.channel, action="list_movies", title="Películas",
itemlist.append(Item(channel=item.channel, action="list_movies", title=config.get_localized_string(60509),
category="Videoteca de películas",
thumbnail=get_thumb("videolibrary_movie.png")))
itemlist.append(Item(channel=item.channel, action="list_tvshows", title="Series",
itemlist.append(Item(channel=item.channel, action="list_tvshows", title=config.get_localized_string(60600),
category="Videoteca de series",
thumbnail=get_thumb("videolibrary_tvshow.png")))
@@ -28,7 +28,7 @@ def mainlist(item):
def channel_config(item):
return platformtools.show_channel_settings(channelpath=os.path.join(config.get_runtime_path(), "channels",
item.channel),
caption="configuración -- Videoteca")
caption=config.get_localized_string(60598))
def list_movies(item):
@@ -54,10 +54,10 @@ def list_movies(item):
visto = new_item.library_playcounts.get(os.path.splitext(f)[0], 0)
new_item.infoLabels["playcount"] = visto
if visto > 0:
texto_visto = "Marcar película como no vista"
texto_visto = config.get_localized_string(60016)
contador = 0
else:
texto_visto = "Marcar película como vista"
texto_visto = config.get_localized_string(60017)
contador = 1
# Menu contextual: Eliminar serie/canal
@@ -65,10 +65,10 @@ def list_movies(item):
if "downloads" in new_item.library_urls:
num_canales -= 1
if num_canales > 1:
texto_eliminar = "Eliminar película/canal"
texto_eliminar = config.get_localized_string(60018)
multicanal = True
else:
texto_eliminar = "Eliminar esta película"
texto_eliminar = config.get_localized_string(60019)
multicanal = False
new_item.context = [{"title": texto_visto,
@@ -107,19 +107,19 @@ def list_tvshows(item):
visto = item_tvshow.library_playcounts.get(item_tvshow.contentTitle, 0)
item_tvshow.infoLabels["playcount"] = visto
if visto > 0:
texto_visto = "Marcar serie como no vista"
texto_visto = config.get_localized_string(60020)
contador = 0
else:
texto_visto = "Marcar serie como vista"
texto_visto = config.get_localized_string(60021)
contador = 1
# Menu contextual: Buscar automáticamente nuevos episodios o no
if item_tvshow.active and int(item_tvshow.active) > 0:
texto_update = "Buscar automáticamente nuevos episodios: Desactivar"
texto_update = config.get_localized_string(60022)
value = 0
item_tvshow.text_color = "green"
else:
texto_update = "Buscar automáticamente nuevos episodios: Activar"
texto_update = config.get_localized_string(60023)
value = 1
item_tvshow.text_color = "0xFFDF7401"
@@ -128,10 +128,10 @@ def list_tvshows(item):
if "downloads" in item_tvshow.library_urls:
num_canales -= 1
if num_canales > 1:
texto_eliminar = "Eliminar serie/canal"
texto_eliminar = config.get_localized_string(60024)
multicanal = True
else:
texto_eliminar = "Eliminar esta serie"
texto_eliminar = config.get_localized_string(60025)
multicanal = False
item_tvshow.context = [{"title": texto_visto,
@@ -160,7 +160,7 @@ def list_tvshows(item):
itemlist = sorted(itemlist, key=lambda it: it.title.lower())
itemlist.append(Item(channel=item.channel, action="update_videolibrary", thumbnail=item.thumbnail,
title="Buscar nuevos episodios y actualizar videoteca", folder=False))
title=config.get_localized_string(60026), folder=False))
return itemlist
@@ -182,7 +182,7 @@ def get_seasons(item):
for f in ficheros:
if f.endswith('.json'):
season = f.split('x')[0]
dict_temp[season] = "Temporada %s" % season
dict_temp[season] = config.get_localized_string(60027) % season
if config.get_setting("no_pile_on_seasons", "videolibrary") == 1 and len(
dict_temp) == 1: # Sólo si hay una temporada
@@ -205,10 +205,10 @@ def get_seasons(item):
visto = item_nfo.library_playcounts.get("season %s" % season, 0)
new_item.infoLabels["playcount"] = visto
if visto > 0:
texto = "Marcar temporada como no vista"
texto = config.get_localized_string(60028)
value = 0
else:
texto = "Marcar temporada como vista"
texto = config.get_localized_string(60029)
value = 1
new_item.context = [{"title": texto,
"action": "mark_season_as_watched",
@@ -222,7 +222,7 @@ def get_seasons(item):
itemlist = sorted(itemlist, key=lambda it: int(it.contentSeason))
if config.get_setting("show_all_seasons", "videolibrary"):
new_item = item.clone(action="get_episodes", title="*Todas las temporadas")
new_item = item.clone(action="get_episodes", title=config.get_localized_string(60030))
new_item.infoLabels["playcount"] = 0
itemlist.insert(0, new_item)
@@ -260,7 +260,7 @@ def get_episodes(item):
if epi.contentTitle:
title_episodie = epi.contentTitle.strip()
else:
title_episodie = "Temporada %s Episodio %s" % \
title_episodie = config.get_localized_string(60031) % \
(epi.contentSeason, str(epi.contentEpisodeNumber).zfill(2))
epi.contentTitle = "%sx%s" % (epi.contentSeason, str(epi.contentEpisodeNumber).zfill(2))
@@ -273,10 +273,10 @@ def get_episodes(item):
visto = item_nfo.library_playcounts.get(season_episode, 0)
epi.infoLabels["playcount"] = visto
if visto > 0:
texto = "Marcar episodio como no visto"
texto = config.get_localized_string(60032)
value = 0
else:
texto = "Marcar episodio como visto"
texto = config.get_localized_string(60033)
value = 1
epi.context = [{"title": texto,
"action": "mark_content_as_watched",
@@ -292,6 +292,7 @@ def get_episodes(item):
def findvideos(item):
logger.info()
from lib import generictools
# logger.debug("item:\n" + item.tostring('\n'))
itemlist = []
@@ -321,10 +322,11 @@ def findvideos(item):
list_canales[nom_canal] = filetools.join(path_dir, fd)
num_canales = len(list_canales)
# logger.debug(str(list_canales))
if 'downloads' in list_canales:
json_path = list_canales['downloads']
item_json = Item().fromjson(filetools.read(json_path))
item_json = generictools.redirect_clone_newpct1(item_json) ###### Redirección al canal NewPct1.py si es un clone
item_json.contentChannel = "local"
# Soporte para rutas relativas en descargas
if filetools.is_relative(item_json.url):
@@ -341,8 +343,8 @@ def findvideos(item):
filtro_canal = ''
if num_canales > 1 and config.get_setting("ask_channel", "videolibrary"):
opciones = ["Mostrar solo los enlaces de %s" % k.capitalize() for k in list_canales.keys()]
opciones.insert(0, "Mostrar todos los enlaces")
opciones = [config.get_localized_string(70089) % k.capitalize() for k in list_canales.keys()]
opciones.insert(0, config.get_localized_string(70083))
if item_local:
opciones.append(item_local.title)
@@ -356,13 +358,18 @@ def findvideos(item):
platformtools.play_video(item_local)
elif index > 0:
filtro_canal = opciones[index].replace("Mostrar solo los enlaces de ", "")
filtro_canal = opciones[index].replace(config.get_localized_string(70078), "")
itemlist = []
for nom_canal, json_path in list_canales.items():
if filtro_canal and filtro_canal != nom_canal.capitalize():
continue
item_canal = Item()
item_canal.channel = nom_canal
item_canal = generictools.redirect_clone_newpct1(item_canal) ###### Redirección al canal NewPct1.py si es un clone
nom_canal = item_canal.channel
# Importamos el canal de la parte seleccionada
try:
channel = __import__('channels.%s' % nom_canal, fromlist=["channels.%s" % nom_canal])
@@ -370,6 +377,7 @@ def findvideos(item):
exec "import channels." + nom_canal + " as channel"
item_json = Item().fromjson(filetools.read(json_path))
item_json = generictools.redirect_clone_newpct1(item_json) ###### Redirección al canal NewPct1.py si es un clone
list_servers = []
try:
@@ -450,7 +458,7 @@ def play(item):
v.title = item.contentTitle
else:
if item.contentType == "episode":
v.title = "Episodio %s" % item.contentEpisodeNumber
v.title = config.get_localized_string(60036) % item.contentEpisodeNumber
v.thumbnail = item.thumbnail
v.contentThumbnail = item.thumbnail
@@ -482,8 +490,8 @@ def update_tvshow(item):
logger.info()
# logger.debug("item:\n" + item.tostring('\n'))
heading = 'Actualizando serie....'
p_dialog = platformtools.dialog_progress_bg('alfa', heading)
heading = config.get_localized_string(60037)
p_dialog = platformtools.dialog_progress_bg(config.get_localized_string(20000), heading)
p_dialog.update(0, heading, item.contentSerieName)
import videolibrary_service
@@ -672,13 +680,13 @@ def delete(item):
# logger.debug(item.tostring('\n'))
if item.contentType == 'movie':
heading = "Eliminar película"
heading = config.get_localized_string(70084)
else:
heading = "Eliminar serie"
heading = config.get_localized_string(70085)
if item.multicanal:
# Obtener listado de canales
opciones = ["Eliminar solo los enlaces de %s" % k.capitalize() for k in item.library_urls.keys() if
opciones = [config.get_localized_string(70086) % k.capitalize() for k in item.library_urls.keys() if
k != "downloads"]
opciones.insert(0, heading)
@@ -690,7 +698,7 @@ def delete(item):
elif index > 0:
# Seleccionado Eliminar canal X
canal = opciones[index].replace("Eliminar solo los enlaces de ", "").lower()
canal = opciones[index].replace(config.get_localized_string(70079), "").lower()
num_enlaces = 0
for fd in filetools.listdir(item.path):
@@ -704,14 +712,14 @@ def delete(item):
del item_nfo.library_urls[canal]
filetools.write(item.nfo, head_nfo + item_nfo.tojson())
msg_txt = "Eliminados %s enlaces del canal %s" % (num_enlaces, canal)
msg_txt = config.get_localized_string(70087) % (num_enlaces, canal)
logger.info(msg_txt)
platformtools.dialog_notification(heading, msg_txt)
platformtools.itemlist_refresh()
else:
if platformtools.dialog_yesno(heading,
"¿Realmente desea eliminar '%s' de su videoteca?" % item.infoLabels['title']):
config.get_localized_string(70088) % item.infoLabels['title']):
delete_all(item)

1092
plugin.video.alfa/core/downloader.py Executable file → Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -18,6 +18,9 @@ from core.cloudflare import Cloudflare
from platformcode import config, logger
from platformcode.logger import WebErrorException
## Obtiene la versión del addon
__version = config.get_addon_version()
cookies_lock = Lock()
cj = cookielib.MozillaCookieJar()
@@ -31,6 +34,10 @@ default_headers["Accept-Language"] = "es-ES,es;q=0.8,en-US;q=0.5,en;q=0.3"
default_headers["Accept-Charset"] = "UTF-8"
default_headers["Accept-Encoding"] = "gzip"
# Tiempo máximo de espera para downloadpage, si no se especifica nada
HTTPTOOLS_DEFAULT_DOWNLOAD_TIMEOUT = config.get_setting('httptools_timeout', default=15)
if HTTPTOOLS_DEFAULT_DOWNLOAD_TIMEOUT == 0: HTTPTOOLS_DEFAULT_DOWNLOAD_TIMEOUT = None
def get_url_headers(url):
domain_cookies = cj._cookies.get("." + urlparse.urlparse(url)[1], {}).get("/", {})
@@ -122,8 +129,11 @@ def downloadpage(url, post=None, headers=None, timeout=None, follow_redirects=Tr
url = urllib.quote(url, safe="%/:=&?~#+!$,;'@()*[]")
# Limitar tiempo de descarga si no se ha pasado timeout y hay un valor establecido en la variable global
if timeout is None and HTTPTOOLS_DEFAULT_DOWNLOAD_TIMEOUT is not None: timeout = HTTPTOOLS_DEFAULT_DOWNLOAD_TIMEOUT
logger.info("----------------------------------------------")
logger.info("downloadpage")
logger.info("downloadpage Alfa: %s" %__version)
logger.info("----------------------------------------------")
logger.info("Timeout: %s" % timeout)
logger.info("URL: " + url)
@@ -270,3 +280,5 @@ class NoRedirectHandler(urllib2.HTTPRedirectHandler):
http_error_301 = http_error_302
http_error_303 = http_error_302
http_error_307 = http_error_302

View File

@@ -21,10 +21,10 @@ def find_and_set_infoLabels(item):
scraper = None
# logger.debug("item:\n" + item.tostring('\n'))
list_opciones_cuadro = ["Introducir otro nombre", "Completar información"]
list_opciones_cuadro = [config.get_localized_string(60223), config.get_localized_string(60224)]
# Si se añaden más scrapers hay q declararlos aqui-> "modulo_scraper": "Texto_en_cuadro"
scrapers_disponibles = {'tmdb': "Buscar en TheMovieDB.org",
'tvdb': "Buscar en TheTvDB.com"}
scrapers_disponibles = {'tmdb': config.get_localized_string(60225),
'tvdb': config.get_localized_string(60226)}
# Obtener el Scraper por defecto de la configuracion segun el tipo de contenido
if item.contentType == "movie":
@@ -63,10 +63,10 @@ def find_and_set_infoLabels(item):
return True
elif scraper_result:
# Contenido encontrado pero no hay 'code'
msg = "Identificador no encontrado para: %s" % title
msg = config.get_localized_string(60227) % title
else:
# Contenido no encontrado
msg = "No se ha encontrado informacion para: %s" % title
msg = config.get_localized_string(60228) % title
logger.info(msg)
# Mostrar cuadro con otras opciones:
@@ -80,7 +80,7 @@ def find_and_set_infoLabels(item):
elif index == 0:
# Pregunta el titulo
title = platformtools.dialog_input(title, "Introduzca el nombre de la %s a buscar" % tipo_contenido)
title = platformtools.dialog_input(title, config.get_localized_string(60229) % tipo_contenido)
if title:
if item.contentType == "movie":
item.contentTitle = title
@@ -125,19 +125,19 @@ def cuadro_completar(item):
COLOR = ["0xFF8A4B08", "0xFFF7BE81"]
# Creamos la lista de campos del infoLabel
controls = [("title", "text", "Titulo:"),
("originaltitle", "text", "Titulo original"),
("year", "text", "Año"),
("identificadores", "label", "Identificadores:"),
("tmdb_id", "text", " The Movie Database ID"),
("url_tmdb", "text", " URL Tmdb", "+!eq(-1,'')"),
("tvdb_id", "text", " The TVDB ID", "+eq(-7,'Serie')"),
("url_tvdb", "text", " URL TVDB", "+!eq(-1,'')+eq(-8,'Serie')"),
("imdb_id", "text", " IMDb ID"),
("otro_id", "text", " Otro ID", "+eq(-1,'')"),
("urls", "label", "Imágenes (urls):"),
("fanart", "text", " Fondo"),
("thumbnail", "text", " Miniatura")]
controls = [("title", "text", config.get_localized_string(60230)),
("originaltitle", "text", config.get_localized_string(60231)),
("year", "text", config.get_localized_string(60232)),
("identificadores", "label", config.get_localized_string(60233)),
("tmdb_id", "text", config.get_localized_string(60234)),
("url_tmdb", "text", config.get_localized_string(60235), "+!eq(-1,'')"),
("tvdb_id", "text", config.get_localized_string(60236), "+eq(-7,'Serie')"),
("url_tvdb", "text", config.get_localized_string(60237), "+!eq(-1,'')+eq(-8,'Serie')"),
("imdb_id", "text", config.get_localized_string(60238)),
("otro_id", "text", config.get_localized_string(60239), "+eq(-1,'')"),
("urls", "label", config.get_localized_string(60240)),
("fanart", "text", config.get_localized_string(60241)),
("thumbnail", "text", config.get_localized_string(60242))]
if item.infoLabels["mediatype"] == "movie":
mediatype_default = 0
@@ -146,12 +146,12 @@ def cuadro_completar(item):
listado_controles = [{'id': "mediatype",
'type': "list",
'label': "Tipo de contenido",
'label': config.get_localized_string(60243),
'color': COLOR[1],
'default': mediatype_default,
'enabled': True,
'visible': True,
'lvalues': ["Película", "Serie"]
'lvalues': [config.get_localized_string(60244), config.get_localized_string(60245)]
}]
for i, c in enumerate(controls):
@@ -188,7 +188,7 @@ def cuadro_completar(item):
'visible': True})
# logger.debug(dict_default)
if platformtools.show_channel_settings(list_controls=listado_controles, caption="Completar información", item=item,
if platformtools.show_channel_settings(list_controls=listado_controles, caption=config.get_localized_string(60246), item=item,
callback="core.scraper.callback_cuadro_completar",
custom_button={"visible": False}):
return True
@@ -263,7 +263,6 @@ def get_nfo(item):
def sort_episode_list(episodelist):
episodelist.sort(key=lambda e: e.title, reverse=True)
scraper_actual = ['tmdb', 'tvdb'][config.get_setting("scraper_tvshows", "videolibrary")]
if scraper_actual == "tmdb":

View File

@@ -706,21 +706,27 @@ def filter_servers(servers_list):
return servers_list
def check_list_links(itemlist, numero):
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Comprobación de enlaces
# -----------------------
def check_list_links(itemlist, numero='', timeout=3):
"""
Comprueba una lista de enlaces a videos y la devuelve modificando el titulo con la verificacion.
El segundo parametro (numero) indica cuantos enlaces hay que verificar (0:5, 1:10, 2:15, 3:20)
El parámetro numero indica cuantos enlaces hay que verificar (0:5, 1:10, 2:15, 3:20)
El parámetro timeout indica un tope de espera para descargar la página
"""
numero = ((int(numero) + 1) * 5) if numero != '' else 10
for it in itemlist:
if numero > 0 and it.server != '' and it.url != '':
verificacion = check_video_link(it.url, it.server)
verificacion = check_video_link(it.url, it.server, timeout)
it.title = verificacion + ', ' + it.title.strip()
it.alive = verificacion
numero -= 1
return itemlist
def check_video_link(url, server):
def check_video_link(url, server, timeout=3):
"""
Comprueba si el enlace a un video es valido y devuelve un string de 2 posiciones con la verificacion.
:param url, server: Link y servidor
@@ -734,17 +740,23 @@ def check_video_link(url, server):
return "??"
if hasattr(server_module, 'test_video_exists'):
ant_timeout = httptools.HTTPTOOLS_DEFAULT_DOWNLOAD_TIMEOUT
httptools.HTTPTOOLS_DEFAULT_DOWNLOAD_TIMEOUT = timeout # Limitar tiempo de descarga
try:
video_exists, message = server_module.test_video_exists(page_url=url)
if not video_exists:
logger.info("[check_video_link] No existe! %s %s %s" % (message, server, url))
return "NO"
resultado = "NO"
else:
logger.info("[check_video_link] comprovacion OK %s %s" % (server, url))
return "Ok"
logger.info("[check_video_link] comprobacion OK %s %s" % (server, url))
resultado = "Ok"
except:
logger.info("[check_video_link] No se puede comprobar ahora! %s %s" % (server, url))
return "??"
resultado = "??"
finally:
httptools.HTTPTOOLS_DEFAULT_DOWNLOAD_TIMEOUT = ant_timeout # Restaurar tiempo de descarga
return resultado
logger.info("[check_video_link] No hay test_video_exists para servidor: %s" % server)
return "??"

View File

@@ -116,7 +116,7 @@ def save_movie(item):
_id = item.infoLabels['code'][0]
# progress dialog
p_dialog = platformtools.dialog_progress('alfa', 'Añadiendo película...')
p_dialog = platformtools.dialog_progress(config.get_localized_string(20000), config.get_localized_string(60062))
if config.get_setting("original_title_folder", "videolibrary") == 1 and item.infoLabels['originaltitle']:
base_name = item.infoLabels['originaltitle']
@@ -197,7 +197,7 @@ def save_movie(item):
# Si llegamos a este punto es por q algo ha fallado
logger.error("No se ha podido guardar %s en la videoteca" % item.contentTitle)
p_dialog.update(100, 'Fallo al añadir...', item.contentTitle)
p_dialog.update(100, config.get_localized_string(60063), item.contentTitle)
p_dialog.close()
return 0, 0, -1
@@ -366,8 +366,8 @@ def save_episodes(path, episodelist, serie, silent=False, overwrite=True):
# Silent es para no mostrar progreso (para videolibrary_service)
if not silent:
# progress dialog
p_dialog = platformtools.dialog_progress('alfa', 'Añadiendo episodios...')
p_dialog.update(0, 'Añadiendo episodio...')
p_dialog = platformtools.dialog_progress(config.get_localized_string(20000), config.get_localized_string(60064))
p_dialog.update(0, config.get_localized_string(60065))
new_episodelist = []
# Obtenemos el numero de temporada y episodio y descartamos los q no lo sean
@@ -616,21 +616,20 @@ def add_tvshow(item, channel=None):
insertados, sobreescritos, fallidos, path = save_tvshow(item, itemlist)
if not insertados and not sobreescritos and not fallidos:
platformtools.dialog_ok("Videoteca", "ERROR, la serie NO se ha añadido a la videoteca",
"No se ha podido obtener ningun episodio")
platformtools.dialog_ok(config.get_localized_string(30131), config.get_localized_string(60067))
logger.error("La serie %s no se ha podido añadir a la videoteca. No se ha podido obtener ningun episodio"
% item.show)
elif fallidos == -1:
platformtools.dialog_ok("Videoteca", "ERROR, la serie NO se ha añadido a la videoteca")
platformtools.dialog_ok(config.get_localized_string(30131), config.get_localized_string(60068))
logger.error("La serie %s no se ha podido añadir a la videoteca" % item.show)
elif fallidos > 0:
platformtools.dialog_ok("Videoteca", "ERROR, la serie NO se ha añadido completa a la videoteca")
platformtools.dialog_ok(config.get_localized_string(30131), config.get_localized_string(60069))
logger.error("No se han podido añadir %s episodios de la serie %s a la videoteca" % (fallidos, item.show))
else:
platformtools.dialog_ok("Videoteca", "La serie se ha añadido a la videoteca")
platformtools.dialog_ok(config.get_localized_string(30131), config.get_localized_string(60070))
logger.info("Se han añadido %s episodios de la serie %s a la videoteca" %
(insertados, item.show))
if config.is_xbmc():

View File

@@ -21,6 +21,8 @@ from core.item import Item
from platformcode import config, logger
from core import tmdb
channel_py = "newpct1"
def update_title(item):
logger.info()
@@ -64,7 +66,13 @@ def update_title(item):
item.title = item.from_title
del item.from_title
else:
item.add_videolibrary = True #Estamos Añadiendo a la Videoteca. Indicador para control de uso de los Canales
if item.contentType != "movie":
item.add_videolibrary = True #Estamos Añadiendo a la Videoteca. Indicador para control de uso de los Canales
else:
if item.channel == channel_py: #Si es una peli de NewPct1, ponemos el nombre del clone
item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/')
if item.channel_host: #Borramos ya el indicador para que no se guarde en la Videoteca
del item.channel_host
#Sólo ejecutamos este código si no se ha hecho antes en el Canal. Por ejemplo, si se ha llamado desde Episodios,
#ya no se ejecutará al Añadia a Videoteca, aunque desde el canal se podrá llamar tantas veces como se quiera,
@@ -168,10 +176,13 @@ def post_tmdb_listado(item, itemlist):
#Borramos valores si ha habido fail-over
channel_alt = ''
if item.channel_alt:
channel_alt = item.channel
channel_alt = item.channel_alt
del item.channel_alt
if item.url_alt:
del item.url_alt
#Ajustamos el nombre de la categoría
if item.category != "newest":
item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize()
for item_local in itemlist: #Recorremos el Itenlist generado por el canal
title = item_local.title
@@ -185,6 +196,10 @@ def post_tmdb_listado(item, itemlist):
if item_local.url_alt:
del item_local.url_alt
#Ajustamos el nombre de la categoría
if item_local.category != "newest":
item_local.category = scrapertools.find_single_match(item_local.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize()
#Restauramos la info adicional guarda en la lista title_subs, y la borramos de Item
title_add = ' '
if item_local.title_subs:
@@ -199,7 +214,8 @@ def post_tmdb_listado(item, itemlist):
title_add = title_add.rstrip()
title_add += '%s -%s-' % (title_add, title_subs) #se agregan el resto de etiquetas salvadas
del item_local.title_subs
item_local.title_subs = []
del item_local.title_subs
#Preparamos el Rating del vídeo
rating = ''
@@ -276,9 +292,9 @@ def post_tmdb_listado(item, itemlist):
title = re.sub(r'\s\[COLOR \w+\]\[\/COLOR\]', '', title).strip()
if item.category == "newest": #Viene de Novedades. Marcamos el título con el nombre del canal
title += ' -%s-' % item_local.channel.capitalize()
title += ' -%s-' % scrapertools.find_single_match(item_local.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize()
if item_local.contentType == "movie":
item_local.contentTitle += ' -%s-' % item_local.channel.capitalize()
item_local.contentTitle += ' -%s-' % scrapertools.find_single_match(item_local.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize()
item_local.title = title
@@ -288,8 +304,8 @@ def post_tmdb_listado(item, itemlist):
#Si ha habido fail-over, lo comento
if channel_alt:
itemlist.append(item.clone(action='', title="[COLOR yellow]" + channel_alt.capitalize() + '[/COLOR] [ALT ] en uso'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR] caído'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category + '[/COLOR] [ALT ] en uso'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + channel_alt.capitalize() + '[/COLOR] inaccesible'))
return (item, itemlist)
@@ -329,19 +345,29 @@ def post_tmdb_episodios(item, itemlist):
num_temporada_max = 99
num_episodios_flag = True
#Restauramos el num de Temporada para hacer más flexible la elección de Videoteca
#Restauramos el num de Temporada para hacer más flexible la elección de Videoteca
contentSeason = item.contentSeason
if item.contentSeason_save:
contentSeason = item.contentSeason_save
item.contentSeason = item.contentSeason_save
del item.contentSeason_save
#Ajustamos el nombre de la categoría
item.category = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize()
#Restauramos valores si ha habido fail-over
channel_alt = ''
if item.channel_alt:
channel_alt = item.channel
item.channel = item.channel_alt
del item.channel_alt
if item.channel == channel_py:
if item.channel_alt:
channel_alt = item.category
item.category = item.channel_alt.capitalize()
del item.channel_alt
else:
if item.channel_alt:
channel_alt = item.channel
item.channel = item.channel_alt
item.category = item.channel_alt.capitalize()
del item.channel_alt
if item.url_alt:
item.url = item.url_alt
del item.url_alt
@@ -351,17 +377,31 @@ def post_tmdb_episodios(item, itemlist):
del item_local.add_videolibrary
if item_local.add_menu:
del item_local.add_menu
if item_local.contentSeason_save:
del item_local.contentSeason_save
#Restauramos valores para cada Episodio si ha habido fail-over
if item_local.channel_alt:
item_local.channel = item_local.channel_alt
del item_local.channel_alt
#Ajustamos el nombre de la categoría si es un clone de NewPct1
item_local.category = scrapertools.find_single_match(item_local.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/').capitalize()
#Restauramos valores para cada Episodio si ha habido fail-over de un clone de NewPct1
if item_local.channel == channel_py:
if item_local.channel_alt:
item_local.category = item_local.channel_alt
del item_local.channel_alt
else:
if item_local.channel_alt:
item_local.channel = item_local.channel_alt
del item_local.channel_alt
if item_local.url_alt:
host_act = scrapertools.find_single_match(item_local.url, ':\/\/(.*?)\/')
host_org = scrapertools.find_single_match(item_local.url_alt, ':\/\/(.*?)\/')
item_local.url = item_local.url.replace(host_act, host_org)
del item_local.url_alt
#Si está actualizando videoteca de una serie NewPct1, restauramos el channel con el nombre del clone
if item_local.channel == channel_py and (item.library_playcounts or item.add_videolibrary):
item_local.channel = scrapertools.find_single_match(item_local.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/')
#Si el título de la serie está verificado en TMDB, se intenta descubrir los eisodios fuera de rango,
#que son probables errores de la Web
if item.tmdb_stat:
@@ -448,6 +488,10 @@ def post_tmdb_episodios(item, itemlist):
#logger.debug("title: " + item_local.title + " / url: " + item_local.url + " / calidad: " + item_local.quality + " / Season: " + str(item_local.contentSeason) + " / EpisodeNumber: " + str(item_local.contentEpisodeNumber) + " / num_episodios_lista: " + str(num_episodios_lista) + str(num_episodios_flag))
#logger.debug(item_local)
#Si está actualizando videoteca de una serie NewPct1, restauramos el channel con el nombre del clone
if item.channel == channel_py and (item.library_playcounts or item.add_videolibrary):
item.channel = scrapertools.find_single_match(item.url, 'http.?\:\/\/(?:www.)?(\w+)\.\w+\/')
#Terminado el repaso de cada episodio, cerramos con el pié de página
#En primer lugar actualizamos todos los episodios con su núm máximo de episodios por temporada
try:
@@ -512,13 +556,13 @@ def post_tmdb_episodios(item, itemlist):
#Si ha habido fail-over, lo comento
if channel_alt:
itemlist.append(item.clone(action='', title="[COLOR yellow]" + channel_alt.capitalize() + '[/COLOR] [ALT ] en uso'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.channel.capitalize() + '[/COLOR] caído'))
itemlist.append(item.clone(action='', title="[COLOR yellow]" + item.category.capitalize() + '[/COLOR] inaccesible'))
if item.add_videolibrary: #Estamos Añadiendo a la Videoteca.
del item.add_videolibrary #Borramos ya el indicador
if item.add_menu: #Opción que avisa si se ha añadido a la Videoteca
del item.add_menu #desde la página de Episodios o desde Menú Contextual
del item.add_menu #desde la página de Episodios o desde Menú Contextual
#logger.debug(item)
return (item, itemlist)
@@ -593,6 +637,10 @@ def post_tmdb_findvideos(item, itemlist):
if item.quality.lower() in ['gb', 'mb']:
item.quality = item.quality.replace('GB', 'G B').replace('Gb', 'G b').replace('MB', 'M B').replace('Mb', 'M b')
#Ajustamos el nombre de la categoría
if item.channel != channel_py:
item.category = item.channel.capitalize()
#Formateamos de forma especial el título para un episodio
if item.contentType == "episode": #Series
@@ -619,9 +667,9 @@ def post_tmdb_findvideos(item, itemlist):
title_gen = '[COLOR gold]Enlaces Ver: [/COLOR]%s' % (title_gen)
if item.channel_alt:
title_gen = '[COLOR yellow]%s [/COLOR][ALT]: %s' % (item.channel.capitalize(), title_gen)
title_gen = '[COLOR yellow]%s [/COLOR][ALT]: %s' % (item.category.capitalize(), title_gen)
elif config.get_setting("quit_channel_name", "videolibrary") == 1 and item.contentChannel == "videolibrary":
title_gen = '%s: %s' % (item.channel.capitalize(), title_gen)
title_gen = '%s: %s' % (item.category.capitalize(), title_gen)
#Pintamos el pseudo-título con toda la información disponible del vídeo
item.action = ""
@@ -633,7 +681,7 @@ def post_tmdb_findvideos(item, itemlist):
return (item, itemlist)
def fail_over_newpct1(item, patron, patron2=None):
def fail_over_newpct1(item, patron, patron2=None, timeout=None):
logger.info()
import ast
@@ -641,56 +689,74 @@ def fail_over_newpct1(item, patron, patron2=None):
Llamada para encontrar una web alternativa a un canal caído, clone de NewPct1
Creamos una liat de tuplas con los datos de los canales alternativos. Los datos de la tupla son:
Creamos una array con los datos de los canales alternativos. Los datos de la tupla son:
- active = 0,1 Indica si el canal no está activo o sí lo está
- channel nombre del canal alternativo
- channel_host host del canal alternativo, utilizado para el reemplazo de parte de la url
- contentType indica que tipo de contenido que soporta el nuevo canal en fail-overs
- info reservado para uso futuro
- action_excluded lista las acciones que está excluidas para ese canal
La llamada al método desde el principio de Submenu, Episodios y Findvideos, es:
La llamada al método desde el principio de Submenu, Listado_Búsqueda, Episodios y Findvideos, es:
from lib import generictools
item, data = generictools.fail_over_newpct1(item, patron)
- Entrada: patron: con este patron permite verificar si los datos de la nueva web son buenos
- Entrada (opcional): patron2: segundo patron opcional
- Entrada (opcional): timeout: valor de espera máximo en download de página. Por defecto 3
- Saida: data: devuelve los datos del la nueva web. Si vuelve vacía es que no se ha encontrado alternativa
"""
data = ''
#lista de tuplas con los datos de los canales alternativos
fail_over_list = config.get_setting('clonenewpct1_channels_list', "torrentrapid")
fail_over_list = ast.literal_eval(fail_over_list)
if timeout == None:
timeout = config.get_setting('clonenewpct1_timeout_downloadpage', channel_py) #Timeout downloadpage
if timeout == 0: timeout = None
#Recorremos la tupla identificando el canala que falla
for active, channel, channel_host, contentType, info in fail_over_list:
if channel != item.channel: #es el canal que falla?
continue
channel_failed = channel #salvamos el nombre del canal
data = ''
channel_failed = ''
#Array con los datos de los canales alternativos
fail_over_list = config.get_setting('clonenewpct1_channels_list', channel_py)
fail_over_list = ast.literal_eval(fail_over_list)
#Recorremos el Array identificando el canal que falla
for active, channel, channel_host, contentType, action_excluded in fail_over_list:
if item.channel == channel_py:
if channel != item.category.lower(): #es el canal/categoría que falla?
continue
else:
if channel != item.channel: #es el canal que falla?
continue
channel_failed = channel #salvamos el nombre del canal o categoría
channel_host_failed = channel_host #salvamos el nombre del host
channel_url_failed = item.url #salvamos la url
if item.action != 'submenu' and item.action != 'search' and item.contentType not in contentType: #soporta el fail_over de este contenido?
if (item.action == 'episodios' or item.action == 'findvideos') and item.contentType not in contentType: #soporta el fail_over de este contenido?
data = ''
return (item, data) #no soporta el fail_over de este contenido, no podemos hacer nada
break
if not channel_failed:
logger.debug(item)
return (item, data) #Algo no ha funcionado, no podemos hacer nada
#Recorremos la tupla identificando canales activos que funcionen, distintos del caído, que soporten el contenido
for active, channel, channel_host, contentType, info in fail_over_list:
#Recorremos el Array identificando canales activos que funcionen, distintos del caído, que soporten el contenido
for active, channel, channel_host, contentType, action_excluded in fail_over_list:
data_alt = ''
if channel == channel_failed or active == '0': #está activo el nuevo canal?
if channel == channel_failed or active == '0' or item.action in action_excluded: #es válido el nuevo canal?
continue
if item.action != 'submenu' and item.action != 'search' and item.contentType not in contentType: #soporta el contenido?
if (item.action == 'episodios' or item.action == 'findvideos') and item.contentType not in contentType: #soporta el contenido?
continue
#Hacemos el cambio de nombre de canal y url, conservando las anteriores como ALT
item.channel_alt = channel_failed
item.channel = channel
if item.channel != channel_py:
item.channel = channel
item.category = channel.capitalize()
item.url_alt = channel_url_failed
item.url = channel_url_failed
item.url = item.url.replace(channel_host_failed, channel_host)
item.channel_host = channel_host
#quitamos el código de series, porque puede variar entre webs
if item.action == "episodios" or item.action == "get_seasons":
item.url = re.sub(r'\/\d+$', '', item.url) #parece que con el título solo ecuentra la serie, normalmente...
@@ -698,9 +764,9 @@ def fail_over_newpct1(item, patron, patron2=None):
#Leemos la nueva url
try:
if item.post:
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, post=item.post, timeout=2).data)
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, post=item.post, timeout=timeout).data)
else:
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=2).data)
data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data)
except:
data = ''
if not data: #no ha habido suerte, probamos con el siguiente canal válido
@@ -710,38 +776,62 @@ def fail_over_newpct1(item, patron, patron2=None):
#Hemos logrado leer la web, validamos si encontramos un línk válido en esta estructura
#Evitar páginas engañosas que puede meter al canal en un loop infinito
if (not ".com/images/no_imagen.jpg" in data and not ".com/images/imagen-no-disponible.jpg" in data) or item.action != "episodios":
if item.action == 'submenu': #Para submenú hacemos un cambio total de canal
patron = patron.replace(item.channel_alt, item.channel) #el patron lleva el nombre de host
if patron:
data_alt = scrapertools.find_single_match(data, patron)
if patron2 != None:
data_alt = scrapertools.find_single_match(data_alt, patron2)
if not data_alt: #no ha habido suerte, probamos con el siguiente canal
logger.error("ERROR 02: " + item.action + ": Ha cambiado la estructura de la Web: " + item.url + " / Patron: " + patron)
data = ''
if item.action == 'submenu': #restauramos el patrón para el siguiente canal
patron = patron.replace(item.channel, item.channel_alt)
continue
else:
#if item.action == "episodios" or item.action == "get_seasons": #guardamos la url real de esta web
#item.url += str(scrapertools.find_single_match(data, '<ul class="buscar-list">.*?<img src=".*?\/pictures\/.*?(\/\d+)_'))
#para Submenu y Search cambiamos también la Categoria
if item.action == 'submenu' or item.action == 'search':
item.category = item.channel.capitalize()
break #por fin !!! Este canal parece que funciona
else:
logger.error("ERROR 02: " + item.action + ": Ha cambiado la estructura de la Web: " + item.url + " / Patron: " + patron)
data = ''
continue
#logger.debug(item)
if not data: #Si no ha logrado encontrar nada, salimos limpiando variables
if item.channel_alt:
item.channel = item.channel_alt
del item.channel_alt
if item.channel == channel_py:
if item.channel_alt:
item.category = item.channel_alt.capitalize()
del item.channel_alt
else:
if item.channel_alt:
item.channel = item.channel_alt
del item.channel_alt
if item.url_alt:
item.url = item.url_alt
del item.url_alt
if item.channel_host:
del item.channel_host
return (item, data)
return (item, data)
def redirect_clone_newpct1(item):
logger.info()
"""
Llamada para redirigir cualquier llamada a un clone de NewPct1 a NewPct1.py
Incluye las llamadas estándar del canal y la llamadas externas:
- Play fron Library
- Videolibrary Update
La lógica es reemplazar item.channel por "newpct1" y dejar el nombre del clone en item.category.
De esta forma utiliza siempre el código de NewPct1.py, aunque con las urls y apariencia del clone seleccionado por el usuario.
Este método interroga la configruación de NewPct1 para extraer la lista de canales clones. Si item.channel es un clone de NewPct1 y está en esa lista, actualiza item.channel='newpct1'
La llamada recibe el parámetro Item y lo devuleve actualizado
"""
#Array con los datos de los canales alternativos
fail_over_list = config.get_setting('clonenewpct1_channels_list', channel_py)
channel = "'%s'" % item.channel
if channel in fail_over_list:
item.channel = channel_py
return item

View File

@@ -1,145 +1,164 @@
# -*- coding: utf-8 -*-
'''
gktools son un conjunto de funciones para ayudar a resolver enlaces a videos con "protección GK".
Lo de protección gk dudo que exista, le he llamado así pq los primeros ejemplos vistos se eran gkpluginsphp y gkpedia.
Características "GK" :
- Utiliza una cookie __cfduid
- Utiliza meta name="google-site-verification" como texto a encriptar
- La clave para encriptar se calcula en los js
- Se calcula un token criptográfico en función del texto y clave
- Calcula un token criptográfico en función de un texto y una clave
- El texto se saca del html (por ejemplo de meta name="google-site-verification", pero puede ser más complejo)
- La clave para encriptar se calcula en js ofuscados que carga el html
- Se llama a otra url con una serie de parámetros, como el token, y de allí se obtienen los videos finales.
A partir de aquí 2 opciones:
Howto:
1- descargar página
2- extraer datos y calcular los necesarios
3- descargar segunda página con el token calculado
4- extraer videos
a) Si la url indica que hay un /embed/
- se cambia /embed/ por /stream/ y se añade /token
- se descarga la página, dónde se pueden extraer los videos
b) Sino (enlaces directos)
- se busca un identificador
- si hay una llamada a Play() en el js, el id se saca de allí
- sino el id puede estar en la url
- con el identificador y el token se llama a un php (gkpluginsphp, gkpedia)
- el php devuelve la lista de enlaces a los videos
El paso 2 es con diferencia el más variable y depende mucho de cada web/servidor!
Desofuscando los js se pueden ver los datos propios que necesita cada uno
(el texto a encriptar, la clave a usar, la url dónde hay que llamar y los parámetros)
Notas:
- Creado a partir de lo visto en pelispedia y animeyt, que utilizan este sistema.
- Para otros canales habrá que añadir sus datos en las funciones calcular_*
o hacer que estas funciones puedan extraer lo necesario de los js.
Ver ejemplos en el código de los canales animeyt y pelispedia
Created for Alfa-addon by Alfa Developers Team 2018
'''
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
import urlparse
import os, base64, json, hashlib, urlparse
from core import httptools
from core import scrapertools
# ~ from platformcode import logger
from platformcode import logger
from aadecode import decode as aadecode
def gk_play(item):
# Descarga página y captura la petición de cookie
# -----------------------------------------------
def get_data_and_cookie(item, ck_name='__cfduid'):
itemlist = []
# Descargar para tratar header y data por separado
# ------------------------------------------------
headers = {'Referer': item.referer}
resp = httptools.downloadpage(item.url, headers=headers, cookies=False)
# ~ with open('gk_play1.html', 'w') as f: f.write(resp.data); f.close()
# Obtener cookie __cfduid
# -----------------------
for h in resp.headers:
ck = scrapertools.find_single_match(resp.headers[h], '__cfduid=([^;]*)')
if ck:
break
if not ck: return itemlist
ck_value = ''
if ck_name != '':
for h in resp.headers:
ck = scrapertools.find_single_match(resp.headers[h], '%s=([^;]*)' % ck_name)
if ck:
ck_value = ck
break
# Extraer datos y calcular token
# ------------------------------
gsv = scrapertools.find_single_match(resp.data, '<meta name="google-site-verification" content="([^"]*)"')
if not gsv: return itemlist
suto = calcular_sutorimux(item.url) # valor que se calcula en función del dominio
sufijo = calcular_sufijo(item.url) # valor predeterminado que se establece en el código js
token = generar_token(gsv, suto+'yt'+suto+sufijo)
return resp.data, ck_value
# Descargar y extraer videos
# --------------------------
# Descarga página usando una cookie concreta
# ------------------------------------------
def get_data_with_cookie(url, ck_value='', referer='', ck_name='__cfduid'):
if '/embed/' in item.url:
url = item.url.replace('/embed/', '/stream/') + '/' + token
headers = {'Referer': item.url, 'Cookie': '__cfduid=' + ck}
data = httptools.downloadpage(url, headers=headers, cookies=False).data
# ~ with open('gk_play2.html', 'w') as f: f.write(resp.data); f.close()
# Extraer enlaces de la respuesta
# -------------------------------
url = scrapertools.find_single_match(data, '<meta (?:name|property)="og:url" content="([^"]+)"')
srv = scrapertools.find_single_match(data, '<meta (?:name|property)="og:sitename" content="([^"]+)"')
if srv == '' and 'rapidvideo.com/' in url: srv = 'rapidvideo'
headers = {'Cookie': ck_name+'='+ck_value}
if referer != '': headers['referer'] = referer
data = httptools.downloadpage(url, headers=headers, cookies=False).data
# ~ with open('gk_play2.html', 'w') as f: f.write(data); f.close()
if url != '' and srv != '':
itemlist.append(item.clone(url=url, server=srv.lower()))
elif '<title>Vidoza</title>' in data or '|fastplay|' in data:
if '|fastplay|' in data:
packed = scrapertools.find_single_match(data, "<script type='text/javascript'>(eval\(.*?)</script>")
from lib import jsunpack
data = jsunpack.unpack(packed)
data = data.replace("\\'", "'")
matches = scrapertools.find_multiple_matches(data, 'file\s*:\s*"([^"]+)"\s*,\s*label\s*:\s*"([^"]+)"')
subtitle = ''
for fil, lbl in matches:
if fil.endswith('.srt') and not fil.endswith('empty.srt'):
subtitle = fil
if not subtitle.startswith('http'):
domi = scrapertools.find_single_match(data, 'aboutlink\s*:\s*"([^"]*)')
subtitle = domi + subtitle
break
for fil, lbl in matches:
if not fil.endswith('.srt'):
itemlist.append([lbl, fil, 0, subtitle])
return data
# Descarga json usando una cookie concreta
# ----------------------------------------
def get_data_json(url, post, ck_value='', referer='', ck_name='__cfduid'):
headers = {'Content-Type': 'application/x-www-form-urlencoded', 'Cookie': ck_name+'='+ck_value}
if referer != '': headers['referer'] = referer
data = httptools.downloadpage(url, post=post, headers=headers, cookies=False).data
# ~ with open('gk_play3.html', 'w') as f: f.write(data); f.close()
return data
# Obtiene link de una llamada javascript Play() o de la url
# ---------------------------------------------------------
def get_play_link_id(data, url):
playparms = scrapertools.find_single_match(data, 'Play\("([^"]*)","([^"]*)","([^"]*)"')
if playparms:
link = playparms[0]
subtitle = '' if playparms[1] == '' or playparms[2] == '' else playparms[2] + playparms[1] + '.srt'
else:
playparms = scrapertools.find_single_match(resp.data, 'Play\("([^"]*)","([^"]*)","([^"]*)"')
if playparms:
link = playparms[0]
subtitle = '' if playparms[1] == '' or playparms[2] == '' else playparms[2] + playparms[1] + '.srt'
subtitle = ''
link = scrapertools.find_single_match(data, 'Play\("([^"]*)"')
if not link:
link = scrapertools.find_single_match(url, 'id=([^;]*)')
return link, subtitle
# Extraer enlaces a videos de datos json
# --------------------------------------
def extraer_enlaces_json(data, referer, subtitle=''):
itemlist = []
# Ejemplos:
# {"Animeyt":[{"file":"https:\/\/storage.googleapis.com\/my-project-yt-195318.appspot.com\/slow.mp4","type":"mp4","label":"1080p"}]}
# {"link":[{"link":"http:\/\/video8.narusaku.tv\/static\/720p\/2.1208982.2039540?md5=B64FKYNbFuWvxkGcSbtz2Q&expires=1528839657","label":"720p","type":"mp4"},{"link":"http:\/\/video5.narusaku.tv\/static\/480p\/2.1208982.2039540?md5=yhLG_3VghEUSd5YlCXOTBQ&expires=1528839657","label":"480p","type":"mp4","default":true},{"link":"http:\/\/video3.narusaku.tv\/static\/360p\/2.1208982.2039540?md5=vC0ZJkxRwV1rVBdeF7D4iA&expires=1528839657","label":"360p","type":"mp4"},{"link":"http:\/\/video2.narusaku.tv\/static\/240p\/2.1208982.2039540?md5=b-y_-rgrLMW7hJwFQSD8Tw&expires=1528839657","label":"240p","type":"mp4"}]}
# {"link":"https:\/\/storage.googleapis.com\/cloudflare-caching-pelispedia.appspot.com\/cache\/16050.mp4","type":"mp4"}
# {"Harbinger":[{"Harbinger":"...","type":"...","label":"..."}], ...}
data = data.replace('"Harbinger"', '"file"')
# Intentar como json
# ------------------
try:
json_data = json.loads(data)
enlaces = analizar_enlaces_json(json_data)
for enlace in enlaces:
url = enlace['link'] if 'link' in enlace else enlace['file']
if not url.startswith('http'): url = aadecode(base64.b64decode(url)) # necesario para "Harbinger"
if not url.startswith('http'): url = decode_rijndael(url) # post-"Harbinger" en algunos casos
tit = ''
if 'type' in enlace: tit += '[%s]' % enlace['type']
if 'label' in enlace: tit += '[%s]' % enlace['label']
if tit == '': tit = '.mp4'
itemlist.append([tit, corregir_url(url, referer), 0, subtitle])
# Sino, intentar como texto
# -------------------------
except:
matches = scrapertools.find_multiple_matches(data, '"link"\s*:\s*"([^"]*)"\s*,\s*"label"\s*:\s*"([^"]*)"\s*,\s*"type"\s*:\s*"([^"]*)"')
if matches:
for url, lbl, typ in matches:
itemlist.append(['[%s][%s]' % (typ, lbl), corregir_url(url, referer), 0, subtitle])
else:
subtitle = ''
link = scrapertools.find_single_match(resp.data, 'Play\("([^"]*)"')
if not link:
link = scrapertools.find_single_match(item.url, 'id=([^;]*)')
if link:
# ~ logger.info('%s %s %s' % (item.url, link, token))
url_gk = calcular_url_gk(item.url)
post = "link=%s&token=%s" % (link, token)
headers = {'Content-Type': 'application/x-www-form-urlencoded', 'Cookie': '__cfduid=' + ck}
data = httptools.downloadpage(url_gk, post=post, headers=headers, cookies=False).data
# ~ with open('gk_play3.html', 'w') as f: f.write(resp.data); f.close()
# Extraer enlaces de la respuesta
# -------------------------------
matches = scrapertools.find_multiple_matches(data, '"link"\s*:\s*"([^"]*)"\s*,\s*"label"\s*:\s*"([^"]*)"\s*,\s*"type"\s*:\s*"([^"]*)"')
if matches:
for url, lbl, typ in matches:
itemlist.append(['[%s][%s]' % (typ, lbl), corregir_url(url, item.referer), 0, subtitle])
else:
url = scrapertools.find_single_match(data, '"link"\s*:\s*"([^"]*)"')
if url:
itemlist.append(['.mp4', corregir_url(url, item.referer), 0, subtitle])
url = scrapertools.find_single_match(data, '"link"\s*:\s*"([^"]*)"')
if url:
itemlist.append(['.mp4', corregir_url(url, referer), 0, subtitle])
return itemlist
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Función recursiva que busca videos en un diccionario
# ----------------------------------------------------
def analizar_enlaces_json(d):
itemlist = []
found = {}
for k, v in d.iteritems():
if k in ['file','link','type','label'] and not isinstance(v, list):
found[k] = v
if isinstance(v, list):
for l in v:
if isinstance(l, dict): itemlist += analizar_enlaces_json(l)
if 'file' in found or 'link' in found:
itemlist.append(found)
return itemlist
# Correcciones en las urls finales obtenidas
# ------------------------------------------
@@ -149,6 +168,66 @@ def corregir_url(url, referer):
return url
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Conversion tipo hexa que hay en el js
# -------------------------------------
def toHex(txt):
ret = ''
for i in range(len(txt)):
ret += str(hex(ord(txt[i]))).replace('x','')[-2:]
return ret
# Subrutinas de encriptación
# --------------------------
def md5_dominio(url): # sutorimux/kubechi
h = hashlib.md5(urlparse.urlparse(url).netloc)
return h.hexdigest()
def transforma_gsv(gsv, valor):
llista = range(256)
a = 0
for i in range(256):
a = (a + llista[i] + ord(gsv[i % len(gsv)]) ) % 256
b = llista[i]
llista[i] = llista[a]
llista[a] = b
ret = ''
a = 0; b= 0
for i in range(len(valor)):
a = (a + 1) % 256
b = (b + llista[a]) % 256
c = llista[a]
llista[a] = llista[b]
llista[b] = c
ret += chr(ord(valor[i]) ^ llista[(llista[a] + llista[b]) % 256])
return base64.b64encode(ret)
# Codificar/Decodificar con Rijndael
# ----------------------------------
def encode_rijndael(msg, IV, key):
import rijndael
return rijndael.cbc_encrypt(msg, IV, key)
def decode_rijndael(txt, preIV='b3512f4972d314da9', key='3e1a854e7d5835ab99d99a29afec8bbb'):
import rijndael
msg = base64.b64decode(txt[:-15])
IV = preIV + txt[-15:]
deco = rijndael.cbc_decrypt(msg, IV, key)
return deco.replace(chr(0), '')
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -159,6 +238,7 @@ def corregir_url(url, referer):
# pwd: Password
def generar_token(gsv, pwd):
txt = obtener_cripto(pwd, gsv)
# ~ logger.info('Texto pre token %s' % txt)
_0x382d28 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
@@ -182,18 +262,17 @@ def generar_token(gsv, pwd):
def obtener_cripto(password, plaintext):
import os, base64, json
SALT_LENGTH = 8
BLOCK_SIZE = 16
KEY_SIZE = 32
salt = os.urandom(SALT_LENGTH)
iv = os.urandom(BLOCK_SIZE)
paddingLength = 16 - (len(plaintext) % 16)
paddedPlaintext = plaintext+chr(paddingLength)*paddingLength
salt = os.urandom(8)
paddingLength = len(plaintext) % 16
if paddingLength == 0:
paddedPlaintext = plaintext
else:
dif = 16 - paddingLength
paddedPlaintext = plaintext + chr(dif)*dif
kdf = evpKDF(password, salt)
iv = kdf['iv']
try: # Intentar con librería AES del sistema
from Crypto.Cipher import AES
@@ -207,7 +286,6 @@ def obtener_cripto(password, plaintext):
def evpKDF(passwd, salt, key_size=8, iv_size=4, iterations=1, hash_algorithm="md5"):
import hashlib
target_key_size = key_size + iv_size
derived_bytes = ""
number_of_derived_words = 0
@@ -235,63 +313,3 @@ def evpKDF(passwd, salt, key_size=8, iv_size=4, iterations=1, hash_algorithm="md
"key": derived_bytes[0: key_size * 4],
"iv": derived_bytes[key_size * 4:]
}
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Valores extraídos de los js para los dominios tratados (pendiente automatizar!)
# Ej: https://pelispedia.video/plugins/gkpluginsphp.js?v=3.3
# Ej: https://s2.animeyt.tv/rakuten/plugins/rakuten676.js?v=200000000
def calcular_sutorimux(url):
dominio = urlparse.urlparse(url).netloc
claves = {
'pelispedia.video': 'b0a8c83650f18ccc7c87b16e3c460474',
'load.pelispedia.vip': '4fe554b59d760c9986c903b07af8b7a4',
's1.animeyt.tv': '0cdf0d0302091bc22a0afdc3f13c0773',
's2.animeyt.tv': '079c3ee3ca289af95d819d93b852ed94',
's3.animeyt.tv': '6c21a435bce9f5926d26db567fee1241',
's4.animeyt.tv': '38546fb4797f2f7c5b6690a5b4a47e34',
's10.animeyt.tv': 'be88e4cc014c0ae6f9f2d1f947b3b23b',
's.animeyt.tv': '49f911abffe682820dc5b54777713974',
'server.animeyt.tv': '2c60637d7f7aa54225c20aea61a2b468',
'api.animeyt.tv': '54092dea9fd2e163aaa59ad0c4351866',
}
return '' if dominio not in claves else claves[dominio]
def calcular_sufijo(url):
dominio = urlparse.urlparse(url).netloc
claves = {
'pelispedia.video': '2653',
'load.pelispedia.vip': '785446346',
's1.animeyt.tv': '',
's2.animeyt.tv': '3497510',
's3.animeyt.tv': '',
's4.animeyt.tv': '',
's10.animeyt.tv': '',
's.animeyt.tv': '',
'server.animeyt.tv': '',
'api.animeyt.tv': '',
}
return '' if dominio not in claves else claves[dominio]
def calcular_url_gk(url):
dominio = urlparse.urlparse(url).netloc
claves = {
'pelispedia.video': 'https://pelispedia.video/plugins/cloupedia.php', # plugins/gkpedia.php
'load.pelispedia.vip': '',
's1.animeyt.tv': '',
's2.animeyt.tv': 'https://s2.animeyt.tv/rakuten/plugins/gkpluginsphp.php',
's3.animeyt.tv': '',
's4.animeyt.tv': '',
's10.animeyt.tv': '',
's.animeyt.tv': '',
'server.animeyt.tv': '',
'api.animeyt.tv': '',
}
return '' if dominio not in claves else claves[dominio]

View File

@@ -0,0 +1,23 @@
from rijndael import rijndael
from rijndael_cbc import zeropad, cbc
import base64
def cbc_encrypt(msg, IV, key, size=32):
r = rijndael(key, size)
pad = zeropad(size)
cri = cbc(pad, r, IV)
encod = cri.encrypt(msg)
return encod #.encode('hex')
def cbc_decrypt(msg, IV, key, size=32):
r = rijndael(key, size)
pad = zeropad(size)
cri = cbc(pad, r, IV)
return cri.decrypt(msg)

View File

@@ -0,0 +1,361 @@
"""
A pure python (slow) implementation of rijndael with a decent interface
To include -
from rijndael import rijndael
To do a key setup -
r = rijndael(key, block_size = 16)
key must be a string of length 16, 24, or 32
blocksize must be 16, 24, or 32. Default is 16
To use -
ciphertext = r.encrypt(plaintext)
plaintext = r.decrypt(ciphertext)
If any strings are of the wrong length a ValueError is thrown
"""
# ported from the Java reference code by Bram Cohen, April 2001
# this code is public domain, unless someone makes
# an intellectual property claim against the reference
# code, in which case it can be made public domain by
# deleting all the comments and renaming all the variables
import copy
import string
shifts = [[[0, 0], [1, 3], [2, 2], [3, 1]],
[[0, 0], [1, 5], [2, 4], [3, 3]],
[[0, 0], [1, 7], [3, 5], [4, 4]]]
# [keysize][block_size]
num_rounds = {16: {16: 10, 24: 12, 32: 14}, 24: {16: 12, 24: 12, 32: 14}, 32: {16: 14, 24: 14, 32: 14}}
A = [[1, 1, 1, 1, 1, 0, 0, 0],
[0, 1, 1, 1, 1, 1, 0, 0],
[0, 0, 1, 1, 1, 1, 1, 0],
[0, 0, 0, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 1, 1, 1, 1],
[1, 1, 0, 0, 0, 1, 1, 1],
[1, 1, 1, 0, 0, 0, 1, 1],
[1, 1, 1, 1, 0, 0, 0, 1]]
# produce log and alog tables, needed for multiplying in the
# field GF(2^m) (generator = 3)
alog = [1]
for i in range(255):
j = (alog[-1] << 1) ^ alog[-1]
if j & 0x100 != 0:
j ^= 0x11B
alog.append(j)
log = [0] * 256
for i in range(1, 255):
log[alog[i]] = i
# multiply two elements of GF(2^m)
def mul(a, b):
if a == 0 or b == 0:
return 0
return alog[(log[a & 0xFF] + log[b & 0xFF]) % 255]
# substitution box based on F^{-1}(x)
box = [[0] * 8 for i in range(256)]
box[1][7] = 1
for i in range(2, 256):
j = alog[255 - log[i]]
for t in range(8):
box[i][t] = (j >> (7 - t)) & 0x01
B = [0, 1, 1, 0, 0, 0, 1, 1]
# affine transform: box[i] <- B + A*box[i]
cox = [[0] * 8 for i in range(256)]
for i in range(256):
for t in range(8):
cox[i][t] = B[t]
for j in range(8):
cox[i][t] ^= A[t][j] * box[i][j]
# S-boxes and inverse S-boxes
S = [0] * 256
Si = [0] * 256
for i in range(256):
S[i] = cox[i][0] << 7
for t in range(1, 8):
S[i] ^= cox[i][t] << (7-t)
Si[S[i] & 0xFF] = i
# T-boxes
G = [[2, 1, 1, 3],
[3, 2, 1, 1],
[1, 3, 2, 1],
[1, 1, 3, 2]]
AA = [[0] * 8 for i in range(4)]
for i in range(4):
for j in range(4):
AA[i][j] = G[i][j]
AA[i][i+4] = 1
for i in range(4):
pivot = AA[i][i]
if pivot == 0:
t = i + 1
while AA[t][i] == 0 and t < 4:
t += 1
assert t != 4, 'G matrix must be invertible'
for j in range(8):
AA[i][j], AA[t][j] = AA[t][j], AA[i][j]
pivot = AA[i][i]
for j in range(8):
if AA[i][j] != 0:
AA[i][j] = alog[(255 + log[AA[i][j] & 0xFF] - log[pivot & 0xFF]) % 255]
for t in range(4):
if i != t:
for j in range(i+1, 8):
AA[t][j] ^= mul(AA[i][j], AA[t][i])
AA[t][i] = 0
iG = [[0] * 4 for i in range(4)]
for i in range(4):
for j in range(4):
iG[i][j] = AA[i][j + 4]
def mul4(a, bs):
if a == 0:
return 0
r = 0
for b in bs:
r <<= 8
if b != 0:
r = r | mul(a, b)
return r
T1 = []
T2 = []
T3 = []
T4 = []
T5 = []
T6 = []
T7 = []
T8 = []
U1 = []
U2 = []
U3 = []
U4 = []
for t in range(256):
s = S[t]
T1.append(mul4(s, G[0]))
T2.append(mul4(s, G[1]))
T3.append(mul4(s, G[2]))
T4.append(mul4(s, G[3]))
s = Si[t]
T5.append(mul4(s, iG[0]))
T6.append(mul4(s, iG[1]))
T7.append(mul4(s, iG[2]))
T8.append(mul4(s, iG[3]))
U1.append(mul4(t, iG[0]))
U2.append(mul4(t, iG[1]))
U3.append(mul4(t, iG[2]))
U4.append(mul4(t, iG[3]))
# round constants
rcon = [1]
r = 1
for t in range(1, 30):
r = mul(2, r)
rcon.append(r)
del A
del AA
del pivot
del B
del G
del box
del log
del alog
del i
del j
del r
del s
del t
del mul
del mul4
del cox
del iG
class rijndael:
def __init__(self, key, block_size = 16):
if block_size != 16 and block_size != 24 and block_size != 32:
raise ValueError('Invalid block size: ' + str(block_size))
if len(key) != 16 and len(key) != 24 and len(key) != 32:
raise ValueError('Invalid key size: ' + str(len(key)))
self.block_size = block_size
ROUNDS = num_rounds[len(key)][block_size]
BC = block_size // 4
# encryption round keys
Ke = [[0] * BC for i in range(ROUNDS + 1)]
# decryption round keys
Kd = [[0] * BC for i in range(ROUNDS + 1)]
ROUND_KEY_COUNT = (ROUNDS + 1) * BC
KC = len(key) // 4
# copy user material bytes into temporary ints
tk = []
for i in range(0, KC):
tk.append((ord(key[i * 4]) << 24) | (ord(key[i * 4 + 1]) << 16) |
(ord(key[i * 4 + 2]) << 8) | ord(key[i * 4 + 3]))
# copy values into round key arrays
t = 0
j = 0
while j < KC and t < ROUND_KEY_COUNT:
Ke[t // BC][t % BC] = tk[j]
Kd[ROUNDS - (t // BC)][t % BC] = tk[j]
j += 1
t += 1
tt = 0
rconpointer = 0
while t < ROUND_KEY_COUNT:
# extrapolate using phi (the round key evolution function)
tt = tk[KC - 1]
tk[0] ^= (S[(tt >> 16) & 0xFF] & 0xFF) << 24 ^ \
(S[(tt >> 8) & 0xFF] & 0xFF) << 16 ^ \
(S[ tt & 0xFF] & 0xFF) << 8 ^ \
(S[(tt >> 24) & 0xFF] & 0xFF) ^ \
(rcon[rconpointer] & 0xFF) << 24
rconpointer += 1
if KC != 8:
for i in range(1, KC):
tk[i] ^= tk[i-1]
else:
for i in range(1, KC // 2):
tk[i] ^= tk[i-1]
tt = tk[KC // 2 - 1]
tk[KC // 2] ^= (S[ tt & 0xFF] & 0xFF) ^ \
(S[(tt >> 8) & 0xFF] & 0xFF) << 8 ^ \
(S[(tt >> 16) & 0xFF] & 0xFF) << 16 ^ \
(S[(tt >> 24) & 0xFF] & 0xFF) << 24
for i in range(KC // 2 + 1, KC):
tk[i] ^= tk[i-1]
# copy values into round key arrays
j = 0
while j < KC and t < ROUND_KEY_COUNT:
Ke[t // BC][t % BC] = tk[j]
Kd[ROUNDS - (t // BC)][t % BC] = tk[j]
j += 1
t += 1
# inverse MixColumn where needed
for r in range(1, ROUNDS):
for j in range(BC):
tt = Kd[r][j]
Kd[r][j] = U1[(tt >> 24) & 0xFF] ^ \
U2[(tt >> 16) & 0xFF] ^ \
U3[(tt >> 8) & 0xFF] ^ \
U4[ tt & 0xFF]
self.Ke = Ke
self.Kd = Kd
def encrypt(self, plaintext):
if len(plaintext) != self.block_size:
raise ValueError('wrong block length, expected ' + str(self.block_size) + ' got ' + str(len(plaintext)))
Ke = self.Ke
BC = self.block_size // 4
ROUNDS = len(Ke) - 1
if BC == 4:
SC = 0
elif BC == 6:
SC = 1
else:
SC = 2
s1 = shifts[SC][1][0]
s2 = shifts[SC][2][0]
s3 = shifts[SC][3][0]
a = [0] * BC
# temporary work array
t = []
# plaintext to ints + key
for i in range(BC):
t.append((ord(plaintext[i * 4 ]) << 24 |
ord(plaintext[i * 4 + 1]) << 16 |
ord(plaintext[i * 4 + 2]) << 8 |
ord(plaintext[i * 4 + 3]) ) ^ Ke[0][i])
# apply round transforms
for r in range(1, ROUNDS):
for i in range(BC):
a[i] = (T1[(t[ i ] >> 24) & 0xFF] ^
T2[(t[(i + s1) % BC] >> 16) & 0xFF] ^
T3[(t[(i + s2) % BC] >> 8) & 0xFF] ^
T4[ t[(i + s3) % BC] & 0xFF] ) ^ Ke[r][i]
t = copy.copy(a)
# last round is special
result = []
for i in range(BC):
tt = Ke[ROUNDS][i]
result.append((S[(t[ i ] >> 24) & 0xFF] ^ (tt >> 24)) & 0xFF)
result.append((S[(t[(i + s1) % BC] >> 16) & 0xFF] ^ (tt >> 16)) & 0xFF)
result.append((S[(t[(i + s2) % BC] >> 8) & 0xFF] ^ (tt >> 8)) & 0xFF)
result.append((S[ t[(i + s3) % BC] & 0xFF] ^ tt ) & 0xFF)
return ''.join(map(chr, result))
def decrypt(self, ciphertext):
if len(ciphertext) != self.block_size:
raise ValueError('wrong block length, expected ' + str(self.block_size) + ' got ' + str(len(ciphertext)))
Kd = self.Kd
BC = self.block_size // 4
ROUNDS = len(Kd) - 1
if BC == 4:
SC = 0
elif BC == 6:
SC = 1
else:
SC = 2
s1 = shifts[SC][1][1]
s2 = shifts[SC][2][1]
s3 = shifts[SC][3][1]
a = [0] * BC
# temporary work array
t = [0] * BC
# ciphertext to ints + key
for i in range(BC):
t[i] = (ord(ciphertext[i * 4 ]) << 24 |
ord(ciphertext[i * 4 + 1]) << 16 |
ord(ciphertext[i * 4 + 2]) << 8 |
ord(ciphertext[i * 4 + 3]) ) ^ Kd[0][i]
# apply round transforms
for r in range(1, ROUNDS):
for i in range(BC):
a[i] = (T5[(t[ i ] >> 24) & 0xFF] ^
T6[(t[(i + s1) % BC] >> 16) & 0xFF] ^
T7[(t[(i + s2) % BC] >> 8) & 0xFF] ^
T8[ t[(i + s3) % BC] & 0xFF] ) ^ Kd[r][i]
t = copy.copy(a)
# last round is special
result = []
for i in range(BC):
tt = Kd[ROUNDS][i]
result.append((Si[(t[ i ] >> 24) & 0xFF] ^ (tt >> 24)) & 0xFF)
result.append((Si[(t[(i + s1) % BC] >> 16) & 0xFF] ^ (tt >> 16)) & 0xFF)
result.append((Si[(t[(i + s2) % BC] >> 8) & 0xFF] ^ (tt >> 8)) & 0xFF)
result.append((Si[ t[(i + s3) % BC] & 0xFF] ^ tt ) & 0xFF)
return ''.join(map(chr, result))
def encrypt(key, block):
return rijndael(key, len(block)).encrypt(block)
def decrypt(key, block):
return rijndael(key, len(block)).decrypt(block)

View File

@@ -0,0 +1,71 @@
# https://stackoverflow.com/questions/8356689/python-equivalent-of-phps-mcrypt-rijndael-256-cbc
class zeropad:
def __init__(self, block_size):
assert block_size > 0 and block_size < 256
self.block_size = block_size
def pad(self, pt):
ptlen = len(pt)
padsize = self.block_size - ((ptlen + self.block_size - 1) % self.block_size + 1)
return pt + "\0" * padsize
def unpad(self, ppt):
assert len(ppt) % self.block_size == 0
offset = len(ppt)
if (offset == 0):
return ''
end = offset - self.block_size + 1
while (offset > end):
offset -= 1;
if (ppt[offset] != "\0"):
return ppt[:offset + 1]
assert false
class cbc:
def __init__(self, padding, cipher, iv):
assert padding.block_size == cipher.block_size;
assert len(iv) == cipher.block_size;
self.padding = padding
self.cipher = cipher
self.iv = iv
def encrypt(self, pt):
ppt = self.padding.pad(pt)
offset = 0
ct = ''
v = self.iv
while (offset < len(ppt)):
block = ppt[offset:offset + self.cipher.block_size]
block = self.xorblock(block, v)
block = self.cipher.encrypt(block)
ct += block
offset += self.cipher.block_size
v = block
return ct;
def decrypt(self, ct):
assert len(ct) % self.cipher.block_size == 0
ppt = ''
offset = 0
v = self.iv
while (offset < len(ct)):
block = ct[offset:offset + self.cipher.block_size]
decrypted = self.cipher.decrypt(block)
ppt += self.xorblock(decrypted, v)
offset += self.cipher.block_size
v = block
pt = self.padding.unpad(ppt)
return pt;
def xorblock(self, b1, b2):
# sorry, not very Pythonesk
i = 0
r = '';
while (i < self.cipher.block_size):
r += chr(ord(b1[i]) ^ ord(b2[i]))
i += 1
return r

View File

@@ -15,6 +15,27 @@ __settings__ = xbmcaddon.Addon(id="plugin.video." + PLUGIN_NAME)
__language__ = __settings__.getLocalizedString
def get_addon_version(linea_inicio=0, total_lineas=2):
'''
Devuelve el número de de versión del addon, obtenido desde el archivo addon.xml
'''
path = os.path.join(get_runtime_path(), "addon.xml")
f = open(path, "rb")
data = []
for x, line in enumerate(f):
if x < linea_inicio: continue
if len(data) == total_lineas: break
data.append(line)
f.close()
data1 = "".join(data)
# <addon id="plugin.video.alfa" name="Alfa" version="2.5.21" provider-name="Alfa Addon">
aux = re.findall('<addon id="plugin.video.alfa" name="Alfa" version="([^"]+)"', data1, re.MULTILINE | re.DOTALL)
version = "???"
if len(aux) > 0:
version = aux[0]
return version
def get_platform(full_version=False):
"""
Devuelve la información la version de xbmc o kodi sobre el que se ejecuta el plugin
@@ -113,13 +134,13 @@ def open_settings():
if settings_post['adult_aux_new_password1'] == settings_post['adult_aux_new_password2']:
set_setting('adult_password', settings_post['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")
platformtools.dialog_ok(config.get_localized_string(60305),
config.get_localized_string(60306),
config.get_localized_string(60307))
else:
platformtools.dialog_ok("Canales para adultos", "La contraseña no es correcta.",
"Los cambios realizados en esta sección no se guardaran.")
platformtools.dialog_ok(config.get_localized_string(60305), config.get_localized_string(60309),
config.get_localized_string(60310))
# Deshacer cambios
set_setting("adult_mode", settings_pre.get("adult_mode", 0))

View File

@@ -101,7 +101,7 @@ def run(item=None):
elif item.action == "script":
from core import tmdb
if tmdb.drop_bd():
platformtools.dialog_notification("Alfa", "caché eliminada", time=2000, sound=False)
platformtools.dialog_notification(config.get_localized_string(20000), config.get_localized_string(60011), time=2000, sound=False)
# Action in certain channel specified in "action" and "channel" parameters
else:
@@ -113,7 +113,7 @@ def run(item=None):
# Parental control
# If it is an adult channel, and user has configured pin, asks for it
if channeltools.is_adult(item.channel) and config.get_setting("adult_request_password"):
tecleado = platformtools.dialog_input("", "Contraseña para canales de adultos", True)
tecleado = platformtools.dialog_input("", config.get_localized_string(60334), True)
if tecleado is None or tecleado != config.get_setting("adult_password"):
return
@@ -168,7 +168,7 @@ def run(item=None):
# If not, shows user an error message
else:
platformtools.dialog_ok("alfa", "No hay nada para reproducir")
platformtools.dialog_ok(config.get_localized_string(20000), config.get_localized_string(60339))
# If player don't have a "play" function, not uses the standard play from platformtools
else:
@@ -280,10 +280,8 @@ def run(item=None):
canal = scrapertools.find_single_match(traceback.format_exc(), patron)
platformtools.dialog_ok(
"Error en el canal " + canal,
"La web de la que depende parece no estar disponible, puede volver a intentarlo, "
"si el problema persiste verifique mediante un navegador la web: %s. "
"Si la web funciona correctamente informe el error en: www.alfa-addon.com" %(e))
config.get_localized_string(70093) + canal,
config.get_localized_string(60013) %(e))
except:
import traceback
logger.error(traceback.format_exc())
@@ -298,20 +296,17 @@ def run(item=None):
log_name = "xbmc.log"
else:
log_name = "kodi.log"
log_message = "Ruta: " + xbmc.translatePath("special://logpath") + log_name
log_message = config.get_localized_string(50004) + xbmc.translatePath("special://logpath") + log_name
except:
log_message = ""
if canal:
platformtools.dialog_ok(
"Error inesperado en el canal " + canal,
"Puede deberse a un fallo de conexión, la web del canal "
"ha cambiado su estructura, o un error interno de alfa.",
"Para saber más detalles, consulta el log.", log_message)
config.get_localized_string(70093) + canal,
config.get_localized_string(60014), log_message)
else:
platformtools.dialog_ok(
"Se ha producido un error en alfa",
"Comprueba el log para ver mas detalles del error.",
config.get_localized_string(59984),
log_message)
@@ -327,8 +322,8 @@ def reorder_itemlist(itemlist):
modified = 0
not_modified = 0
to_change = [['Ver en', '[V]'],
['Descargar en', '[D]']]
to_change = [[config.get_localized_string(60335), '[V]'],
[config.get_localized_string(60336), '[D]']]
for item in itemlist:
old_title = unicode(item.title, "utf8").lower().encode("utf8")
@@ -415,7 +410,7 @@ def play_from_library(item):
else:
# Ventana emergente
from channels import videolibrary
p_dialog = platformtools.dialog_progress_bg('alfa', 'Cargando...')
p_dialog = platformtools.dialog_progress_bg(config.get_localized_string(20000), config.get_localized_string(70004))
p_dialog.update(0, '')
itemlist = videolibrary.findvideos(item)

View File

@@ -118,7 +118,7 @@ def render_items(itemlist, parent_item):
# Si no hay ningun item, mostramos un aviso
if not len(itemlist):
itemlist.append(Item(title="No hay elementos que mostrar"))
itemlist.append(Item(title=config.get_localized_string(60347)))
genre = False
if 'nero' in parent_item.title:
@@ -437,7 +437,7 @@ def set_context_commands(item, parent_item):
if item.action and item.action not in ["add_pelicula_to_library", "add_serie_to_library", "buscartrailer"]:
# Mostrar informacion: si el item tiene plot suponemos q es una serie, temporada, capitulo o pelicula
if item.infoLabels['plot'] and (num_version_xbmc < 17.0 or item.contentType == 'season'):
context_commands.append(("Información", "XBMC.Action(Info)"))
context_commands.append((config.get_localized_string(60348), "XBMC.Action(Info)"))
# ExtendedInfo: Si esta instalado el addon y se cumplen una serie de condiciones
if xbmc.getCondVisibility('System.HasAddon(script.extendedinfo)') \
@@ -482,7 +482,7 @@ def set_context_commands(item, parent_item):
# 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", "XBMC.Container.Refresh (%s?%s)" %
context_commands.append((config.get_localized_string(60349), "XBMC.Container.Refresh (%s?%s)" %
(sys.argv[0], Item(channel=item.channel, action="mainlist").tourl())))
# Añadir a Favoritos
@@ -514,7 +514,7 @@ def set_context_commands(item, parent_item):
item.wanted = item.contentSerieName
else:
item.wanted = item.contentTitle
context_commands.append(("[COLOR yellow]Buscar en otros canales[/COLOR]",
context_commands.append((config.get_localized_string(60350),
"XBMC.Container.Update (%s?%s)" % (sys.argv[0],
item.clone(channel='search',
action="do_search",
@@ -524,7 +524,7 @@ def set_context_commands(item, parent_item):
# Definir como Pagina de inicio
if config.get_setting('start_page'):
if item.action not in ['findvideos', 'play']:
context_commands.insert(0, ("[COLOR 0xffccff00]Definir como pagina de inicio[/COLOR]",
context_commands.insert(0, (config.get_localized_string(60351),
"XBMC.RunPlugin(%s?%s)" % (
sys.argv[0], Item(channel='side_menu',
action="set_custom_start",
@@ -533,19 +533,19 @@ def set_context_commands(item, parent_item):
if item.channel != "videolibrary":
# Añadir Serie a la videoteca
if item.action in ["episodios", "get_episodios"] and item.contentSerieName:
context_commands.append(("Añadir Serie a Videoteca", "XBMC.RunPlugin(%s?%s)" %
context_commands.append((config.get_localized_string(60352), "XBMC.RunPlugin(%s?%s)" %
(sys.argv[0], item.clone(action="add_serie_to_library",
from_action=item.action).tourl())))
# Añadir Pelicula a videoteca
elif item.action in ["detail", "findvideos"] and item.contentType == 'movie' and item.contentTitle:
context_commands.append(("Añadir Pelicula a Videoteca", "XBMC.RunPlugin(%s?%s)" %
context_commands.append((config.get_localized_string(60353), "XBMC.RunPlugin(%s?%s)" %
(sys.argv[0], item.clone(action="add_pelicula_to_library",
from_action=item.action).tourl())))
if item.channel != "downloads":
# Descargar pelicula
if item.contentType == "movie" and item.contentTitle:
context_commands.append(("Descargar Pelicula", "XBMC.RunPlugin(%s?%s)" %
context_commands.append((config.get_localized_string(60354), "XBMC.RunPlugin(%s?%s)" %
(sys.argv[0], item.clone(channel="downloads", action="save_download",
from_channel=item.channel, from_action=item.action)
.tourl())))
@@ -553,45 +553,45 @@ def set_context_commands(item, parent_item):
elif item.contentSerieName:
# Descargar serie
if item.contentType == "tvshow":
context_commands.append(("Descargar Serie", "XBMC.RunPlugin(%s?%s)" %
context_commands.append((config.get_localized_string(60355), "XBMC.RunPlugin(%s?%s)" %
(sys.argv[0], item.clone(channel="downloads", action="save_download",
from_channel=item.channel,
from_action=item.action).tourl())))
# Descargar episodio
elif item.contentType == "episode":
context_commands.append(("Descargar Episodio", "XBMC.RunPlugin(%s?%s)" %
context_commands.append((config.get_localized_string(60356), "XBMC.RunPlugin(%s?%s)" %
(sys.argv[0], item.clone(channel="downloads", action="save_download",
from_channel=item.channel,
from_action=item.action).tourl())))
# Descargar temporada
elif item.contentType == "season":
context_commands.append(("Descargar Temporada", "XBMC.RunPlugin(%s?%s)" %
context_commands.append((config.get_localized_string(60357), "XBMC.RunPlugin(%s?%s)" %
(sys.argv[0], 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", "XBMC.Container.Update(%s?%s)" %
context_commands.append((config.get_localized_string(60358), "XBMC.Container.Update(%s?%s)" %
(sys.argv[0], Item(channel="setting", action="mainlist").tourl())))
# Buscar Trailer
if item.action == "findvideos" or "buscar_trailer" in context:
context_commands.append(("Buscar Trailer", "XBMC.RunPlugin(%s?%s)" % (sys.argv[0], item.clone(
context_commands.append((config.get_localized_string(60359), "XBMC.RunPlugin(%s?%s)" % (sys.argv[0], item.clone(
channel="trailertools", action="buscartrailer", contextual=True).tourl())))
# Añadir SuperFavourites al menu contextual (1.0.53 o superior necesario)
sf_file_path = xbmc.translatePath("special://home/addons/plugin.program.super.favourites/LaunchSFMenu.py")
check_sf = os.path.exists(sf_file_path)
if check_sf and xbmc.getCondVisibility('System.HasAddon("plugin.program.super.favourites")'):
context_commands.append(("Super Favourites Menu",
context_commands.append((config.get_localized_string(60361),
"XBMC.RunScript(special://home/addons/plugin.program.super.favourites/LaunchSFMenu.py)"))
context_commands = sorted(context_commands, key=lambda comand: comand[0])
# Menu Rapido
context_commands.insert(0, ("[COLOR 0xffccff00]<Menú Rápido>[/COLOR]",
context_commands.insert(0, (config.get_localized_string(60360),
"XBMC.Container.Update (%s?%s)" % (sys.argv[0], Item(channel='side_menu',
action="open_menu",
parent=parent_item.tourl()).tourl(
@@ -755,7 +755,7 @@ def handle_wait(time_to_wait, title, text):
secs += 1
percent = increment * secs
secs_left = str((time_to_wait - secs))
remaining_display = ' Espera ' + secs_left + ' segundos para que comience el vídeo...'
remaining_display = config.get_localized_string(70176) + secs_left + config.get_localized_string(70177)
espera.update(percent, ' ' + text, remaining_display)
xbmc.sleep(1000)
if espera.iscanceled():
@@ -835,13 +835,13 @@ def get_dialogo_opciones(item, default_action, strm, autoplay):
if not autoplay:
if item.server != "":
if "<br/>" in motivo:
dialog_ok("No puedes ver ese vídeo porque...", motivo.split("<br/>")[0], motivo.split("<br/>")[1],
dialog_ok(config.get_localized_string(60362), motivo.split("<br/>")[0], motivo.split("<br/>")[1],
item.url)
else:
dialog_ok("No puedes ver ese vídeo porque...", motivo, item.url)
dialog_ok(config.get_localized_string(60362), motivo, item.url)
else:
dialog_ok("No puedes ver ese vídeo porque...", "El servidor donde está alojado no está",
"soportado en alfa todavía", item.url)
dialog_ok(config.get_localized_string(60362), config.get_localized_string(60363),
config.get_localized_string(60364), item.url)
if item.channel == "favorites":
# "Quitar de favoritos"
@@ -935,7 +935,7 @@ def get_video_seleccionado(item, seleccion, video_urls):
# Si hay un tiempo de espera (como en megaupload), lo impone ahora
if wait_time > 0:
continuar = handle_wait(wait_time, item.server, "Cargando vídeo...")
continuar = handle_wait(wait_time, item.server, config.get_localized_string(60365))
if not continuar:
mediaurl = ""
@@ -1016,9 +1016,9 @@ def torrent_client_installed(show_tuple=False):
for client in torrent_clients:
if xbmc.getCondVisibility('System.HasAddon("%s")' % client["id"]):
if show_tuple:
torrent_options.append(["Plugin externo: %s" % client["name"], client["url"]])
torrent_options.append([config.get_localized_string(60366) % client["name"], client["url"]])
else:
torrent_options.append("Plugin externo: %s" % client["name"])
torrent_options.append(config.get_localized_string(60366) % client["name"])
return torrent_options
@@ -1035,12 +1035,12 @@ def play_torrent(item, xlistitem, mediaurl):
if torrent_client and torrent_client - 1 <= len(torrent_options):
if torrent_client == 0:
seleccion = dialog_select("Abrir torrent con...", [opcion[0] for opcion in torrent_options])
seleccion = dialog_select(config.get_localized_string(70193), [opcion[0] for opcion in torrent_options])
else:
seleccion = torrent_client - 1
else:
if len(torrent_options) > 1:
seleccion = dialog_select("Abrir torrent con...", [opcion[0] for opcion in torrent_options])
seleccion = dialog_select(config.get_localized_string(70193), [opcion[0] for opcion in torrent_options])
else:
seleccion = 0
@@ -1068,10 +1068,10 @@ def play_torrent(item, xlistitem, mediaurl):
# Iniciamos el cliente:
c = Client(url=mediaurl, is_playing_fnc=xbmc_player.isPlaying, wait_time=None, timeout=10,
temp_path=os.path.join(client_tmp_path, "alfa-torrent"), print_status=debug)
temp_path=os.path.join(client_tmp_path, config.get_localized_string(70194)), print_status=debug)
# Mostramos el progreso
progreso = dialog_progress("Alfa - Torrent", "Iniciando...")
progreso = dialog_progress(config.get_localized_string(70195), config.get_localized_string(70196))
# Mientras el progreso no sea cancelado ni el cliente cerrado
while not c.closed:
@@ -1092,7 +1092,7 @@ def play_torrent(item, xlistitem, mediaurl):
(s.progress_file, s.file_size, s.str_state, s._download_rate)
txt2 = 'S: %d(%d) P: %d(%d)' % (s.num_seeds, s.num_complete, s.num_peers, s.num_incomplete)
try:
txt3 = 'Deteniendo automaticamente en: %ss' % (int(s.timeout))
txt3 = config.get_localized_string(70197) % (int(s.timeout))
except:
txt3 = ''
@@ -1102,21 +1102,21 @@ def play_torrent(item, xlistitem, mediaurl):
if progreso.iscanceled():
progreso.close()
if s.buffer == 100:
if dialog_yesno("Alfa - Torrent", "¿Deseas iniciar la reproduccion?"):
if dialog_yesno(config.get_localized_string(70195), config.get_localized_string(70198)):
played = False
progreso = dialog_progress("Alfa - Torrent", "")
progreso = dialog_progress(config.get_localized_string(70195), "")
progreso.update(s.buffer, txt, txt2, txt3)
else:
progreso = dialog_progress("Alfa - Torrent", "")
progreso = dialog_progress(config.get_localized_string(70195), "")
break
else:
if dialog_yesno("Alfa - Torrent", "¿Deseas cancelar el proceso?"):
progreso = dialog_progress("Alfa - Torrent", "")
if dialog_yesno(config.get_localized_string(70195), config.get_localized_string(70199)):
progreso = dialog_progress(config.get_localized_string(70195), "")
break
else:
progreso = dialog_progress("Alfa - Torrent", "")
progreso = dialog_progress(config.get_localized_string(70195), "")
progreso.update(s.buffer, txt, txt2, txt3)
# Si el buffer se ha llenado y la reproduccion no ha sido iniciada, se inicia
@@ -1147,7 +1147,7 @@ def play_torrent(item, xlistitem, mediaurl):
time.sleep(1)
# Cuando este cerrado, Volvemos a mostrar el dialogo
progreso = dialog_progress("Alfa - Torrent", "")
progreso = dialog_progress(config.get_localized_string(70195), "")
progreso.update(s.buffer, txt, txt2, txt3)
except:
@@ -1155,7 +1155,7 @@ def play_torrent(item, xlistitem, mediaurl):
logger.error(traceback.format_exc())
break
progreso.update(100, "Terminando y eliminando datos", " ", " ")
progreso.update(100, config.get_localized_string(70200), " ", " ")
# Detenemos el cliente
if not c.closed:

View File

@@ -204,6 +204,7 @@ def set_lang(language):
#logger.info()
cast =['castellano','espanol','cast','esp','espaol', 'es','zc', 'spa', 'spanish', 'vc']
ita =['italiano','italian','ita','it']
lat=['latino','lat','la', 'espanol latino', 'espaol latino', 'zl', 'mx', 'co', 'vl']
vose=['subtitulado','subtitulada','sub','sub espanol','vose','espsub','su','subs castellano',
'sub: español', 'vs', 'zs', 'vs', 'english-spanish subs', 'ingles sub espanol']
@@ -222,6 +223,8 @@ def set_lang(language):
language = 'cast'
elif language in lat:
language = 'lat'
elif language in ita:
language = 'ita'
elif language in vose:
language = 'vose'
elif language in vos:

View File

@@ -208,8 +208,8 @@ def sync_trakt_kodi(silent=True):
logger.info("Sincronizacion con Trakt iniciada")
if notificacion:
platformtools.dialog_notification("Alfa",
"Sincronizacion con Trakt iniciada",
platformtools.dialog_notification(config.get_localized_string(20000),
config.get_localized_string(60045),
icon=0,
time=2000)
@@ -440,17 +440,15 @@ def set_content(content_type, silent=False):
videolibrarypath = config.get_setting("videolibrarypath")
if content_type == 'movie':
scraper = ["The Movie Database", "Universal Movie Scraper"]
seleccion = platformtools.dialog_select("Seleccione el scraper para las películas", scraper)
scraper = [config.get_localized_string(70093), config.get_localized_string(70096)]
seleccion = platformtools.dialog_select(config.get_localized_string(70094), scraper)
# Instalar The Movie Database
if seleccion == -1 or seleccion == 0:
if not xbmc.getCondVisibility('System.HasAddon(metadata.themoviedb.org)'):
if not silent:
# Preguntar si queremos instalar metadata.themoviedb.org
install = platformtools.dialog_yesno("The Movie Database",
"No se ha encontrado el Scraper de películas de TheMovieDB.",
"¿Desea instalarlo ahora?")
install = platformtools.dialog_yesno(config.get_localized_string(60046))
else:
install = True
@@ -464,7 +462,7 @@ def set_content(content_type, silent=False):
continuar = (install and xbmc.getCondVisibility('System.HasAddon(metadata.themoviedb.org)'))
if not continuar:
msg_text = "The Movie Database no instalado."
msg_text = config.get_localized_string(60047)
if continuar:
xbmc.executebuiltin('xbmc.addon.opensettings(metadata.themoviedb.org)', True)
@@ -474,9 +472,7 @@ def set_content(content_type, silent=False):
continuar = False
if not silent:
# Preguntar si queremos instalar metadata.universal
install = platformtools.dialog_yesno("Universal Movie Scraper",
"No se ha encontrado el Scraper de series de TheMovieDB.",
"¿Desea instalarlo ahora?")
install = platformtools.dialog_yesno(config.get_localized_string(70095))
else:
install = True
@@ -490,22 +486,20 @@ def set_content(content_type, silent=False):
continuar = (install and continuar)
if not continuar:
msg_text = "Universal Movie Scraper no instalado."
msg_text = config.get_localized_string(70097)
if continuar:
xbmc.executebuiltin('xbmc.addon.opensettings(metadata.universal)', True)
else: # SERIES
scraper = ["The TVDB", "The Movie Database"]
seleccion = platformtools.dialog_select("Seleccione el scraper para las series", scraper)
scraper = [config.get_localized_string(70098), config.get_localized_string(70093)]
seleccion = platformtools.dialog_select(config.get_localized_string(70107), scraper)
# Instalar The TVDB
if seleccion == -1 or seleccion == 0:
if not xbmc.getCondVisibility('System.HasAddon(metadata.tvdb.com)'):
if not silent:
# Preguntar si queremos instalar metadata.tvdb.com
install = platformtools.dialog_yesno("The TVDB",
"No se ha encontrado el Scraper de series de The TVDB.",
"¿Desea instalarlo ahora?")
install = platformtools.dialog_yesno(config.get_localized_string(60048))
else:
install = True
@@ -519,7 +513,7 @@ def set_content(content_type, silent=False):
continuar = (install and xbmc.getCondVisibility('System.HasAddon(metadata.tvdb.com)'))
if not continuar:
msg_text = "The TVDB no instalado."
msg_text = config.get_localized_string(70099)
if continuar:
xbmc.executebuiltin('xbmc.addon.opensettings(metadata.tvdb.com)', True)
@@ -529,9 +523,7 @@ def set_content(content_type, silent=False):
continuar = False
if not silent:
# Preguntar si queremos instalar metadata.tvshows.themoviedb.org
install = platformtools.dialog_yesno("The Movie Database",
"No se ha encontrado el Scraper de series de TheMovieDB.",
"¿Desea instalarlo ahora?")
install = platformtools.dialog_yesno(config.get_localized_string(70100))
else:
install = True
@@ -546,7 +538,7 @@ def set_content(content_type, silent=False):
continuar = (install and continuar)
if not continuar:
msg_text = "The Movie Database no instalado."
msg_text = config.get_localized_string(60047)
if continuar:
xbmc.executebuiltin('xbmc.addon.opensettings(metadata.tvshows.themoviedb.org)', True)
@@ -594,7 +586,7 @@ def set_content(content_type, silent=False):
idParentPath = idPath
idPath += 1
else:
msg_text = "Error al fijar videolibrarypath en BD"
msg_text = config.get_localized_string(70101)
if continuar:
continuar = False
@@ -647,7 +639,7 @@ def set_content(content_type, silent=False):
else:
if not silent:
# Preguntar si queremos configurar themoviedb.org como opcion por defecto
actualizar = platformtools.dialog_yesno("The TVDB", strActualizar)
actualizar = platformtools.dialog_yesno(config.get_localized_string(70098), strActualizar)
else:
actualizar = True
@@ -663,17 +655,17 @@ def set_content(content_type, silent=False):
continuar = True
if not continuar:
msg_text = "Error al configurar el scraper en la BD."
msg_text = config.get_localized_string(60055)
if not continuar:
heading = "Videoteca %s no configurada" % content_type
heading = config.get_localized_string(70102) % content_type
elif content_type == 'SERIES' and not xbmc.getCondVisibility(
'System.HasAddon(metadata.tvshows.themoviedb.org)'):
heading = "Videoteca %s configurada" % content_type
msg_text = "Es necesario reiniciar Kodi para que los cambios surtan efecto."
heading = config.get_localized_string(70103) % content_type
msg_text = config.get_localized_string(60058)
else:
heading = "Videoteca %s configurada" % content_type
msg_text = "Felicidades la videoteca de Kodi ha sido configurada correctamente."
heading = config.get_localized_string(70103) % content_type
msg_text = config.get_localized_string(70104)
platformtools.dialog_notification(heading, msg_text, icon=1, time=3000)
logger.info("%s: %s" % (heading, msg_text))
@@ -824,9 +816,9 @@ def ask_set_content(flag, silent=False):
add_sources(config.get_setting("downloadpath"))
if not silent:
heading = "Alfa Auto-configuración"
linea1 = "¿Desea que Alfa auto-configure la videoteca de Kodi? Se le pedirá que configure los scrapers para las películas y las series."
linea2 = "Si pulsa 'No', podra hacerlo desde 'Configuración > Preferencia > Rutas'."
heading = config.get_localized_string(59971)
linea1 = config.get_localized_string(70105)
linea2 = config.get_localized_string(70106)
if platformtools.dialog_yesno(heading, linea1, linea2):
do_config()
else:

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,122 +1,125 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<settings>
<category label="General">
<setting id="player_mode" type="enum" values="Direct|SetResolvedUrl|Built-In|Download and Play" label="30044" default="0"/>
<setting id="default_action" type="enum" lvalues="30006|30007|30008" label="30005" default="0"/>
<setting id="thumbnail_type" type="enum" lvalues="30011|30012|30200" label="30010" default="2"/>
<setting id="channel_language" type="labelenum" values="all|cast|lat" label="30019" default="all"/>
<setting id="trakt_sync" type="bool" label="Sincronizar con Trakt.tv (Debes tener una cuenta)" default="false"/>
<setting id="forceview" type="bool" label="30043" default="false"/>
<setting id="faster_item_serialization" type="bool" label="30300" default="false"/>
<setting id="debug" type="bool" label="30003" default="false"/>
<setting label="Uso de servidores" type="lsep"/>
<setting id="resolve_priority" type="enum" label="Método prioritario" values="Free primero|Premium primero|Debriders primero" default="0"/>
<setting id="resolve_stop" type="bool" label="Dejar de buscar cuando encuentre una opción" default="true"/>
<setting id="hidepremium" type="bool" label="Ocultar servidores de pago sin cuenta" default="false"/>
<category label="$ADDON[plugin.video.alfa 70168]">
<setting id="player_mode" type="enum" values="Direct|SetResolvedUrl|Built-In|Download and Play" label="$ADDON[plugin.video.alfa 30044]" default="0"/>
<setting id="default_action" type="enum" lvalues="30006|30007|30008" label="$ADDON[plugin.video.alfa 30005]" default="0"/>
<setting id="thumbnail_type" type="enum" lvalues="30011|30012|30200" label="$ADDON[plugin.video.alfa 30010]" default="2"/>
<setting id="channel_language" type="labelenum" values="all|cast|lat|ita" label="$ADDON[plugin.video.alfa 30019]" default="all"/>
<setting id="trakt_sync" type="bool" label="$ADDON[plugin.video.alfa 70109]" default="false"/>
<setting id="forceview" type="bool" label="$ADDON[plugin.video.alfa 30043]" default="false"/>
<setting id="faster_item_serialization" type="bool" label="$ADDON[plugin.video.alfa 30300]" default="false"/>
<setting id="debug" type="bool" label="$ADDON[plugin.video.alfa 30003]" default="false"/>
<setting label="$ADDON[plugin.video.alfa 70169]" type="lsep"/>
<setting id="resolve_priority" type="enum" label="$ADDON[plugin.video.alfa 70110]" lvalues="70164|70165|70166" default="0"/>
<setting id="resolve_stop" type="bool" label="$ADDON[plugin.video.alfa 70111]" default="true"/>
<setting id="hidepremium" type="bool" label="$ADDON[plugin.video.alfa 70112]" default="false"/>
<setting type="sep"/>
<setting label="Canales para adultos" type="lsep"/>
<setting id="adult_aux_intro_password" type="text" label="Contraseña (por defecto 0000):" option="hidden" default=""/>
<setting id="adult_mode" type="enum" values="Nunca|Siempre|Solo hasta que se reinicie Kodi" label="30002" enable="!eq(-1,)" default="0"/>
<setting id="adult_request_password" type="bool" label="Solicitar contraseña para abrir canales de adultos" enable="!eq(-1,0)+!eq(-2,)" default="true"/>
<setting id="adult_aux_new_password1" type="text" label="Nueva contraseña:" option="hidden" enable="!eq(-3,)" default=""/>
<setting id="adult_aux_new_password2" type="text" label="Confirmar nueva contraseña:" option="hidden" enable="!eq(-1,)" default=""/>
<setting label="$ADDON[plugin.video.alfa 60305]" type="lsep"/>
<setting id="adult_aux_intro_password" type="text" label="$ADDON[plugin.video.alfa 70113]" option="hidden" default=""/>
<setting id="adult_mode" type="enum" lvalues="60602|60616|70114" label="$ADDON[plugin.video.alfa 30002]" enable="!eq(-1,)" default="0"/>
<setting id="adult_request_password" type="bool" label="$ADDON[plugin.video.alfa 70115]" enable="!eq(-1,0)+!eq(-2,)" default="true"/>
<setting id="adult_aux_new_password1" type="text" label="$ADDON[plugin.video.alfa 70116]" option="hidden" enable="!eq(-3,)" default=""/>
<setting id="adult_aux_new_password2" type="text" label="$ADDON[plugin.video.alfa 70117]" option="hidden" enable="!eq(-1,)" default=""/>
</category>
<!-- Path downloads -->
<category label="30501">
<setting id="downloadpath" type="folder" label="30017" default=""/>
<setting id="downloadlistpath" type="folder" label="30018" default=""/>
<setting id="videolibrarypath" type="folder" label="30067" default=""/>
<category label="$ADDON[plugin.video.alfa 30501]">
<setting id="downloadpath" type="folder" label="$ADDON[plugin.video.alfa 30017]" default=""/>
<setting id="downloadlistpath" type="folder" label="$ADDON[plugin.video.alfa 30018]" default=""/>
<setting id="videolibrarypath" type="folder" label="$ADDON[plugin.video.alfa 30067]" default=""/>
<setting type="sep"/>
<setting label="30131" type="lsep"/>
<setting id="folder_tvshows" type="text" label="Nombre de carpeta para 'Series'" default="SERIES"/>
<setting id="folder_movies" type="text" label="Nombre de carpeta para 'Peliculas'" default="CINE"/>
<setting label="$ADDON[plugin.video.alfa 30131]" type="lsep"/>
<setting id="folder_tvshows" type="text" label="$ADDON[plugin.video.alfa 70118]" default="SERIES"/>
<setting id="folder_movies" type="text" label="$ADDON[plugin.video.alfa 70119]" default="CINE"/>
<setting id="videolibrary_kodi_flag" type="number" label="" default="0" visible="false"/>
<setting id="videolibrary_kodi" type="bool" label="Autoconfigurar videoteca de XBMC/Kodi para contenido de Alfa" enable="lt(-1,2)+eq(0,false)" default="false"/>
<setting id="videolibrary_kodi" type="bool" label="$ADDON[plugin.video.alfa 70120]" enable="lt(-1,2)+eq(0,false)" default="false"/>
</category>
<category label="Pagina de inicio">
<setting id="start_page" type="bool" label="Activar pagina de inicio" default="false"/>
<setting id="custom_start" type="bool" label="Personalizado (seleccionar desde un canal)" default="false"
<category label="$ADDON[plugin.video.alfa 70121]">
<setting id="start_page" type="bool" label="$ADDON[plugin.video.alfa 70121]" default="false"/>
<setting id="custom_start" type="bool" label="$ADDON[plugin.video.alfa 70122]" default="false"
visible="eq(-1,True)"/>
<setting id="news_start" type="bool" label="Mostrar Novedades" default="false" visible="eq(-2,True)"
<setting id="news_start" type="bool" label="$ADDON[plugin.video.alfa 70123]" default="false" visible="eq(-2,True)"
enable="eq(-1,False)+eq(-2,True"/>
<setting id="category" type="labelenum" label="Categoria"
values="Peliculas|Series|Anime|Infantiles|Documentales|Terror|Castellano|Latino|Torrent"
default="Peliculas" visible="eq(-3,True)+eq(-1,True)+eq(-2,False)" enable="eq(-3,True)+eq(-1,True)+(-2,false)"/>
<setting id="category" type="labelenum" label="$ADDON[plugin.video.alfa 70124]"
lvalues="70137|70136|70127|60269|60272|70013|70014|59976|70171"
default="$ADDON[plugin.video.alfa 70137]" visible="eq(-3,True)+eq(-1,True)+eq(-2,False)" enable="eq(-3,True)+eq(-1,True)+(-2,false)"/>
</category>
<category label="Opciones Visuales">
<setting id="icon_set" type="labelenum" label="Set de iconos" values="default|dark|angedam" default="default"/>
<setting id="infoplus_set" type="labelenum" label="Opción visual Infoplus" values="Sin animación|Con animación" default="Sin animación"/>
<setting id="video_thumbnail_type" type="enum" label="Thumbnail para videos" values="Poster|Logo del servidor" default="0"/>
<setting label="Opciones para Titulos" type="lsep"/>
<setting id="unify" type="bool" label="Titulos Inteligentes" default="false"/>
<setting id="title_color" type="bool" label="Colores Personalizados" default="false" visible="eq(-1,true)"/>
<setting id="movie_color" type="labelenum" label="Pelicula"
<category label="$ADDON[plugin.video.alfa 70126]">
<setting id="icon_set" type="labelenum" label="$ADDON[plugin.video.alfa 70108]" values="default|dark|angedam" default="default"/>
<setting id="infoplus_set" type="labelenum" label="$ADDON[plugin.video.alfa 70128]" lvalues="70129|70130" default="$ADDON[plugin.video.alfa 70129]"/>
<setting id="video_thumbnail_type" type="enum" label="$ADDON[plugin.video.alfa 70131]" lvalues="70132|70133" default="0"/>
<setting label="$ADDON[plugin.video.alfa 70167]" type="lsep"/>
<setting id="unify" type="bool" label="$ADDON[plugin.video.alfa 70134]" default="false"/>
<setting id="title_color" type="bool" label="$ADDON[plugin.video.alfa 70135]" default="false" visible="eq(-1,true)"/>
<setting id="movie_color" type="labelenum" label="$ADDON[plugin.video.alfa 70137]"
lvalues="[COLOR white]white[/COLOR]|[COLOR cyan]cyan[/COLOR]|[COLOR deepskyblue]deepskyblue[/COLOR]|[COLOR firebrick]firebrick[/COLOR]|[COLOR gold]gold[/COLOR]|[COLOR goldenrod]goldenrod[/COLOR]|[COLOR hotpink]hotpink[/COLOR]|[COLOR limegreen]limegreen[/COLOR]|[COLOR orange]orange[/COLOR]|[COLOR orchid]orchid[/COLOR]|[COLOR red]red[/COLOR]|[COLOR salmon]salmon[/COLOR]|[COLOR yellow]yellow[/COLOR]"
default="white" visible="eq(-1,true)+eq(-2,true)"/>
<setting id="tvshow_color" type="labelenum" label="Serie"
<setting id="tvshow_color" type="labelenum" label="$ADDON[plugin.video.alfa 70136]"
lvalues="[COLOR white]white[/COLOR]|[COLOR cyan]cyan[/COLOR]|[COLOR deepskyblue]deepskyblue[/COLOR]|[COLOR firebrick]firebrick[/COLOR]|[COLOR gold]gold[/COLOR]|[COLOR goldenrod]goldenrod[/COLOR]|[COLOR hotpink]hotpink[/COLOR]|[COLOR limegreen]limegreen[/COLOR]|[COLOR orange]orange[/COLOR]|[COLOR orchid]orchid[/COLOR]|[COLOR red]red[/COLOR]|[COLOR salmon]salmon[/COLOR]|[COLOR yellow]yellow[/COLOR]"
default="white" visible="eq(-2,true)+eq(-3,true)"/>
<setting id="year_color" type="labelenum" label="Año"
<setting id="year_color" type="labelenum" label="$ADDON[plugin.video.alfa 60232]"
lvalues="[COLOR white]white[/COLOR]|[COLOR cyan]cyan[/COLOR]|[COLOR deepskyblue]deepskyblue[/COLOR]|[COLOR firebrick]firebrick[/COLOR]|[COLOR gold]gold[/COLOR]|[COLOR goldenrod]goldenrod[/COLOR]|[COLOR hotpink]hotpink[/COLOR]|[COLOR limegreen]limegreen[/COLOR]|[COLOR orange]orange[/COLOR]|[COLOR orchid]orchid[/COLOR]|[COLOR red]red[/COLOR]|[COLOR salmon]salmon[/COLOR]|[COLOR yellow]yellow[/COLOR]"
default="white" visible="eq(-3,true)+eq(-4,true)"/>
<setting id="rating_1_color" type="labelenum" label="Valoracion Baja"
<setting id="rating_1_color" type="labelenum" label="$ADDON[plugin.video.alfa 70138]"
lvalues="[COLOR white]white[/COLOR]|[COLOR cyan]cyan[/COLOR]|[COLOR deepskyblue]deepskyblue[/COLOR]|[COLOR firebrick]firebrick[/COLOR]|[COLOR gold]gold[/COLOR]|[COLOR goldenrod]goldenrod[/COLOR]|[COLOR hotpink]hotpink[/COLOR]|[COLOR limegreen]limegreen[/COLOR]|[COLOR orange]orange[/COLOR]|[COLOR orchid]orchid[/COLOR]|[COLOR red]red[/COLOR]|[COLOR salmon]salmon[/COLOR]|[COLOR yellow]yellow[/COLOR]"
default="white" visible="eq(-4,true)+eq(-5,true)"/>
<setting id="rating_2_color" type="labelenum" label="Valoracion Media"
<setting id="rating_2_color" type="labelenum" label="$ADDON[plugin.video.alfa 70139]"
lvalues="[COLOR white]white[/COLOR]|[COLOR cyan]cyan[/COLOR]|[COLOR deepskyblue]deepskyblue[/COLOR]|[COLOR firebrick]firebrick[/COLOR]|[COLOR gold]gold[/COLOR]|[COLOR goldenrod]goldenrod[/COLOR]|[COLOR hotpink]hotpink[/COLOR]|[COLOR limegreen]limegreen[/COLOR]|[COLOR orange]orange[/COLOR]|[COLOR orchid]orchid[/COLOR]|[COLOR red]red[/COLOR]|[COLOR salmon]salmon[/COLOR]|[COLOR yellow]yellow[/COLOR]"
default="white" visible="eq(-5,true)+eq(-6,true)"/>
<setting id="rating_3_color" type="labelenum" label="Valoracion Alta"
<setting id="rating_3_color" type="labelenum" label="$ADDON[plugin.video.alfa 70140]"
lvalues="[COLOR white]white[/COLOR]|[COLOR cyan]cyan[/COLOR]|[COLOR deepskyblue]deepskyblue[/COLOR]|[COLOR firebrick]firebrick[/COLOR]|[COLOR gold]gold[/COLOR]|[COLOR goldenrod]goldenrod[/COLOR]|[COLOR hotpink]hotpink[/COLOR]|[COLOR limegreen]limegreen[/COLOR]|[COLOR orange]orange[/COLOR]|[COLOR orchid]orchid[/COLOR]|[COLOR red]red[/COLOR]|[COLOR salmon]salmon[/COLOR]|[COLOR yellow]yellow[/COLOR]"
default="white" visible="eq(-6,true)+eq(-7,true)"/>
<setting id="quality_color" type="labelenum" label="Calidad"
<setting id="quality_color" type="labelenum" label="$ADDON[plugin.video.alfa 70141]"
lvalues="[COLOR white]white[/COLOR]|[COLOR cyan]cyan[/COLOR]|[COLOR deepskyblue]deepskyblue[/COLOR]|[COLOR firebrick]firebrick[/COLOR]|[COLOR gold]gold[/COLOR]|[COLOR goldenrod]goldenrod[/COLOR]|[COLOR hotpink]hotpink[/COLOR]|[COLOR limegreen]limegreen[/COLOR]|[COLOR orange]orange[/COLOR]|[COLOR orchid]orchid[/COLOR]|[COLOR red]red[/COLOR]|[COLOR salmon]salmon[/COLOR]|[COLOR yellow]yellow[/COLOR]"
default="white" visible="eq(-7,true)+eq(-8,true)"/>
<setting id="cast_color" type="labelenum" label="Castellano"
<setting id="cast_color" type="labelenum" label="$ADDON[plugin.video.alfa 59980]"
lvalues="[COLOR white]white[/COLOR]|[COLOR cyan]cyan[/COLOR]|[COLOR deepskyblue]deepskyblue[/COLOR]|[COLOR firebrick]firebrick[/COLOR]|[COLOR gold]gold[/COLOR]|[COLOR goldenrod]goldenrod[/COLOR]|[COLOR hotpink]hotpink[/COLOR]|[COLOR limegreen]limegreen[/COLOR]|[COLOR orange]orange[/COLOR]|[COLOR orchid]orchid[/COLOR]|[COLOR red]red[/COLOR]|[COLOR salmon]salmon[/COLOR]|[COLOR yellow]yellow[/COLOR]"
default="white" visible="eq(-8,true)+eq(-9,true)"/>
<setting id="lat_color" type="labelenum" label="Latino"
<setting id="lat_color" type="labelenum" label="$ADDON[plugin.video.alfa 59981]"
lvalues="[COLOR white]white[/COLOR]|[COLOR cyan]cyan[/COLOR]|[COLOR deepskyblue]deepskyblue[/COLOR]|[COLOR firebrick]firebrick[/COLOR]|[COLOR gold]gold[/COLOR]|[COLOR goldenrod]goldenrod[/COLOR]|[COLOR hotpink]hotpink[/COLOR]|[COLOR limegreen]limegreen[/COLOR]|[COLOR orange]orange[/COLOR]|[COLOR orchid]orchid[/COLOR]|[COLOR red]red[/COLOR]|[COLOR salmon]salmon[/COLOR]|[COLOR yellow]yellow[/COLOR]"
default="white" visible="eq(-9,true)+eq(-10,true)"/>
<setting id="vose_color" type="labelenum" label="VOSE (Versión Original Subtitulado Español)"
<setting id="vose_color" type="labelenum" label="$ADDON[plugin.video.alfa 701402]"
lvalues="[COLOR white]white[/COLOR]|[COLOR cyan]cyan[/COLOR]|[COLOR deepskyblue]deepskyblue[/COLOR]|[COLOR firebrick]firebrick[/COLOR]|[COLOR gold]gold[/COLOR]|[COLOR goldenrod]goldenrod[/COLOR]|[COLOR hotpink]hotpink[/COLOR]|[COLOR limegreen]limegreen[/COLOR]|[COLOR orange]orange[/COLOR]|[COLOR orchid]orchid[/COLOR]|[COLOR red]red[/COLOR]|[COLOR salmon]salmon[/COLOR]|[COLOR yellow]yellow[/COLOR]"
default="white" visible="eq(-10,true)+eq(-11,true)"/>
<setting id="vos_color" type="labelenum" label="VOS (Versión Original Subtitulado)"
<setting id="vos_color" type="labelenum" label="$ADDON[plugin.video.alfa 70143]"
lvalues="[COLOR white]white[/COLOR]|[COLOR cyan]cyan[/COLOR]|[COLOR deepskyblue]deepskyblue[/COLOR]|[COLOR firebrick]firebrick[/COLOR]|[COLOR gold]gold[/COLOR]|[COLOR goldenrod]goldenrod[/COLOR]|[COLOR hotpink]hotpink[/COLOR]|[COLOR limegreen]limegreen[/COLOR]|[COLOR orange]orange[/COLOR]|[COLOR orchid]orchid[/COLOR]|[COLOR red]red[/COLOR]|[COLOR salmon]salmon[/COLOR]|[COLOR yellow]yellow[/COLOR]"
default="white" visible="eq(-11,true)+eq(-12,true)"/>
<setting id="vo_color" type="labelenum" label="VO (Versión Original)"
<setting id="vo_color" type="labelenum" label="$ADDON[plugin.video.alfa 70144]"
lvalues="[COLOR white]white[/COLOR]|[COLOR cyan]cyan[/COLOR]|[COLOR deepskyblue]deepskyblue[/COLOR]|[COLOR firebrick]firebrick[/COLOR]|[COLOR gold]gold[/COLOR]|[COLOR goldenrod]goldenrod[/COLOR]|[COLOR hotpink]hotpink[/COLOR]|[COLOR limegreen]limegreen[/COLOR]|[COLOR orange]orange[/COLOR]|[COLOR orchid]orchid[/COLOR]|[COLOR red]red[/COLOR]|[COLOR salmon]salmon[/COLOR]|[COLOR yellow]yellow[/COLOR]"
default="white" visible="eq(-12,true)+eq(-13,true)"/>
<setting id="server_color" type="labelenum" label="Servidores"
<setting id="server_color" type="labelenum" label="$ADDON[plugin.video.alfa 70145]"
lvalues="[COLOR white]white[/COLOR]|[COLOR cyan]cyan[/COLOR]|[COLOR deepskyblue]deepskyblue[/COLOR]|[COLOR firebrick]firebrick[/COLOR]|[COLOR gold]gold[/COLOR]|[COLOR goldenrod]goldenrod[/COLOR]|[COLOR hotpink]hotpink[/COLOR]|[COLOR limegreen]limegreen[/COLOR]|[COLOR orange]orange[/COLOR]|[COLOR orchid]orchid[/COLOR]|[COLOR red]red[/COLOR]|[COLOR salmon]salmon[/COLOR]|[COLOR yellow]yellow[/COLOR]"
default="white" visible="eq(-13,true)+eq(-14,true)"/>
<setting id="library_color" type="labelenum" label="Añadir a Videoteca"
<setting id="library_color" type="labelenum" label="$ADDON[plugin.video.alfa 70146]"
lvalues="[COLOR white]white[/COLOR]|[COLOR cyan]cyan[/COLOR]|[COLOR deepskyblue]deepskyblue[/COLOR]|[COLOR firebrick]firebrick[/COLOR]|[COLOR gold]gold[/COLOR]|[COLOR goldenrod]goldenrod[/COLOR]|[COLOR hotpink]hotpink[/COLOR]|[COLOR limegreen]limegreen[/COLOR]|[COLOR orange]orange[/COLOR]|[COLOR orchid]orchid[/COLOR]|[COLOR red]red[/COLOR]|[COLOR salmon]salmon[/COLOR]|[COLOR yellow]yellow[/COLOR]"
default="white" visible="eq(-14,true)+eq(-15,true)"/>
<setting id="update_color" type="labelenum" label="Videoteca (Actualizar serie)"
<setting id="update_color" type="labelenum" label="$ADDON[plugin.video.alfa 70147]"
lvalues="[COLOR white]white[/COLOR]|[COLOR cyan]cyan[/COLOR]|[COLOR deepskyblue]deepskyblue[/COLOR]|[COLOR firebrick]firebrick[/COLOR]|[COLOR gold]gold[/COLOR]|[COLOR goldenrod]goldenrod[/COLOR]|[COLOR hotpink]hotpink[/COLOR]|[COLOR limegreen]limegreen[/COLOR]|[COLOR orange]orange[/COLOR]|[COLOR orchid]orchid[/COLOR]|[COLOR red]red[/COLOR]|[COLOR salmon]salmon[/COLOR]|[COLOR yellow]yellow[/COLOR]"
default="white" visible="eq(-15,true)+eq(-16,true)"/>
<setting id="no_update_color" type="labelenum" label="Videoteca (No actualizar serie)"
<setting id="no_update_color" type="labelenum" label="$ADDON[plugin.video.alfa 70148]"
lvalues="[COLOR white]white[/COLOR]|[COLOR cyan]cyan[/COLOR]|[COLOR deepskyblue]deepskyblue[/COLOR]|[COLOR firebrick]firebrick[/COLOR]|[COLOR gold]gold[/COLOR]|[COLOR goldenrod]goldenrod[/COLOR]|[COLOR hotpink]hotpink[/COLOR]|[COLOR limegreen]limegreen[/COLOR]|[COLOR orange]orange[/COLOR]|[COLOR orchid]orchid[/COLOR]|[COLOR red]red[/COLOR]|[COLOR salmon]salmon[/COLOR]|[COLOR yellow]yellow[/COLOR]"
default="white" visible="eq(-16,true)+eq(-17,true)"/>
</category>
<category label="Otros">
<setting label="Info de películas/series en menú contextual" type="lsep"/>
<setting id="infoplus" type="bool" label="Mostrar opción Infoplus:" default="true"/>
<setting id="extended_info" type="bool" label="Mostrar opción ExtendedInfo (Necesario addon externo):" default="false"/>
<category label="$ADDON[plugin.video.alfa 70149]">
<setting label="$ADDON[plugin.video.alfa 70150]" type="lsep"/>
<setting id="infoplus" type="bool" label="$ADDON[plugin.video.alfa 70151]" default="true"/>
<setting id="extended_info" type="bool" label="$ADDON[plugin.video.alfa 70152]" default="false"/>
<setting label="Botones/Teclas de acceso (Cambios requieren reiniciar Kodi)" type="lsep"/>
<setting label="$ADDON[plugin.video.alfa 70153]" type="lsep"/>
<setting id="shortcut_key" type="action" label="30999" action="RunPlugin(plugin://plugin.video.alfa/?ew0KICAgICJhY3Rpb24iOiAia2V5bWFwIg0KfQ==)" />
<setting type="sep"/>
<setting label="TheMovieDB (obtiene datos de las películas o series)" type="lsep"/>
<setting id="tmdb_threads" type="labelenum" values="5|10|15|20|25|30" label="Búsquedas simultáneas (puede causar inestabilidad)" default="20"/>
<setting id="tmdb_plus_info" type="bool" label="Buscar información extendida (datos de actores) Aumenta el tiempo de búsqueda" default="false"/>
<setting id="tmdb_cache" type="bool" label="Usar caché (mejora las búsquedas recurrentes)" default="true"/>
<setting id="tmdb_cache_expire" type="enum" lvalues="cada 1 día|cada 7 días|cada 15 días|cada 30 días|No" label="¿Renovar caché?" enable="eq(-1,true)" default="4"/>
<setting id="tmdb_clean_db_cache" type="action" label="Pulse para 'Borrar caché' guardada" action="RunPlugin(plugin://plugin.video.alfa/?ew0KICAgICJhY3Rpb24iOiAic2NyaXB0Ig0KfQ==)" />
<setting label="$ADDON[plugin.video.alfa 70154]" type="lsep"/>
<setting id="tmdb_threads" type="labelenum" values="5|10|15|20|25|30" label="$ADDON[plugin.video.alfa 70155]" default="20"/>
<setting id="tmdb_plus_info" type="bool" label="$ADDON[plugin.video.alfa 70156]" default="false"/>
<setting id="tmdb_cache" type="bool" label="$ADDON[plugin.video.alfa 70157]" default="true"/>
<setting id="tmdb_cache_expire" type="enum" lvalues="70158|70159|70160|70161|70170" label="$ADDON[plugin.video.alfa 70162]" enable="eq(-1,true)" default="4"/>
<setting id="tmdb_clean_db_cache" type="action" label="$ADDON[plugin.video.alfa 70163]" action="RunPlugin(plugin://plugin.video.alfa/?ew0KICAgICJhY3Rpb24iOiAic2NyaXB0Ig0KfQ==)" />
</category>
<setting type="sep"/>
<setting label="Para evitar esperar demasiado cuando un servidor no responde:" type="lsep"/>
<setting id="httptools_timeout" type="labelenum" values="0|5|10|15|20|25|30" label="Timeout (tiempo de espera máximo)" default="15"/>
</category>
</settings>

View File

@@ -26,7 +26,7 @@
<textcolor>0xFFFFA500</textcolor>
<align>center</align>
<aligny>center</aligny>
<label>Opciones</label>
<label>$ADDON[plugin.video.alfa 70000]</label>
</control>
<control type="button" id="10003">
<posx>735</posx>
@@ -46,7 +46,7 @@
<texturenofocus>Controls/KeyboardKeyNF.png</texturenofocus>
<align>center</align>
<aligny>center</aligny>
<label>OK</label>
<label>$ADDON[plugin.video.alfa 70001]</label>
</control>
<control type="button" id="10005">
<posx>325</posx>
@@ -58,7 +58,7 @@
<texturenofocus>Controls/KeyboardKeyNF.png</texturenofocus>
<align>center</align>
<aligny>center</aligny>
<label>Cancelar</label>
<label>$ADDON[plugin.video.alfa 70002]</label>
</control>
<control type="button" id="10006">
<posx>495</posx>
@@ -70,7 +70,7 @@
<texturenofocus>Controls/KeyboardKeyNF.png</texturenofocus>
<align>center</align>
<aligny>center</aligny>
<label>Por defecto</label>
<label>$ADDON[plugin.video.alfa 70003]</label>
</control>
<control type="group" id="10007">
<posy>45</posy>
@@ -91,7 +91,7 @@
<textcolor>0xFFFFFFFF</textcolor>
<align>center</align>
<aligny>center</aligny>
<label>Cargando...</label>
<label>$ADDON[plugin.video.alfa 70004]</label>
</control>
</control>
<control type="image" id="10008">

View File

@@ -18,6 +18,8 @@ def get_video_url(page_url, premium=False, user="", password="", video_password=
data = data.replace("\\'", "'")
media_url = scrapertools.find_single_match(data, '{type:"video/mp4",src:"([^"]+)"}')
if not media_url:
media_url = scrapertools.find_single_match(data, '"file":"([^"]+)')
logger.info("media_url=" + media_url)
video_urls = list()

View File

@@ -3,14 +3,9 @@
# Service for updating new episodes on library series
# ------------------------------------------------------------
import datetime
import imp
import math
import threading
import datetime, imp, math, threading
from core import channeltools
from core import filetools
from core import videolibrarytools
from core import channeltools, filetools, videolibrarytools
from platformcode import config, logger
from platformcode import platformtools
from channels import videolibrary
@@ -18,33 +13,37 @@ from channels import videolibrary
def update(path, p_dialog, i, t, serie, overwrite):
logger.info("Actualizando " + path)
from lib import generictools
insertados_total = 0
#logger.debug(serie)
head_nfo, it = videolibrarytools.read_nfo(path + '/tvshow.nfo')
# logger.debug("%s: %s" %(serie.contentSerieName,str(list_canales) ))
for channel, url in serie.library_urls.items():
serie.channel = channel
serie.url = url
serie = generictools.redirect_clone_newpct1(serie) ###### Redirección al canal NewPct1.py si es un clone
channel_enabled = channeltools.is_enabled(channel)
channel_enabled = channeltools.is_enabled(serie.channel)
if channel_enabled:
heading = 'Actualizando videoteca....'
heading = config.get_localized_string(60389)
p_dialog.update(int(math.ceil((i + 1) * t)), heading, "%s: %s" % (serie.contentSerieName,
serie.channel.capitalize()))
try:
pathchannels = filetools.join(config.get_runtime_path(), "channels", serie.channel + '.py')
logger.info("Cargando canal: " + pathchannels + " " +
serie.channel)
logger.debug(serie)
if serie.library_filter_show:
serie.show = serie.library_filter_show.get(channel, serie.contentSerieName)
serie.show = serie.library_filter_show.get(serie.channel, serie.contentSerieName)
obj = imp.load_source(serie.channel, pathchannels)
itemlist = obj.episodios(serie)
serie.channel = channel #Restauramos el valor incial del clone de NewPct1
try:
if int(overwrite) == 3:
@@ -91,8 +90,8 @@ def check_for_update(overwrite=True):
if config.get_setting("update", "videolibrary") != 0 or overwrite:
config.set_setting("updatelibrary_last_check", hoy.strftime('%Y-%m-%d'), "videolibrary")
heading = 'Actualizando videoteca....'
p_dialog = platformtools.dialog_progress_bg('alfa', heading)
heading = config.get_localized_string(60389)
p_dialog = platformtools.dialog_progress_bg(config.get_localized_string(20000), heading)
p_dialog.update(0, '')
show_list = []