Enable Copy-Paste

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

Dovrai installare un'estensione come Tampermonkey, Greasemonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Userscripts per installare questo script.

Dovrai installare un'estensione come ad esempio Tampermonkey per installare questo script.

Dovrai installare un gestore di script utente per installare questo script.

(Ho già un gestore di script utente, lasciamelo installare!)

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

(Ho già un gestore di stile utente, lasciamelo installare!)

// ==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);

})();