Greasy Fork

Greasy Fork is available in English.

s.to autoplay

Autoplay für SerienStream.to

当前为 2024-09-20 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         s.to autoplay
// @namespace    https://github.com/zaheer-exe
// @version      8.3
// @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==

////////// LISTER ////////////////////////////////////////////////////////////////
const sToHosts = ['s.to', 'aniworld.to', 'serienstream.to'];
if (sToHosts.includes(new URL(window.location.href).hostname)) {
    let isAutoPlayed = false;

    function nextEpisode() {
        const currentLang = document.querySelector("img.selectedLanguage").dataset.langKey;
        console.log("S: current lang ", currentLang);
        const episodeMenuCurrentELem = document.querySelector('li a.active[href*="episode"]');
        const nextEpisodeUrl = episodeMenuCurrentELem.parentElement.nextElementSibling.querySelector('a');
        var xmlHttp = new XMLHttpRequest();
        xmlHttp.open( "GET", nextEpisodeUrl, false );
        xmlHttp.send(null);
        let temp = document.createElement('div')
        temp.innerHTML=xmlHttp.responseText;
        let url = temp.querySelector('li[data-lang-key="' + currentLang + '"] .watchEpisode .icon.VOE').parentElement.href;
        let title = temp.querySelector(".hosterSiteTitle").innerHTML;
        document.querySelector(".inSiteWebStream iframe").src = url;
        document.querySelector(".hosterSiteTitle").innerHTML = title;
        document.querySelector(".breadCrumbMenu").innerHTML = temp.querySelector(".breadCrumbMenu").innerHTML;
        episodeMenuCurrentELem.classList.remove('active');
        nextEpisodeUrl.classList.add('active');
        episodeMenuCurrentELem.classList.remove('active');
        window.history.pushState("", "", nextEpisodeUrl.href);
        if (!isAutoPlayed) {
            disableElements();
            isAutoPlayed = true;
        }
    }

    function disableElements() {
        const style = document.createElement('style');
        style.textContent = `
        .changeLanguage, li[data-link-target] {
            opacity: 0.3;
            cursor: none;
        }

        .changeLanguageBox, li[data-link-target] > .generateInlinePlayer {
            pointer-events: none;
        }

        .tooltip {
            position: absolute;
            background-color: #333; /* Dark background for contrast */
            color: #fff; /* White text for contrast */
            padding: 10px; /* Padding for better appearance */
            border-radius: 5px; /* Rounded corners */
            font-size: 14px; /* Font size for readability */
            line-height: 1.4; /* Line height for better text readability */
            white-space: nowrap; /* Prevent text wrapping */
            display: none; /* Hidden by default */
            z-index: 9999; /* Ensure it appears above other content */
            pointer-events: none; /* Ensure it doesn't interfere with interactions */
            transform: translate(-50%, -50%); /* Center tooltip on the cursor */
        }
    `;
        document.head.appendChild(style);

        const tooltip = document.createElement('div');
        tooltip.className = 'tooltip';
        tooltip.textContent = 'Autoplay enabled. Refresh/Reload Page to change settings.';
        document.body.appendChild(tooltip);

        function updateTooltipPosition(event) {
            tooltip.style.left = `${event.pageX}px`;
            tooltip.style.top = `${event.pageY}px`;
        }

        function showTooltip(event) {
            tooltip.style.display = 'block';
            updateTooltipPosition(event);
        }

        function hideTooltip() {
            tooltip.style.display = 'none';
        }

        const elements = document.querySelectorAll('.changeLanguage, li[data-link-target]');
        elements.forEach(element => {
            element.addEventListener('mouseenter', showTooltip);
            element.addEventListener('mousemove', updateTooltipPosition);
            element.addEventListener('mouseleave', hideTooltip);
        });
    }

    function autoPlaySettings() {
        const style = document.createElement('style');
        style.textContent = `
        .autoplay-settings-container {
            border: 1px solid #3a3a3a;
            border-radius: 8px;
            margin-top: 15px;
            padding: 15px;
            background-color: #18181b;
            font-family: Arial, sans-serif;
            color: #ffffff;
            box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
        }
        .autoplay-settings-container h2 {
            margin: 0 0 15px 0;
            color: #8257e6;
            font-size: 16px;
            font-weight: bold;
        }
        .settings-row {
            display: flex;
            justify-content: space-between;
        }
        .settings-column {
            width: 48%;
        }
        .setting-group {
            margin-bottom: 10px;
        }
        .setting-group label {
            display: block;
            margin-bottom: 5px;
            font-size: 14px;
            color: #a0a0a0;
        }
        .setting-group input {
            width: 100%;
            padding: 8px;
            border: 1px solid #3a3a3a;
            border-radius: 4px;
            font-size: 14px;
            background-color: #27272a;
            color: #ffffff;
            transition: border-color 0.3s, box-shadow 0.3s;
        }
        .setting-group input:focus {
            outline: none;
            border-color: #8257e6;
            box-shadow: 0 0 5px rgba(130, 87, 230, 0.5);
        }
        .setting-group input::placeholder {
            color: #6b7280;
        }
    `;
    document.head.appendChild(style);

    const container = document.createElement("div");
    container.classList.add("autoplay-settings-container");
    container.innerHTML = `
        <h2>AutoPlay Settings</h2>
        <div class="settings-row">
            <div class="settings-column">
                <div class="setting-group">
                    <label for="skip-intro">Skip intro (seconds)</label>
                    <input id="skip-intro" type="number" min="0" placeholder="e.g., 30">
                </div>
                <div class="setting-group">
                    <label for="skip-outro">Skip outro (seconds)</label>
                    <input id="skip-outro" type="number" min="0" placeholder="e.g., 60">
                </div>
            </div>
            <div class="settings-column">
                <div class="setting-group">
                    <label for="still-here">"Are you still watching?" popup (minutes of inactivity)</label>
                    <input id="still-here" type="number" min="0" placeholder="e.g., 120">
                </div>
            </div>
        </div>
    `;
    document.querySelector(".hosterSiteDirectNav").appendChild(container);

    ['skip-intro', 'skip-outro', 'still-here'].forEach(id => {
        document.getElementById(id).addEventListener("change", (e) => {
            const value = e.target.value;
            console.log(`${e.target.id} changed to: ${value}`);
            // Here you can add logic to save the settings or trigger other actions
        });
    });
}

    //autoPlaySettings();

    function showTooltip(e) {
        const tooltip = document.getElementById('autoplay-tooltip');
        tooltip.style.display = 'block';
        tooltip.style.left = e.pageX + 10 + 'px';
        tooltip.style.top = e.pageY + 10 + 'px';
    }

    function hideTooltip() {
        const tooltip = document.getElementById('autoplay-tooltip');
        tooltip.style.display = 'none';
    }

    window.addEventListener("message", (event) => {
        if(typeof event.data === "string" && event.data.startsWith("autoplay")) {
            const parsed = event.data.split("$");
            console.log("event", parsed);
            switch (parsed[1]) {
                case "url": {
                    console.log("S: url");
                    let streamIframe = document.querySelector(".inSiteWebStream iframe");
                    if (streamIframe.src.includes("/redirect")) {
                        document.querySelector(".inSiteWebStream iframe").src = parsed[2];
                    }
                    break;
                }
                case "end": {
                    console.log("S: ended");
                    nextEpisode();
                }
            }
        }
    }, false);
    document.querySelector(".inSiteWebStream iframe").allow="autoplay; fullscreen; picture-in-picture; xr-spatial-tracking; clipboard-write";
}

////////// HOSTER ////////////////////////////////////////////////////////////////
let checkIfVoe = document.querySelector("head > meta[name='og:sitename']");
if (checkIfVoe && checkIfVoe.content == "VOE: Video Hosting Platform & Online Cloud Storage") {

    window.parent.postMessage("autoplay$url$" + window.location.href, '*');
    document.querySelector("video").play();

    let ended = false;
    document.querySelector("video").addEventListener("ended", () => {
        if (!ended) {
            console.log("VEO: ended");
            window.parent.postMessage("autoplay$end", "*");
            ended = true;
        }
    });

    // sometimes the "ended" event does not fire.. idk why. needs a workaround:
    window.setInterval(() => {
        let video = document.querySelector("video");
        if (video.currentTime + 0.5 >= video.duration && !ended) {
            console.log("VEO: ended workaround");
            window.parent.postMessage("autoplay$end", "*");
            ended = true;
        }
    }, 500);
}