Auto Next

Busca los reproductores compatibles en el listado, los selecciona y maximiza. También redirige al siguiente episodio de manera automática.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(У мене вже є менеджер скриптів, дайте мені встановити його!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         Auto Next
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  Busca los reproductores compatibles en el listado, los selecciona y maximiza. También redirige al siguiente episodio de manera automática.
// @author       Chomusuke
// @license      MIT
// @match        https://serieskao.top/*
// @match        https://xupalace.org/*
// @match        https://hlsflast.com/*
// @match        https://vidhidefast.com/*
// @match        https://dood.work/*
// @match        https://kllamrd.org/*
// @match        https://sandratableother.com/*
// @match        https://waaw.to/*
// @grant        none
// ==/UserScript==

// REORGANIZAR A GUSTO
const reproductores = ['streamwish', 'filelions', 'doodstream', 'embedsito', 'voe', 'waaw']
// streamwish, filelions, doodstream, stape, vox, waav
const timeRemainToNext = 15 //tiempo restante del video para que inicie redirección

// USE F11 para tenerlo en pantalla completa siempre
// NO TOCAR---------------------------------------------------------------------------------
const sudomains = {
    'streamwish':'https://hlsflast.com',
    'filelions':'https://vidhidefast.com',
    'doodstream':'https://dood.work',
    'embedsito':'https://kllamrd.org',
    'voe':'https://sandratableother.com',
    'waaw':'https://waaw.to',
}
const videoListURL = 'https://xupalace.org'
const mainURL = 'https://serieskao.top'
const timeout = 5500; // Límite de tiempo en milisegundos

const waitForElements = (selector) => {
    return new Promise((resolve, reject) => {
        const timeout = 5000; // Límite de tiempo en milisegundos
        const startTime = Date.now();
        const interval = setInterval(() => {
            const elements = document.querySelectorAll(selector);
            if (elements.length > 0) {
                clearInterval(interval);
                resolve(elements);
            } else if (Date.now() - startTime > timeout) {
                clearInterval(interval);
                reject(new Error(`Timeout: No se encontraron elementos para el selector "${selector}" dentro de 5 segundos.`));
            }
        }, 100);
    });
};

const waitForElement = (selector) => {
    return new Promise((resolve, reject) => {
        const timeout = 5000; // Límite de tiempo en milisegundos
        const startTime = Date.now();
        const interval = setInterval(() => {
            const element = document.querySelector(selector);
            if (element) {
                clearInterval(interval);
                resolve(element);
            } else if (Date.now() - startTime > timeout) {
                clearInterval(interval);
                reject(new Error(`Timeout: No se encontró el elemento para el selector "${selector}" dentro de 5 segundos.`));
            }
        }, 100);
    });
};


(function () {
    'use strict';
    //para el principal
    if (window.self !== window.top || !window.location.href.startsWith(mainURL)) return;
    const capituloSigLink = Array.from(document.querySelectorAll('a'))
    .find(link => link.textContent.includes('Capitulo Siguiente'));
    let curIndex = 0;
    let curPlayer = reproductores[curIndex];
    // Escuchar mensajes de iframes
    window.addEventListener('message', (event) => {
        // Asegúrar origen del mensaje
        console.log(event)
        if (event.origin.startsWith(sudomains[curPlayer]) || event.origin.startsWith(videoListURL)) {
            if (capituloSigLink && event.data === 'next'){
                window.location.href = capituloSigLink.href;
            }
            if (event.data === 'full-size'){
                fullscreen()
            }
            if (event.data === 'fail'){
                curIndex = curIndex < reproductores.length -1 ? curIndex +1 : -1;
                if (curIndex < 0){
                    alert("No hay reproductores disponibles")
                    return
                }
                curPlayer = reproductores[curIndex];
                const iframe = document.querySelector('iframe');
                if (iframe) {
                    iframe.src = iframe.src; // Recarga el iframe
                }
            }
            if (event.data === 'requestCurPlayer'){
                event.source.postMessage({ curPlayer: curPlayer }, event.origin);
            }
        }
    });

    const fullscreen = () => {
        const frame = document.querySelector('iframe');
        if (!frame) return;
        if (frame.style.position ==='fixed'){
            frame.style.position = 'relative';
            frame.style.zIndex = '300';
        }else{
            frame.style.position = 'fixed';
            frame.style.zIndex = '10000';
        }
    }
    window.addEventListener('load', fullscreen);
})();

(function () {
    'use strict';
    // Verifica que se ejecute en la lista de videos
    if (window.self === window.top ||
        !window.location.href.startsWith(videoListURL)||
        !document.referrer.startsWith(mainURL)) return;
    // Solicitar la variable curSelection desde el root
    window.top.postMessage("requestCurPlayer", mainURL);
    window.addEventListener('message', (event) => {
        if (event.origin === mainURL) {
            if (event.data.curPlayer) {
                const curPlayer = event.data.curPlayer;
                const button = document.createElement('button');
                const searchAndClick = async () => {
                    try{
                        console.log(`Buscando el primer <li> con ${curPlayer}...`);
                        const liElements = await waitForElements(`li[onclick*="${curPlayer}"]`);
                        if (liElements.length > 0) {
                            const firstLi = liElements[0];
                            const onclickValue = firstLi.getAttribute('onclick');
                            const urlMatch = onclickValue.match(/'([^']+)'/);
                            // Simular el clic en el primer elemento <li>
                            firstLi.click();
                        } else {
                            console.error(`No se encontró ningún elemento <li> con "${curPlayer}" en este iframe.`);
                        }
                    }catch(error){
                        console.error('Error:',error.message);
                        window.top.postMessage("fail", mainURL);
                    }
                };
                button.addEventListener('click', searchAndClick);
                button.click()
            }
        }
    });
})();


