// ==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 // @downloadURL 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), '*'); }); } }