Greasy Fork

NBA.com - Spoiler Blocker

Enhances NBA.com by hiding video lengths and adding fictitious durations to the progress bar to prevent spoilers.

目前为 2024-04-21 提交的版本。查看 最新版本

// ==UserScript==
// @name         NBA.com - Spoiler Blocker
// @version      0.1
// @description  Enhances NBA.com by hiding video lengths and adding fictitious durations to the progress bar to prevent spoilers.
//               This script also adds custom buttons for skipping predefined intervals such as timeouts and halftimes,
//               enhancing the viewing experience. It also hides spoilers on the front page.
// @author       You
// @match        *://*.nba.com/*
// @license      MIT
// @grant        none
// @run-at       document-start
// @namespace https://greasyfork.org/users/1291378
// ==/UserScript==

(function() {
    'use strict';

    // Inject CSS to hide specific elements as soon as the page starts loading.
    // This prevents the element from being seen even momentarily.
    const css = '.MaxWidthContainer_mwc__ID5AG { display: none !important; }';
    const head = document.head || document.getElementsByTagName('head')[0];
    const style = document.createElement('style');
    style.type = 'text/css';
    if (style.styleSheet){
      // IE8 and below
      style.styleSheet.cssText = css;
    } else {
      // Other browsers
      style.appendChild(document.createTextNode(css));
    }
    head.appendChild(style);

    // Function to create and append skip buttons to the video player control bar.
    function createAndAppendButton(container, label, seconds) {
        const button = document.createElement('button');
        button.textContent = label;
        button.style.padding = '8px';
        button.style.marginLeft = '5px';
        button.style.background = '#FFF';
        button.style.color = '#000';
        button.style.border = 'none';
        button.style.cursor = 'pointer';

        // When clicked, the button adjusts the current time of the video.
        button.onclick = function() {
            const video = document.querySelector('video');
            if (video) {
                video.currentTime += seconds;
            }
        };

        container.appendChild(button);
    }

    // Generate a random maximum length between 3 and 4 hours to obscure the true length of videos.
    function getRandomMaxLength() {
        const threeHoursInSeconds = 3 * 60 * 60; // 3 hours in seconds
        const oneHourInSeconds = 60 * 60; // 1 hour in seconds
        return threeHoursInSeconds + Math.floor(Math.random() * oneHourInSeconds);
    }

    // Store the random max length so it's used consistently throughout the session.
    const standardMaxLength = getRandomMaxLength();

    // Apply the random max length to video progress bars to obscure their real length.
    function randomizeProgressBar() {
        const progressBar = document.getElementById('progress-bar');
        const rangeInput = document.querySelector('.sc-beqWaB.bpZMgR input[type="range"]');
        if (progressBar && rangeInput) {
            progressBar.max = standardMaxLength;
            rangeInput.max = standardMaxLength;
            rangeInput.setAttribute('aria-valuemax', standardMaxLength);
        }
    }

    // Function to hide elements that show video time, preventing spoilers.
    function hideTimeElements() {
        const timePattern = /\b\d{2}:\d{2}:\d{2}\b/;
        const spans = document.querySelectorAll('span');
        spans.forEach(span => {
            if (timePattern.test(span.innerText)) {
                span.style.display = 'none';
            }
        });
    }

    // Monitor for dynamic changes in the DOM to reapply the hiding functions and check for control bars to add buttons.
    const observer = new MutationObserver((mutations) => {
        mutations.forEach(mutation => {
            if (mutation.type === 'childList' || mutation.type === 'attributes') {
                hideTimeElements();
                addSkipButtonsIfControlBarExists();
            }
        });
    });

    // Ensure custom buttons are added to the video player control bar.
    function addSkipButtonsIfControlBarExists() {
        const controlBar = document.querySelector('.sc-lnAgIa.hfaRgm.controlbar');
        if (controlBar && !controlBar.dataset.skipButtonsAdded) {
            controlBar.dataset.skipButtonsAdded = 'true';

            createAndAppendButton(controlBar, 'Skip Short Timeout (30sec)', 30);
            createAndAppendButton(controlBar, 'Skip Timeout (90sec)', 90);
            createAndAppendButton(controlBar, 'Skip Free Throws (1min)', 60);
            createAndAppendButton(controlBar, 'Skip Halftime (15min)', 900);
        }
    }

    // Start the mutation observer to handle dynamic content changes.
    observer.observe(document.body, {
        attributes: true,
        childList: true,
        subtree: true
    });

    // Periodically apply randomization to the progress bar to maintain the fictitious length.
    setInterval(randomizeProgressBar, 1000);
    // Perform initial hiding of time elements and button addition.
    hideTimeElements();
    addSkipButtonsIfControlBarExists();
})();