s.to autoplay

Autoplay für SerienStream.to

// ==UserScript==
// @name         s.to autoplay
// @namespace    https://github.com/zaheer-exe
// @version      7
// @description  Autoplay für SerienStream.to
// @author       zaheer-exe
// @match        https://s.to/*
// @match        https://serienstream.to/*
// @match        https://aniworld.to/*
// @match        https://voe.sx/*
// @match        *://*/*
// @grant        GM_xmlhttpRequest
// @icon         https://www.google.com/s2/favicons?sz=64&domain=s.to
// @license      Apache License
// @grant        none
// ==/UserScript==



window.addEventListener('load', function() {
    main();
}, false);

function getNextEpisodeUrl(target)
{
    var xmlHttp = new XMLHttpRequest();
    xmlHttp.open( "GET", target, false ); // false for synchronous requesy
    xmlHttp.send(null);
    let temp = document.createElement('div')
    temp.innerHTML=xmlHttp.responseText;
    let tempElem = temp.querySelector('.watchEpisode .icon.VOE')
    let url = tempElem.parentElement.href
    console.log("next url", url);
    let title = temp.querySelector(".hosterSiteTitle").innerHTML;
    return {url: url, title: title};
}

async function main() {
    const sToHosts = ['s.to', 'aniworld.to', 'serienstream.to'];

    const currentHost = (() => {
        const url = new URL(document.location);
        return url.host;
    })();

    // code by  https://stackoverflow.com/a/61511955/14589345
    function waitForElem(selector) {
        return new Promise(resolve => {
            if (document.querySelector(selector)) {
                return resolve(document.querySelector(selector));
            }
            const observer = new MutationObserver(mutations => {
                if (document.querySelector(selector)) {
                    resolve(document.querySelector(selector));
                    observer.disconnect();
                }
            });
            observer.observe(document.body, {
                childList: true,
                subtree: true
            });
        });
    }

    // s.to
    if (sToHosts.includes(currentHost)) {
        console.log('running for ' + currentHost);

        function nextEpisode() {
            const episodeMenuCurrentELem = document.querySelector('li a.active[href*="episode"]');
            episodeMenuCurrentELem.classList.remove('active');
            const nextEpisodeUrl = episodeMenuCurrentELem.parentElement.nextElementSibling.querySelector('a');
            if (nextEpisodeUrl) {
                nextEpisodeUrl.classList.add('active');
                window.history.pushState("", "", nextEpisodeUrl.href);
                console.log(iframe);
                let data = getNextEpisodeUrl(nextEpisodeUrl.href);
                console.log("next url final", data.url);
                iframe.src = data.url;
                document.querySelector(".hosterSiteTitle").innerHTML = data.title;
            }
        }

        function prevEpisode() {
            const episodeMenuCurrentELem = document.querySelector('li a.active[href*="episode"]');
            const prevEpisodeUrl = episodeMenuCurrentELem.parentElement.previousElementSibling.querySelector('a');
            if (prevEpisodeUrl) {
                episodeMenuCurrentELem.classList.remove('active');
                prevEpisodeUrl.classList.add('active');
                window.history.pushState("", "", prevEpisodeUrl.href);
                iframe.src = prevEpisodeUrl.href;
            }
        }

        waitForElem('.seasonEpisodeTitle').then(() => {
            const watchData = JSON.parse((localStorage.getItem('watchData') ?? '{}'));
            function addProgressBar(elem) {
                const episodeUrl = new URL(elem.querySelector('a').href);
                if (Object.keys(watchData).includes(episodeUrl.href)) {
                    elem.style = 'position: relative; z-index: 5;';
                    const watchDataForEpisode = watchData[episodeUrl.href];
                    const progressBarElem = document.createElement('progress');
                    progressBarElem.value = watchDataForEpisode.currentTime;
                    progressBarElem.max = watchDataForEpisode.duration;
                    progressBarElem.style = 'position: absolute; width: 100%; height: 100%; appearance: none; top: 0; z-index: -1; opacity: 0.5;';
                    elem.appendChild(progressBarElem);
                }
            }
            const allElements = document.querySelectorAll('.seasonEpisodeTitle');
            allElements.forEach(addProgressBar)
        });
        const iframe = await waitForElem('.inSiteWebStream iframe[src]');
        iframe.allow="autoplay; fullscreen; picture-in-picture; xr-spatial-tracking; clipboard-write";


        window.addEventListener('message', (event) => {
            const sourceUrl = new URL(event.origin);
                const data = JSON.parse(event.data);
                if (data.type == 'watchData') {
                    let watchData = JSON.parse((localStorage.getItem('watchData') ?? '{}'));
                    watchData[window.location] = data;
                    localStorage.setItem('watchData', JSON.stringify(watchData));
                    if (iframe.src.includes('redirect')) {
                        iframe.src = data.url;
                    }
                    if (data.duration > 0 && data.duration == data.currentTime) {
                        nextEpisode();
                    }
                }
                if (data.type == 'action') {
                    if (data.action == 'next') {
                        nextEpisode();
                    }
                    if (data.action == 'prev') {
                        prevEpisode();
                    }
                }
        }, false);
    }

    let checkIfVoe = document.querySelector("head > meta[name='og:sitename']");
    if (checkIfVoe.content == "VOE: Video Hosting Platform & Online Cloud Storage") {
        console.log('running for ' + currentHost);
        const video = await waitForElem('video');
        console.log(video);
        video.setAttribute('autoplay', '');
        video.play();
        const lastTime = JSON.parse((localStorage.getItem('lastTime') ?? '{}'));
        const videoData = {
            url: window.location.href,
            duration: video.duration,
            currentTime: 0,
            type: 'watchData'
        }

        window.parent.postMessage(JSON.stringify(videoData), '*');

        video.addEventListener('progress', (event) => {
            if(video.currentTime + 20 >= video.duration) {
                console.log("ENDED");

                videoData.currentTime = video.duration;
                videoData.duration = video.duration;
                window.parent.postMessage(JSON.stringify(videoData), '*');
            }

            console.log("progress", event);
            videoData.currentTime = video.currentTime;
            videoData.duration = video.duration;
            window.parent.postMessage(JSON.stringify(videoData), '*');
            lastTime[window.location.href] = videoData.currentTime;
            localStorage.setItem('lastTime', JSON.stringify(lastTime));

        }
                              );
        video.addEventListener('ended', (event) => {
            console.log("ENDED");
            videoData.currentTime = video.currentTime;
            videoData.duration = video.duration;
            window.parent.postMessage(JSON.stringify(videoData), '*');
        });
    }

}