// ==UserScript== // @name burningseries-autoplay // @namespace https://github.com/zaheer-exe/burningseries-autoplay // @version 3.2 // @description Autoplay für Burningseries // @author zaheer-exe // @match https://bs.to/* // @match https://*.vivo.sx/* // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @grant GM_openInTab // @grant window.close // @license Apache License // @downloadURL none // ==/UserScript== const debugging = false; function log(msg) { if(debugging) { console.log(msg); } } 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 }); }); } class SiteHandler { constructor() { log('SiteHandler: constructor()'); this.dataHandler = new DataHandler(); this.url = new URL(document.location.href); this.settings = this.dataHandler.getSettings(); this.registerEvents(); } registerEvents() { document.addEventListener('visibilitychange', () => { if(!document.hidden) { let url = new URL(document.location.href); this.dataHandler.setCurrentWebsite(url.host); return true } return false; }); } } class VivoHandler extends SiteHandler { constructor() { super(); this.data = this.dataHandler.getEpisodeData(this.settings.lastBsUrl); log(this.data); if(this.settings.vivoEnabled && this.isVivo()) { this.play(); } if(this.settings.vivoEnabled && this.isVivoVideo()){ this.resize(); this.trackWatchedState(); if(this.settings.autonextEnabled) { this.onEndPlayNext(); } } if(this.settings.vivoButtonsEnabled && this.isVivoVideo()){ this.loadButtons(); } if(this.settings.autoresumeEnabled) { this.resume(); } } isVivo() { log('VivoHandler: isVivo()'); const vivoDomains = ['vivo.sx']; const currentUrl = new URL(document.location.href); log(currentUrl); return vivoDomains.includes(currentUrl.host); } isVivoVideo() { log('VivoHandler: isVivoVideo()'); if(document.querySelector('video') && window.location.href.includes('vivo') && window.location.href.includes('--')) { return true; } return false; } loadButtons() { if(this.data.prev) { let prevButton = document.createElement('button'); prevButton.style.position = 'absolute'; prevButton.style.left = '0'; prevButton.innerText = 'Vorherige Folge'; prevButton.style.top = '50%'; prevButton.style.visibility = 'hidden'; prevButton.addEventListener('click', ()=>{ window.location.href = this.data.prev; }); prevButton.classList.add('autoplay-button'); document.body.append(prevButton); } if(this.data.next) { let nextButton = document.createElement('button'); nextButton.innerText = 'Nächste Folge'; nextButton.style.position = 'absolute'; nextButton.style.top = '50%'; nextButton.style.visibility = 'hidden'; document.body.append(nextButton); nextButton.style.left = 'calc(100% - ' + nextButton.offsetWidth + 'px)'; nextButton.addEventListener('click', ()=>{ window.location.href = this.data.next; }); nextButton.classList.add('autoplay-button'); } let timer = null; document.body.addEventListener('mousemove', () => { if(timer) { clearTimeout(timer); } document.querySelectorAll('.autoplay-button').forEach(button => { button.style.visibility = 'visible'; }); timer = setTimeout(() => { document.querySelectorAll('.autoplay-button').forEach(button => { button.style.visibility = 'hidden'; }); }, 1000); }); } trackWatchedState() { log('VivoHandler: trackWatchedState()'); let videoElem = document.querySelector('video'); if (videoElem) { videoElem.addEventListener('progress', (event) => { let current = videoElem.currentTime; let duration = videoElem.duration; if (current && duration) { this.data.currentTime = current; this.data.maxTime = duration; this.dataHandler.setEpisodeData(this.settings.lastBsUrl, this.data); } }); } } onEndPlayNext() { log('VivoHandler: onEndPlayNext()'); let videoElem = document.querySelector("video"); videoElem.onended = () => { let current = videoElem.currentTime; let duration = videoElem.duration; if (current && duration) { this.data.currentTime = current; this.data.maxTime = duration; this.dataHandler.setEpisodeData(this.settings.lastBsUrl, this.data); } let nextEpisode = this.data.next; window.location.href = nextEpisode; } } resize() { let video = document.querySelector("video"); video.style.width = "100%"; video.style.height = "100%"; document.body.style.margin = "0px"; } play() { log('VivoHandler: 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; } } window.location.href = url; } resume() { let videoElem = document.querySelector('video'); if ((this.data.currentTime !== this.data.maxTime) && videoElem) { videoElem.currentTime = this.data.currentTime; } } } class BsHandler extends SiteHandler { constructor() { super(); if(this.isBs()) { this.dataHandler.setCurrentWebsite('bs'); this.settings = this.dataHandler.getSettings(); this.loadMenu(); } if(this.dataHandler.getSettings().bsEnabled) { this.main(); } } isBs() { log('BsHandler: isBs()'); const bsDomains = ['bs.to', 'burningseries.co']; const currentUrl = new URL(document.location.href); log(currentUrl); return bsDomains.includes(currentUrl.host); } loadMenu() { log('BsHandler: loadMenu()'); let css = document.createElement('style'); let lastText = this.settings.lastVivoUrl ? `