Raw Text Content QR
monkey-horse-bee



// ==UserScript==
// @name         Video Replacement Script
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Replaces the largest video element with an iframe pointing to a local server.
// @author       You
// @match        *://*/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // Function to get the dimensions of an element
    function getElementDimensions(element) {
        if (!element) return { width: 0, height: 0 };
        const rect = element.getBoundingClientRect();
        return { width: rect.width, height: rect.height };
    }

    let currentIframe = null; // To keep track of the created iframe
    let currentLargestVideo = null; // To keep track of the largest video
    let stoppedMediaElements = new Set(); // To keep track of media elements that have been permanently stopped

    function applyVideoReplacementLogic() {
        const videoElements = document.querySelectorAll('video');
        let foundLargestVideo = null;
        let largestArea = 0;

        videoElements.forEach(video => {
            const dimensions = getElementDimensions(video);
            const area = dimensions.width * dimensions.height;
            if (area > largestArea) {
                largestArea = area;
                foundLargestVideo = video;
            }
        });

        // If the largest video has changed or is newly found, or if no video was found before
        if (foundLargestVideo !== currentLargestVideo) {
            // Clean up old iframe if it's not relevant anymore
            if (currentIframe && currentIframe.parentNode) {
                currentIframe.remove();
                currentIframe = null;
            }

            currentLargestVideo = foundLargestVideo;

            if (currentLargestVideo) {
                const videoDimensions = getElementDimensions(currentLargestVideo);
                const videoArea = videoDimensions.width * videoDimensions.height;
                let currentParent = currentLargestVideo.parentElement;
                let finalTargetContainer = currentLargestVideo.parentElement; // Default to immediate parent

                // Traverse up the DOM to find the ideal parent
                while (currentParent) {
                    const parentDimensions = getElementDimensions(currentParent);
                    const parentArea = parentDimensions.width * parentDimensions.height;

                    // Stop at the last parent which size is at most 2% larger than the video.
                    if (parentArea <= videoArea * 1.02) {
                        finalTargetContainer = currentParent;
                    } else {
                        // If the current parent is too large, the previous one was the largest suitable parent.
                        break;
                    }
                    if (currentParent === document.body) break; // Stop at body
                    currentParent = currentParent.parentElement;
                }

                // Ensure the finalTargetContainer has a positioning context for the absolutely positioned iframe
                const containerStyle = window.getComputedStyle(finalTargetContainer);
                if (containerStyle.position === 'static') {
                    finalTargetContainer.style.position = 'relative';
                }

                // Create and insert the iframe
                currentIframe = document.createElement('iframe');
                currentIframe.src = `https://2c47rw7m-5000.euw.devtunnels.ms/iframe?url=${encodeURIComponent(window.top.location.href)}`;
                currentIframe.style.border = 'none';
                currentIframe.style.position = 'absolute';
                currentIframe.style.zIndex = '9999'; // High z-index to be on top
                currentIframe.allowFullscreen = true;
                
                // Set iframe size to match the container and position at the top
                const targetContainerRect = finalTargetContainer.getBoundingClientRect();
                currentIframe.style.width = `${targetContainerRect.width}px`;
                currentIframe.style.height = `${targetContainerRect.height}px`;
                currentIframe.style.top = '0';
                currentIframe.style.left = '0';

                finalTargetContainer.appendChild(currentIframe);

                // Hide the original video content but preserve its space for the iframe
                currentLargestVideo.style.opacity = '0';
                currentLargestVideo.style.pointerEvents = 'none'; // Prevent interaction with the hidden video
            } else { // No videos found, clear iframe if it exists
                if (currentIframe && currentIframe.parentNode) {
                    currentIframe.remove();
                }
                currentIframe = null;
                currentLargestVideo = null;
            }
        } else if (currentLargestVideo && currentIframe) {
            // If the largest video hasn't changed, but its container/video itself might have moved or resized, update iframe geometry.
            const container = currentIframe.parentNode;
            if (container) {
                const targetContainerRect = container.getBoundingClientRect();
                currentIframe.style.width = `${targetContainerRect.width}px`;
                currentIframe.style.height = `${targetContainerRect.height}px`;
                currentLargestVideo.style.opacity = '0';
                currentLargestVideo.style.pointerEvents = 'none';
            }
        }

        // Prevent playback of other audio/video elements
        const mediaElements = document.querySelectorAll('video, audio');
        mediaElements.forEach(media => {
            // Stop all media elements UNLESS they are the iframe itself or inside the iframe.
            if (media !== currentIframe && !isElementInsideIframe(media, currentIframe)) {
                stopAndDisableMedia(media);
            }
        });
    }

    // Function to stop and disable a media element
    function stopAndDisableMedia(media) {
        if (!media || media === currentIframe || stoppedMediaElements.has(media)) {
            return;
        }

        media.pause();
        media.src = '';
        try {
            media.load();
        } catch (e) {
            console.warn('Tampermonkey: Error calling media.load() after clearing src:', e);
        }
        media.removeAttribute('autoplay');
        media.removeAttribute('controls');
        media.muted = true;
        media.volume = 0;

        const preventEvent = (e) => {
            e.stopImmediatePropagation();
            e.preventDefault();
        };
        media.addEventListener('play', preventEvent, true);
        media.addEventListener('playing', preventEvent, true);
        media.addEventListener('canplay', preventEvent, true);
        media.addEventListener('canplaythrough', preventEvent, true);
        media.addEventListener('loadeddata', preventEvent, true);
        media.addEventListener('loadedmetadata', preventEvent, true);
        media.addEventListener('progress', preventEvent, true);
        media.addEventListener('seeking', preventEvent, true);
        media.addEventListener('seeked', preventEvent, true);
        media.addEventListener('timeupdate', preventEvent, true);
        media.addEventListener('ended', preventEvent, true);

        stoppedMediaElements.add(media);
    }

    // Helper function to check if an element is inside the iframe's document
    function isElementInsideIframe(element, iframe) {
        if (!iframe || !iframe.contentDocument || !iframe.contentDocument.body) {
            return false;
        }
        try {
            return iframe.contentDocument.body.contains(element);
        } catch (e) {
            return false;
        }
    }

    // Initial application of the logic
    applyVideoReplacementLogic();

    // Observe for new media elements being added to the DOM.
    const mediaObserver = new MutationObserver(mutationsList => {
        for (const mutation of mutationsList) {
            if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
                mutation.addedNodes.forEach(node => {
                    if (node.nodeType === 1) {
                        if (node.tagName === 'VIDEO' || node.tagName === 'AUDIO') {
                            stopAndDisableMedia(node);
                        }
                        node.querySelectorAll('video, audio').forEach(stopAndDisableMedia);
                    }
                });
            }
        }
    });

    mediaObserver.observe(document.body, { childList: true, subtree: true });

    // Override HTMLMediaElement.prototype.play to prevent any media from playing directly.
    const originalPlay = HTMLMediaElement.prototype.play;
    HTMLMediaElement.prototype.play = function() {
        if (this === currentIframe || (this.tagName !== 'VIDEO' && this.tagName !== 'AUDIO')) {
            return originalPlay.apply(this, arguments);
        }
        console.log('Tampermonkey: Preventing playback of:', this);
        this.pause();
        this.currentTime = 0;
        return Promise.resolve();
    };

    // Override HTMLMediaElement.prototype.load to prevent loading of other media.
    const originalLoad = HTMLMediaElement.prototype.load;
    HTMLMediaElement.prototype.load = function() {
        if (this === currentIframe || (this.tagName !== 'VIDEO' && this.tagName !== 'AUDIO')) {
            return originalLoad.apply(this, arguments);
        }
        console.log('Tampermonkey: Preventing load of:', this);
        this.src = '';
        return;
    };

    // Ensure all existing media elements are stopped immediately when the script loads.
    document.querySelectorAll('video, audio').forEach(stopAndDisableMedia);

    let applyLogicTimeout = null;
    const DEBOUNCE_TIME = 200;

    // Observe DOM for changes to re-evaluate video replacement logic.
    const observer = new MutationObserver((mutations) => {
        let videoAddedOrChanged = false;
        for (const mutation of mutations) {
            if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
                for (const node of mutation.addedNodes) {
                    if (node.nodeType === 1) {
                        if (node.tagName === 'VIDEO' || node.querySelector('video')) {
                            videoAddedOrChanged = true;
                            break;
                        }
                        if (node.querySelectorAll('video, audio').length > 0) {
                             videoAddedOrChanged = true;
                             break;
                        }
                    }
                }
            } else if (mutation.type === 'attributes' && mutation.target.tagName === 'VIDEO') {
                videoAddedOrChanged = true;
            }
            if (videoAddedOrChanged) break;
        }
        if (videoAddedOrChanged) {
            clearTimeout(applyLogicTimeout);
            applyLogicTimeout = setTimeout(() => {
                applyVideoReplacementLogic();
            }, DEBOUNCE_TIME);
        }
    });

    observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['src', 'autoplay', 'controls', 'style'] });

    // Detect URL changes for single-page applications.
    let lastUrl = window.location.href;
    const urlChangeObserver = new MutationObserver(() => {
        if (window.location.href !== lastUrl) {
            lastUrl = window.location.href;
            if (currentIframe) {
                currentIframe.src = `https://2c47rw7m-5000.euw.devtunnels.ms/iframe?url=${encodeURIComponent(window.top.location.href)}`;
            } else {
                applyVideoReplacementLogic();
            }
        }
    });

    urlChangeObserver.observe(document, { subtree: true, childList: true });

    // Also handle browser history navigation (back/forward buttons) and programmatic URL changes.
    window.addEventListener('popstate', () => {
        if (window.location.href !== lastUrl) {
            lastUrl = window.location.href;
            if (currentIframe) {
                currentIframe.src = `https://2c47rw7m-5000.euw.devtunnels.ms/iframe?url=${encodeURIComponent(window.top.location.href)}`;
            } else {
                applyVideoReplacementLogic();
            }
        }
    });

    // Override pushState and replaceState to detect programmatic URL changes.
    (function(history){
        const pushState = history.pushState;
        history.pushState = function() {
            if (typeof pushState === 'function') pushState.apply(history, arguments);
            window.dispatchEvent(new Event('popstate'));
        };

        const replaceState = history.replaceState;
        history.replaceState = function() {
            if (typeof replaceState === 'function') replaceState.apply(history, arguments);
            window.dispatchEvent(new Event('popstate'));
        };
    })(window.history);

    // --- Keyboard shortcuts for iframe control ---
    window.addEventListener('keydown', (event) => {
        // Only act if an iframe exists and the event didn't originate from a text input
        if (currentIframe && currentIframe.contentWindow && !event.isComposing &&
            !(event.target.tagName === 'INPUT' || event.target.tagName === 'TEXTAREA')) {

            // Prevent default spacebar action (scrolling)
            if (event.code === 'Space') {
                event.preventDefault();
                // Attempt to dispatch a space keydown event directly to the iframe
                // This might not work due to cross-origin restrictions, but it's the closest to "passing through"
                try {
                    const iframeEvent = new KeyboardEvent('keydown', {
                        key: ' ',
                        code: 'Space',
                        keyCode: 32,
                        which: 32,
                        bubbles: true,
                        cancelable: true
                    });
                    currentIframe.contentWindow.dispatchEvent(iframeEvent);
                } catch (e) {
                    console.warn("Tampermonkey: Could not dispatch Space event to iframe directly:", e);
                    // Fallback: Post a message if direct dispatch fails or is not possible
                    currentIframe.contentWindow.postMessage({ action: 'togglePlayPause' }, '*');
                }
            } else if (event.key === 'f' || event.key === 'F') {
                event.preventDefault(); // Prevent browser's default 'f' action if any
                // Attempt to dispatch an 'f' keydown event directly to the iframe
                try {
                    const iframeEvent = new KeyboardEvent('keydown', {
                        key: 'f',
                        code: 'KeyF',
                        keyCode: 70,
                        which: 70,
                        bubbles: true,
                        cancelable: true
                    });
                    currentIframe.contentWindow.dispatchEvent(iframeEvent);
                } catch (e) {
                    console.warn("Tampermonkey: Could not dispatch 'f' event to iframe directly:", e);
                    // Fallback: Post a message if direct dispatch fails or is not possible
                    currentIframe.contentWindow.postMessage({ action: 'toggleFullscreen' }, '*');
                }
            }
        }
    }, true); // Use capture phase to ensure we catch events before other handlers

})();

Read 5 times, last 32 seconds ago