Video Right-Click Download Enabler

Enables default right-click context-menu to download videos of HTML5 video players. Also works together with other video download extension and scripts (native & custom).

// ==UserScript==
// @name         Video Right-Click Download Enabler
// @namespace    https://github.com/BD9Max/userscripts
// @version      1.1
// @description  Enables default right-click context-menu to download videos of HTML5 video players. Also works together with other video download extension and scripts (native & custom).
// @author       BD9Max
// @license      MIT
// @match        https://*/*
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';

    // Block all contextmenu event listeners on videos
    const originalAddEventListener = EventTarget.prototype.addEventListener;
    EventTarget.prototype.addEventListener = function(type, listener, options) {
        if (this.tagName === 'VIDEO' && type === 'contextmenu') {
            return; // Block contextmenu blockers
        }
        return originalAddEventListener.call(this, type, listener, options);
    };

    // Allow native context menu on videos only
    document.addEventListener('contextmenu', function(e) {
        if (e.target.tagName === 'VIDEO') {
            e.stopPropagation();
            return true;
        }
    }, true);

    // Process all videos
    function enableVideo(video) {
        video.oncontextmenu = null;
        video.removeAttribute('oncontextmenu');
        video.removeAttribute('controlsList');
    }

    // Watch for videos
    const observer = new MutationObserver((mutations) => {
        mutations.forEach((mutation) => {
            mutation.addedNodes.forEach((node) => {
                if (node.tagName === 'VIDEO') {
                    enableVideo(node);
                } else if (node.querySelectorAll) {
                    node.querySelectorAll('video').forEach(enableVideo);
                }
            });
        });
    });

    function init() {
        document.querySelectorAll('video').forEach(enableVideo);
        if (document.body) {
            observer.observe(document.body, { childList: true, subtree: true });
        }
    }

    if (document.body) {
        init();
    } else {
        document.addEventListener('DOMContentLoaded', init);
    }

    // Periodic cleanup
    setInterval(() => {
        document.querySelectorAll('video[oncontextmenu]').forEach(v => {
            v.removeAttribute('oncontextmenu');
        });
    }, 1000);
})();