Enable Copy-Paste

Force-enables copy, paste, context menu, and keyboard shortcuts by monkey-patching and piercing Shadow DOM.

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Necesitará instalar una extensión como Tampermonkey para instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name         Enable Copy-Paste
// @version      3.0
// @description  Force-enables copy, paste, context menu, and keyboard shortcuts by monkey-patching and piercing Shadow DOM.
// @description:en Force-enables copy, paste, context menu, and keyboard shortcuts by monkey-patching and piercing Shadow DOM.
// @match        *://*/*
// @grant        GM_addStyle
// @run-at       document-start
// @namespace    http://tampermonkey.net/
// @license      LGPL-2.1
// ==/UserScript==

(function() {
    'use strict';

    // 1. Define CSS rules
    const cssRule = `
        *, *::before, *::after {
            -webkit-user-select: auto !important;
            -moz-user-select: auto !important;
            -ms-user-select: auto !important;
            user-select: auto !important;
            -webkit-touch-callout: auto !important;
        }
    `;

    // 2. Inject CSS (Light DOM)
    GM_addStyle(cssRule);

    // 3. Pierce Shadow DOM
    const originalAttachShadow = Element.prototype.attachShadow;
    Element.prototype.attachShadow = function(options) {
        const shadowRoot = originalAttachShadow.call(this, options);
        const style = document.createElement('style');
        style.textContent = cssRule;
        shadowRoot.appendChild(style);
        return shadowRoot;
    };

    // 4. Block Event Listeners

    // Events to simply block
    const simpleForbiddenEvents = [
        'copy', 'paste', 'cut',
        'selectstart',
        'contextmenu',
        'dragstart'
    ];

    // Keyboard events for smart handling
    const keyboardEvents = ['keydown', 'keyup', 'keypress'];

    // Shortcut detection
    const isShortcut = (e) => {
        return (e.ctrlKey || e.metaKey) &&
               ['c', 'v', 'x', 'a', 'insert'].includes(e.key.toLowerCase());
    };

    // Override addEventListener
    const originalAddEventListener = EventTarget.prototype.addEventListener;

    EventTarget.prototype.addEventListener = function(type, listener, options) {

        if (simpleForbiddenEvents.includes(type)) {
            console.log(`[Anti-Restrict] Blocked ${type} event listener.`);
            return;
        }

        if (keyboardEvents.includes(type)) {
            const wrappedListener = function(event) {
                if (isShortcut(event)) {
                    console.log(`[Anti-Restrict] Bypassed shortcut in ${type} event.`);
                    event.stopImmediatePropagation();
                } else {
                    Reflect.apply(listener, this, arguments);
                }
            };

            originalAddEventListener.call(this, type, wrappedListener, options);
            return;
        }

        originalAddEventListener.call(this, type, listener, options);
    };

    // 5. Clean up on* event handlers
    const clearOnEventHandlers = () => {
        const targets = [window, document, document.body];
        const eventHandlers = [
            'oncontextmenu', 'oncopy', 'oncut', 'onpaste',
            'onselectstart', 'ondragstart',
            'onkeydown', 'onkeyup', 'onkeypress'
        ];

        for (const target of targets) {
            if (!target) continue;
            for (const handler of eventHandlers) {
                try {
                    if (target[handler]) {
                        target[handler] = null;
                    }
                    Object.defineProperty(target, handler, {
                        value: null,
                        writable: true,
                        configurable: true
                    });
                } catch (e) {
                    // Ignore errors
                }
            }
        }
    };

    clearOnEventHandlers();
    window.addEventListener('load', clearOnEventHandlers);
    setTimeout(clearOnEventHandlers, 1500);

})();