Greasy Fork

Greasy Fork is available in English.

burningseries-autoplay

Autoplay für Burningseries

当前为 2021-01-14 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         burningseries-autoplay
// @namespace    https://github.com/zaheer-exe/burningseries-autoplay
// @version      3.3
// @description  Autoplay für Burningseries
// @author       zaheer-exe
// @match        https://bs.to/*
// @match        https://*.vivo.sx/*
// @match        https://burningseries.co/*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_deleteValue
// @grant        GM_openInTab
// @grant        window.close
// @license      Apache License
// ==/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 http://greasyfork.icu/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 ? `<h3><span>Weiterschauen: </span><a target="_blank" href="`+ this.settings.lastVivoUrl + `">` + this.settings.lastName + `</a></h3>` : '';
        css.innerHTML =
            `
            .bs-autoplay-menu {
                color: white;
                position: absolute;
                top: 0;
                z-index: 999;
                background: rgba(0,0,0,0.6);
                margin: 10px;
                padding: 5px;
            }
           .bs-autoplay-menu .cb {
               display: inline-block;
           }
           .bs-autoplay-menu a {
               color: red;
           }
        `
        let html = document.createElement('div');
        html.innerHTML =
            `
            <div class="bs-autoplay-menu">
                <h1 class="title">Autoplay</h1>
                `+lastText+`
                <div>
                    <div>
                        <span>autoplay bs: </span>
                        <input type="checkbox" class="cb toggle-button-bs">
                    </div>
                    <div>
                        <span>autoplay vivo: </span>
                        <input type="checkbox" class="cb toggle-button-vivo">
                    </div>
                    <div>
                        <span>automatisch nächste Folge abspielen: </span>
                        <input type="checkbox" class="cb toggle-button-autonext">
                    </div>
                    <div>
                        <span>fortsetzen wo du aufgehört hast: </span>
                        <input type="checkbox" class="cb toggle-button-autoresume">
                    </div>
                    <div>
                        <span>Buttons im Video anzeigen: </span>
                        <input type="checkbox" class="cb toggle-button-vivobuttons">
                    </div>
                </div>
            </div>
        `
        html.querySelector('.toggle-button-bs').checked = this.settings.bsEnabled;
        html.querySelector('.toggle-button-bs').addEventListener('click', () => {
            this.settings.bsEnabled = !this.settings.bsEnabled;
            this.dataHandler.setSettings(this.settings);
            location.reload();
        });
        html.querySelector('.toggle-button-vivo').checked = this.settings.vivoEnabled;
        html.querySelector('.toggle-button-vivo').addEventListener('click', () => {
            this.settings.vivoEnabled = !this.settings.vivoEnabled;
            this.dataHandler.setSettings(this.settings);
            location.reload();
        });
        html.querySelector('.toggle-button-autonext').checked = this.settings.autonextEnabled;
        html.querySelector('.toggle-button-autonext').addEventListener('click', () => {
            this.settings.autonextEnabled = !this.settings.autonextEnabled;
            this.dataHandler.setSettings(this.settings);
            location.reload();
        });
        html.querySelector('.toggle-button-autoresume').checked = this.settings.autoresumeEnabled;
        html.querySelector('.toggle-button-autoresume').addEventListener('click', () => {
            this.settings.autoresumeEnabled = !this.settings.autoresumeEnabled;
            this.dataHandler.setSettings(this.settings);
            location.reload();
        });
        html.querySelector('.toggle-button-vivobuttons').checked = this.settings.vivoButtonsEnabled;
        html.querySelector('.toggle-button-vivobuttons').addEventListener('click', () => {
            this.settings.vivoButtonsEnabled = !this.settings.vivoButtonsEnabled;
            this.dataHandler.setSettings(this.settings);
            location.reload();
        });
        html.querySelector('.bs-autoplay-menu').append()
        document.body.append(css);
        document.body.append(html);
    }

    loadAutoplayButtons() {
        let episodeRows = document.querySelectorAll('.episodes tr');
        episodeRows.forEach((episode) => {
            let target = episode.querySelector('[title=\'vivo\']');
            if (!target) {
                return;
            }
            target = target.parentElement;
            let buttonElem = document.createElement('button');
            buttonElem.innerHTML = 'Auto Play';
            buttonElem.addEventListener('click', () => {
                let url = episode.querySelector('a').href;
                window.open(url + "#autoplay");
            })
            target.prepend(buttonElem);
        })
    }

    setPrevAndNextEpisode() {
        let next = document.querySelector('#episodes .active').nextElementSibling;
        let prev = document.querySelector('#episodes .active').previousElementSibling;
        let data = this.dataHandler.getEpisodeData(this.url.pathname) || {};
        if(next) {
            next = next.querySelector('a').href;
        }
        if(prev) {
            prev = prev.querySelector('a').href;
        }
        console.log(data);
        data.prev = prev || false;
        data.next = next || false;
        this.dataHandler.setEpisodeData(this.url.pathname, data);
    }

    play() {
        // setTimeout needed because loading time of js libs
        setTimeout(() => {
            let playerElem = document.querySelector('section.serie .hoster-player');
            if(playerElem) {
                let clickEvent = new Event('click');
                clickEvent.which = 1;
                clickEvent.pageX = 1;
                clickEvent.pageY = 1;
                playerElem.dispatchEvent(clickEvent);
                waitForElem('.hoster-player a').then((elem) => {
                    let data = this.dataHandler.getEpisodeData(this.url.pathname) || {};
                    let url = elem.href;
                    data.vivourl = url;
                    this.settings.lastVivoUrl = url;
                    this.settings.lastBsUrl = this.url.pathname;
                    this.settings.lastName = document.querySelector('section.serie h2').innerText;
                    this.dataHandler.setSettings(this.settings);
                    this.dataHandler.setEpisodeData(this.url.pathname, data);
                    window.close();
                })
            }
        }, 1000);
    }

     addProgessBars() {
        let elements = document.querySelectorAll('.episodes tr');
        elements.forEach((episodeRowElem) => {
            let url = new URL(episodeRowElem.querySelector('a').href);
            let path = url.pathname;
            let data = this.dataHandler.getEpisodeData(path);
            let percentage = data.currentTime * 100 / data.maxTime;

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

    main() {
        this.loadAutoplayButtons();
        this.addProgessBars();
        this.setPrevAndNextEpisode();
        this.play();
    }

}

class DataHandler {
    constructor() {
        log('DataHandler: constructor()');
    }

    getCurrentWebsite() {
        log('DataHandler: getCurrentWebsite()');
        let currentWebsite = GM_getValue('currentWebsite');

        try {
            currentWebsite = JSON.parse(currentWebsite);
        } catch(e) {
            log('Datahandler: getCurrentWebsite()' + e);

            return false;
        }
        log(currentWebsite);
        return currentWebsite;
    }

    setCurrentWebsite(site) {
        log('DataHandler: setCurrentWebsite()');
        try {
            let currentWebsite = JSON.stringify(site);
            GM_setValue('currentWebsite', currentWebsite);
        } catch(e) {
            log('Datahandler: setCurrentWebsite()' + e);

            return false;
        }

        return true;
    }

    setSettings(data) {
        try {
            let d = JSON.stringify(data);
            GM_setValue('settings', d);
        } catch(e) {
            log('Datahandler: setSettings()' + e);

            return false;
        }

        return true;
    }

    getSettings() {
        log('DataHandler: getSettings()');
        let data = GM_getValue('settings') || '{}';

        try {
            data = JSON.parse(data);
        } catch(e) {
            log('Datahandler: getSettings()' + e);

            return false;
        }
        log(data);
        return data;
    }

    setEpisodeData(url, data) {
        try {
            let d = JSON.stringify(data);
            GM_setValue(url, d);
        } catch(e) {
            log('Datahandler: setEpisodeData()' + e);

            return false;
        }

        return true;
    }

    getEpisodeData(url) {
        log('DataHandler: getEpisodeData()');
        let data = GM_getValue(url) || {};

        try {
            data = JSON.parse(data);
        } catch(e) {
            log('Datahandler: getEpisodeData('+ url +')' + e);

            return false;
        }
        log(data);
        return data;
    }
}

new BsHandler();
new VivoHandler();