Greasy Fork is available in English.
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), '*');
});
}
}