Twitch - Refresh on Advert

Detects placeholder ads and refreshes the page, or for FFZ users, resets the player.

目前為 2020-11-06 提交的版本,檢視 最新版本

// ==UserScript==
// @name         Twitch - Refresh on Advert
// @version      0.6
// @description  Detects placeholder ads and refreshes the page, or for FFZ users, resets the player.
// @author       CodingAndAlgorithm - videoPlayerObserver is based on code written by SimpleHacker
// @match        https://www.twitch.tv/*
// @namespace    https://gf.qytechs.cn/users/701035
// ==/UserScript==

(function() {
    'use strict';

    let awaitingCompressorRestore = false;
    let awaitingVolumeRestore = false;
    let skippedFirstMutation = false;
    let volumeHolder = 0.5;

    window.onload = function() {
        let player = getVideoPlayer();
        if(player) {
            videoPlayerObserver.observe(player, {
                childList: true,
                subtree: true
            });
        }
        logTime("Twitch - Refresh on Advert");
    }

    const videoPlayerObserver = new MutationObserver(function(mutations) {
        mutations.forEach((mutation) => {

            // Restore volume after a specific series of mutations that occur when the player is reset.
            if(awaitingVolumeRestore && mutation.removedNodes.length == 1)
            {
                if(mutation.target.className == "tw-absolute tw-bottom-0 tw-left-0 tw-right-0 tw-top-0 video-player__overlay"
                && mutation.previousSibling.className == "tw-absolute tw-bottom-0 tw-left-0 tw-right-0 tw-top-0")
                {
                    if(skippedFirstMutation)
                    {
                        restoreVolume();
                    }
                    else
                    {
                        skippedFirstMutation = true;
                    }
                    return;
                }
            }

            // Wait for the compressor warning message to be removed before restoring.
            if(awaitingCompressorRestore && mutation.removedNodes.length == 1)
            {
                var targetNode = mutation.removedNodes[0];
                if(targetNode.nodeType == Node.TEXT_NODE)
                {
                    if(targetNode.textContent == "Audio Compressor cannot be enabled when viewing Clips.")
                    {
                        restoreCompressorState();
                        return;
                    }
                }
            }

            // Listen for adverts
            mutation.addedNodes.forEach((node) => {
                if (node.nodeType === Node.ELEMENT_NODE)
                {
                    let adBanner = node.querySelector('[data-test-selector="ad-banner-default-text"]');
                    if (adBanner)
                    {
                        if (getFFZResetButton())
                        {
                            logTime("-------------/nADVERT DETECTED/n-------------")
                            // Hold our audio settings
                            // Player.volume has already been modified at this point, take the value from the volume slider instead.
                            volumeHolder = getVolumeSlider().value;
                            // Reset player
                            var dblClickEvent = document.createEvent ('MouseEvents');
                            dblClickEvent.initEvent ('dblclick', true, true);
                            getFFZResetButton().dispatchEvent(dblClickEvent);
                            awaitingCompressorRestore = isFFZCompressorActive();
                            awaitingVolumeRestore = true;
                            skippedFirstMutation = false;
                        }
                        else
                        {
                            window.location.reload();
                        }
                    }
                }
            });
        });
    });

    function restoreVolume()
    {
        // Restore player volume & slider position
        getVideo().volume = volumeHolder;
        getVolumeSlider().value = volumeHolder;
        awaitingVolumeRestore = false;
        console.log("Restored Volume: " + Math.round(volumeHolder * 100) + "%");
    }

    function restoreCompressorState()
    {
        getFFZCompressorButton().click();
        awaitingCompressorRestore = false;
        console.log("Restored Compressor");
    }


    function logTime(message)
    {
        console.log(new Date().toLocaleTimeString() + ": "+ message);
    }

    // TODO: Add lazy loading for getElement functions.
    function getFFZCompressorButton() {
        return document.querySelector('[data-a-target="ffz-player-comp-button"]');
    }

    function getFFZResetButton() {
        return document.querySelector('[data-a-target="ffz-player-reset-button"]');
    }

    function getVideoPlayer() {
        return document.querySelector('[data-a-target="video-player"]');
    }

    function getVideo() {
        return document.querySelector('video');
    }

    function getVolumeSlider() {
        return document.querySelector('[data-a-target="player-volume-slider"]');
    }

    function isFFZCompressorActive() {
        return document.getElementsByClassName("ffz-player-icon ffz-i-comp-on")[0] != null;
    }

})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址