s.to autoplay

Autoplay für SerienStream.to

< Feedback on s.to autoplay

Review: Good - script works

§
Posted: 12-12-2020
Edited: 12-12-2020

// ==UserScript==
// @name bs.to autoplay
// @namespace http://tampermonkey.net/
// @version 2.5.1 (10.12.20)
// @description auto play. sit back and relax.
// @author xZaheer, ipgroup2010
// @match https://bs.to/*
// @match https://*.vivo.sx/*
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_deleteValue
// @grant GM_openInTab
// @grant window.close
// @require https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js
// @license GPL
// ==/UserScript==

class VivoHandler {
constructor() {
this.episodeHandler = new EpisodeHandler();
this.currentEpisode = this.episodeHandler.getCurrent();
this.nextEpisode = this.episodeHandler.getNext();
this.prevEpisode = this.episodeHandler.getPrev();
this.skipTime = this.episodeHandler.getCurrentSkip();

if(window.location.href.includes("vivo.sx")) {
this.initEvents();
}
}

initEvents() {
if(window.location.href.includes("https://vivo.sx")) {
this.play();
} else {
let waitForElem = setInterval(() => {
let videoElem = document.querySelector("video");
if(videoElem) {
clearTimeout(waitForElem);
GM_setValue("playing", true);
this.resize();
this.onEnd();
this.resume();
this.showControls();
this.trackWatchedState();
}
}, 50);
}
}

play() {
// code by https://greasyfork.org/de/scripts/28779-zu-vivo-video-navigieren
// Thank you!
var source = document.getElementsByTagName('body')[0].innerHTML;
if (source != null) {
source = source.replace(/(?:.|\n)+Core\.InitializeStream\s*\(\s*\{[^)}]*source\s*:\s*'(.*?)'(?:.|\n)+/, "$1");
var toNormalize = decodeURIComponent(source);
var url = ""
for (var i = 0; i < toNormalize.length; i++) {
var c = toNormalize.charAt(i);
if (c != ' ') {
var t = (function (c) { return c.charCodeAt == null ? c : c.charCodeAt(0); })(c) + '/'.charCodeAt(0);
if (126 < t) {
t -= 94;
}
url += String.fromCharCode(t);
}
}
if (!url.toLowerCase().startsWith("http")) {
alert("Vivo-Script Defect!");
return;
}
}
GM_setValue("playing", true);
window.location.href = url;
}

showControls() {
//document.body.style.position = "relative";
let nextButton = document.createElement("button");
let prevButton = document.createElement("button");
nextButton.style.visibility = "hidden";
prevButton.style.visibility = "hidden";;
nextButton.innerHTML = "Nächste Episode";
prevButton.innerHTML = "Vorherige Episode";
nextButton.style.position = "absolute";
prevButton.style.position = "absolute";
nextButton.addEventListener("click", () => {
this.episodeHandler.clean();
this.episodeHandler.setCurrent(this.nextEpisode);
window.location.href = this.nextEpisode + "#autoplay";
});
prevButton.addEventListener("click", () => {
this.episodeHandler.clean();
this.episodeHandler.setCurrent(this.prevEpiside);
window.location.href = this.prevEpisode + "#autoplay";
});
document.body.appendChild(nextButton);
document.body.appendChild(prevButton);
prevButton.style.left = "0";
nextButton.style.left = "calc(100% - "+ (nextButton.offsetWidth + 1) +"px)";
nextButton.style.top = "50%";
prevButton.style.top = "50%";
let timer = null;
document.body.addEventListener("mousemove", () => {
if(timer) {
clearTimeout(timer);
}
nextButton.style.visibility = "visible";
prevButton.style.visibility = "visible";
timer = setTimeout(() => {
nextButton.style.visibility = "hidden";
prevButton.style.visibility = "hidden";
}, 1000);
})
}

resize() {
let video = document.querySelector("video");
video.style.width = "100%";
video.style.height = "100%";
document.body.style.margin = "0px";

}

onEnd() {
let videoElem = document.querySelector("video");
videoElem.onended = () => {
let current = videoElem.currentTime;
let duration = videoElem.duration;
if (current && duration) {
this.episodeHandler.watch(this.currentEpisode, current, duration);
}
let nextEpisode = this.episodeHandler.getNext();
this.episodeHandler.clean();
this.episodeHandler.setCurrent(nextEpisode);
window.location.href = nextEpisode + "#autoplay";

}
}

trackWatchedState() {
let videoElem = document.querySelector("video");
if(videoElem && this.currentEpisode) {
videoElem.addEventListener('progress', (event) => {
let current = videoElem.currentTime;
let duration = videoElem.duration;
if (current && duration) {
this.episodeHandler.watch(this.currentEpisode, current, duration);
}
});
}
}

skip() {
let videoElem = document.querySelector("video");
videoElem.currentTime = this.skipTime;
}

resume() {
let videoElem = document.querySelector("video");
let data = this.episodeHandler.getWatched(this.currentEpisode);
if((data.current !== data.duration) && videoElem && data) {
videoElem.currentTime = data.current;
} else {
this.skip();
}
}

}