(function () {
    'use strict';
    // Ejecutar dentro del iframe del reproductor
    if (window.self === window.top ||
        !document.referrer.startsWith(videoListURL)) return;
        // Variable global para asegurarse de que solo haya una instancia del botón
    let redirectButtonInstance = null;
    // Función que muestra el botón con la cuenta regresiva y redirige al hacer clic o cuando termina el tiempo
    function showRedirectButton() {
        // Si ya hay un botón, no hacemos nada
        if (redirectButtonInstance) return;

        // Crear el contenedor del botón
        const buttonContainer = document.createElement('div');
        buttonContainer.style.position = 'fixed';
        buttonContainer.style.top = '10px';
        buttonContainer.style.right = '10px';
        buttonContainer.style.zIndex = '999999';

        // Crear el botón de "Siguiente Video"
        const button = document.createElement('button');
        button.textContent = 'Siguiente video en 5 segundos';
        button.style.padding = '10px 15px';
        button.style.backgroundColor = '#007bff';
        button.style.color = '#fff';
        button.style.border = 'none';
        button.style.borderRadius = '5px';
        button.style.cursor = 'pointer';

        // Crear el botón de cancelación "X"
        const cancelButton = document.createElement('button');
        cancelButton.textContent = 'X';
        cancelButton.style.padding = '10px 15px';
        cancelButton.style.backgroundColor = '#ff0000';
        cancelButton.style.color = '#fff';
        cancelButton.style.border = 'none';
        cancelButton.style.borderRadius = '50%';
        cancelButton.style.cursor = 'pointer';
        cancelButton.style.marginLeft = '10px';

        // Función que actualiza el texto de cuenta regresiva en el botón
        let countdown = 5;
        const updateButtonText = () => {
            button.textContent = `Siguiente video en ${countdown} segundos`;
            if (countdown === 0) {
                window.top.postMessage('next', mainURL);
            }
            countdown--;
        };

        // Llama a la función de actualización cada segundo
        const intervalId = setInterval(updateButtonText, 1000);

        // Función para cancelar la redirección si se hace clic en "X"
        cancelButton.addEventListener('click', () => {
            clearInterval(intervalId); // Detener la cuenta regresiva
            button.textContent = 'Redirección cancelada';
            button.disabled = true; // Deshabilitar el botón
            cancelButton.disabled = true; // Deshabilitar el botón "X"
        });

        // Función para redirigir al hacer clic en el botón
        button.addEventListener('click', () => {
            clearInterval(intervalId); // Detener la cuenta regresiva si se hace clic
            window.top.postMessage('next', mainURL);
        });

        // Agregar los botones al contenedor y el contenedor al cuerpo de la página
        buttonContainer.appendChild(button);
        buttonContainer.appendChild(cancelButton);
        document.body.appendChild(buttonContainer);

        // Guardar la instancia para evitar que se cree otra
        redirectButtonInstance = buttonContainer;
    }
    // Función para convertir el tiempo en formato 'MM:SS' a segundos
    function timeToSeconds(timeStr) {
        const [minutes, seconds] = timeStr.split(':').map(num => parseInt(num, 10));
        return minutes * 60 + seconds;
    }
    // Función que verifica el tiempo y llama a la función si se cumple la condición
    function checkTime() {
        // Obtén el tiempo del div con clase "jw-text-elapsed"
        const elapsedElement = document.querySelector('.jw-icon.jw-icon-inline.jw-text.jw-reset.jw-text-elapsed')||
              document.querySelector('.plyr__controls__item.plyr__time--current.plyr__time');

        const elapsedTime = elapsedElement ? elapsedElement.textContent.trim() : '00:00';

        // Obtén el tiempo del div con clase "jw-text-duration"
        const durationElement = document.querySelector('.jw-icon.jw-icon-inline.jw-text.jw-reset.jw-text-duration')||
              document.querySelector('.plyr__controls__item.plyr__time--duration.plyr__time')||
              document.querySelector('.vjs-remaining-time-display');
        const durationTime = durationElement && durationElement.textContent.trim()!=='0:00' ? durationElement.textContent.trim() : '10:00';
        // Convierte ambos tiempos a segundos
        const elapsedTimeSeconds = timeToSeconds(elapsedTime);
        const durationTimeSeconds = timeToSeconds(durationTime);

        // Si el tiempo del primer div (elapsed) es igual o mayor al tiempo del segundo div (duration) menos 15 segundos
        if (elapsedTimeSeconds >= (durationTimeSeconds - 20)) {
            showRedirectButton();
        }
    }
    // Solicitar la variable curSelection desde el root
    window.top.postMessage("requestCurPlayer", mainURL);
    window.addEventListener('message', (event) => {
        if (event.origin === mainURL) {
            if (event.data.curPlayer) {
                const curPlayer = event.data.curPlayer;
                if (!window.location.href.startsWith(sudomains[curPlayer])) return;
                const button = document.createElement('button');

                const performActions = async () => {
                    try{
                        await waitForElement('video');
                        const videoElement = document.querySelector('video');
                        if (videoElement) {
                            videoElement.click();
                        } else {
                            console.warn('No se encontró el elemento <video>.');
                        }
                    }catch(error){
                        console.error('Error: ',error.message);
                        window.top.postMessage("fail", mainURL);
                    }
                };
                button.addEventListener('click', performActions);
                button.click()
                const escButton = document.createElement('button');
                escButton.style.position = 'fixed'
                escButton.style.top = '40px';
                escButton.style.right = '10px';
                escButton.style.zIndex = '999999';
                escButton.style.padding = '5px 10px';
                escButton.style.backgroundColor = 'whitesmoke';
                escButton.style.color = '#fff';
                escButton.style.border = 'none';
                escButton.style.borderRadius = '5px';
                escButton.style.cursor = 'pointer';
                escButton.textContent = '❌';
                escButton.addEventListener('click', () => {
                    window.top.postMessage('full-size', mainURL);
                });
                document.body.appendChild(escButton);
                // Llama a la función `checkTime` cada segundo para verificar el tiempo continuamente
                setInterval(checkTime, 1000);
            }
        }
    });
})();