class BsHandler {
constructor() {
this.episodeHandler = new EpisodeHandler();
this.buttonElem = null;
if(window.location.href.includes("bs.to")) {
this.initEvents();
}
}

initEvents() {
// handle bs.to/*
if(this.isLoggedIn()) {
}

// handle episode overview table
if(window.location.href.includes("bs.to/serie") && this.isEpisodeOverview()){
this.episodeHandler.clean();
this.initElementsEpisodeOverview();
}

// handle episode view
if(!this.isEpisodeOverview() && this.isEpisodeSelected()){
if(this.isVivoAvailable() && this.isAutoplayForEpisode()) {
this.closeOnPlay();
this.setPrevNext();
this.showAutoplayOverlay();
this.clickPlay();
} else {
this.episodeHandler.clean();
}
}
}

isAutoplayForEpisode() {
return (window.location.href.includes("#autoplay")) ? true : false;
}

setPrevNext() {
let episodes = document.querySelector("#episodes > ul");
let selectedEpisode = episodes.querySelector(".active");
let nextEpisode = episodes.querySelector("li.active + li");
let prevEpisode = selectedEpisode.previousElementSibling;
let prevUrl = (prevEpisode) ? prevEpisode.querySelector("a").href : "";
let nextUrl = (nextEpisode) ? nextEpisode.querySelector("a").href : "";
this.episodeHandler.setPrev(prevUrl);
this.episodeHandler.setNext(nextUrl);

}

showAutoplayOverlay() {
let overlayElem = document.createElement("h1");
document.querySelector("#root").style.visibility = "hidden";
document.body.style.overflow = "hidden";
document.body.style.height = "100vh";
document.querySelector("footer").style.visibility = "hidden";
overlayElem.innerHTML = "Auto Playing ..."
overlayElem.style.position = "absolute";
document.body.style.display = "flex";
document.body.style.alignItems = "center";
document.body.style.justifyContent = "center";
overlayElem.style.zIndex = "999";
document.body.appendChild(overlayElem);
}

initElementsEpisodeOverview() {
let tableElem = document.querySelectorAll("#root > section > table > tbody > tr");
let episodeRowElemToHandle = [];
tableElem.forEach(episodeRowElem => {
if(episodeRowElem.querySelector(".vivo")) {
episodeRowElemToHandle.push(episodeRowElem);
}
});
this.addSkipControl();
this.addContinueButtons(episodeRowElemToHandle);
this.addProgessBars(episodeRowElemToHandle);
}

addSkipControl() {
let seasonUrl = this.getActiveSeasonUrl();
let onChange = (event) => {
let time = parseInt(event.target.value) || 0;
this.episodeHandler.setSkipForSeason(seasonUrl, time);
};

let divElem = document.createElement("div");
let labelElem = document.createElement("label");
let inputElem = document.createElement("input");
inputElem.type = "number";
divElem.appendChild(labelElem);
labelElem.innerHTML= "Intro überspringen (in Sekunden):"
divElem.appendChild(inputElem);
let locationElem = document.querySelector("#root > section > div.selectors");

locationElem.appendChild(divElem);
inputElem.value = this.episodeHandler.getSkipForSeason(seasonUrl) || "";
inputElem.addEventListener("change", onChange);
}

getActiveSeasonUrl() {
return document.querySelector("#seasons > ul > .active > a").href;
}

addProgessBars(elements) {
elements.forEach((episodeRowElem) => {
let url = episodeRowElem.querySelector("a").href;
let data = this.episodeHandler.getWatched(url);
let percentage = data.current * 100 / data.duration;

if(percentage) {
let episodeProgressbarElem = document.createElement("meter");
episodeProgressbarElem.value = percentage;
episodeProgressbarElem.max = 100;
episodeProgressbarElem.style.width = "100%";
episodeRowElem.appendChild(episodeProgressbarElem);
}
});
}

addContinueButtons(elements) {
elements.forEach((episodeRowElem) => {
let location = episodeRowElem.querySelector("[title='vivo']").parentElement;
let buttonElem = document.createElement("a");
buttonElem.innerHTML = "AutoPlay";
buttonElem.style.cursor = "pointer";
buttonElem.addEventListener("click", () => {
let url = episodeRowElem.querySelector("a").href;
this.episodeHandler.clean();
this.episodeHandler.setCurrent(url);
window.open(url + "#autoplay");
})
location.prepend(buttonElem);
});
}

isLoggedIn() {
let logoutButtonElem = document.querySelector("#root > header > section > a:nth-child(4)");
return (logoutButtonElem) ? true : false;
}

isEpisodeOverview() {
let isSerie = window.location.href.includes("serie");
return (isSerie && !this.isEpisodeSelected());
}

isEpisodeSelected() {
let checkElem = document.querySelector("#root > section > ul.hoster-tabs.top");
return (checkElem) ? true : false;

}

isVivoAvailable() {
let vivoButton = document.querySelector("#root > section > ul.hoster-tabs.top > li > a > i.vivo");
if(!vivoButton) {
return false;
} else {
return true;
}
}

clickPlay() {
let seasonUrl = this.getActiveSeasonUrl();
let skipTime = this.episodeHandler.getSkipForSeason(seasonUrl);
this.episodeHandler.setCurrentSkip(skipTime);

// setTimeout needed because loading time of js libs
setTimeout(() => {
let playerElem = document.querySelector("section.serie .hoster-player");
let clickEvent = new Event("click");
clickEvent.which = 1;
clickEvent.pageX = 1;
clickEvent.pageY = 1;
playerElem.dispatchEvent(clickEvent);

}, 1000)
}

closeOnPlay() {
setInterval(() => {
if(GM_getValue("playing")) {
window.close();
}
}, 1000);
}
}

class EpisodeHandler {
watch(episodeUrl, current, duration) {
let data = JSON.parse(GM_getValue(episodeUrl) || "{}");
data.watched = {current: current, duration: duration};
GM_setValue(episodeUrl, JSON.stringify(data));
}

getWatched(episodeUrl) {
let data = GM_getValue(episodeUrl);
if(!data) {
return false;
}

data = JSON.parse(data);
return data.watched;
}

// oursource
setSkipForSeason(seasonUrl, time) {
let data = JSON.parse(GM_getValue(seasonUrl) || "{}");
data.skipTime = time;
console.log(data);
GM_setValue(seasonUrl, JSON.stringify(data));
}

getSkipForSeason(seasonUrl) {
let data = GM_getValue(seasonUrl);
if(!data) {
return false;
}

data = JSON.parse(data);
return data.skipTime;
}
//outsource end

setCurrentSkip(time) {
GM_setValue("currentSkip", time);
}

getCurrentSkip() {
return GM_getValue("currentSkip") || 0;
}

getCurrent() {
return GM_getValue("current");
}

setCurrent(episodeUrl) {
GM_setValue("current", episodeUrl);
}

getPrev() {
return GM_getValue("prev");
}

setPrev(episodeUrl) {
GM_setValue("prev", episodeUrl);
}

getNext() {
return GM_getValue("next");
}

setNext(episodeUrl) {
GM_setValue("next", episodeUrl);
}

clean() {
GM_deleteValue("current");
GM_deleteValue("next");
GM_deleteValue("prev");
GM_deleteValue("playing");
GM_deleteValue("currentSkip");

}
}

(function() {
'use strict';
let vivoHandler = new VivoHandler();
let bsHandler = new BsHandler();

})();

xZaheerAuthor
§
Posted: 12-01-2021

Vielen Dank! Hat geholfen. Bitte die aktuelle Version testen.
Hab es mal auf github gepackt https://github.com/zaheer-exe/burningseries-autoplay
Gruß Zaheer!

Post reply

Sign in to post a reply.