Universal Bypass

Bypass common web restrictions: right-click, copy-paste, text selection, console, debugger, and more.

目前為 2025-01-10 提交的版本,檢視 最新版本

// ==UserScript==
// @name         Universal Bypass
// @namespace    https://github.com/x3ric
// @version      1.5
// @description  Bypass common web restrictions: right-click, copy-paste, text selection, console, debugger, and more.
// @author       x3ric
// @license      MIT
// @match        *://*/*
// @run-at       document-start
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_registerMenuCommand
// @grant        GM_unregisterMenuCommand
// @grant        GM_notification
// @grant        unsafeWindow
// @inject-into  page
// @compatible   firefox Violentmonkey
// @compatible   firefox Tampermonkey
// @compatible   chrome Violentmonkey
// @compatible   chrome Tampermonkey
// @compatible   opera Violentmonkey
// @compatible   opera Tampermonkey
// @compatible   safari Stay
// @compatible   edge Violentmonkey
// @compatible   edge Tampermonkey
// @compatible   brave Violentmonkey
// @compatible   brave Tampermonkey
// ==/UserScript==

(function() {
    'use strict';

    // Load settings or set defaults if not already saved
    const settings = GM_getValue('universalBypassSettings', {
        rightClick: true,
        copyPaste: true,
        textSelection: true,
        consoleBypass: false,
        debuggerBypass: false
    });

    // Save settings to storage
    const saveSettings = () => {
        GM_setValue('universalBypassSettings', settings);
    };

    // Function to remove all added listeners from problematic scripts
    const removeAllEventListeners = () => {
        var newElement = document.createElement('div');
        newElement.innerHTML = document.body.innerHTML;
        document.body.innerHTML = newElement.innerHTML;
    };

    // Function to apply bypasses based on settings
    const applyBypasses = () => {
        if (settings.rightClick) {
            window.addEventListener('contextmenu', e => e.stopImmediatePropagation(), { once: true, capture: true });
        }

        if (settings.copyPaste) {
            // Nullify any set event handlers that restrict copy/paste operations
            document.onkeydown = null;
            document.onselectstart = null;
            document.onmousedown = null;
            document.onclick = null;
            document.body.oncopy = document.body.oncut = document.body.onpaste = null;

            ['copy', 'paste', 'cut'].forEach(ev => {
                document.addEventListener(ev, e => e.stopImmediatePropagation(), { capture: true });
            });

            // Reset event listeners on body's HTML content replacement
            window.onload = removeAllEventListeners;
            document.addEventListener('DOMContentLoaded', removeAllEventListeners);
            document.addEventListener('touchstart', e => e.stopPropagation(), true);
            document.addEventListener('touchend', e => e.stopPropagation(), true);
        }

        if (settings.textSelection) {
            // Override CSS to enable text selection
            document.querySelectorAll('*').forEach(el => {
                el.style.userSelect = 'text';
                el.style.cursor = 'auto';
            });

            const style = document.createElement('style');
            style.textContent = '* { user-select: text !important; -webkit-user-select: text !important; }';
            document.head.appendChild(style);
        }

        if (settings.consoleBypass) {
            ['log', 'warn', 'error', 'debug', 'info'].forEach(func => {
                console[func] = () => {};
            });
        }

        if (settings.debuggerBypass) {
            unsafeWindow.eval = new Proxy(unsafeWindow.eval, {
                apply: (target, thisArg, args) => {
                    args[0] = args[0].replace(/debugger/g, '');
                    return Reflect.apply(target, thisArg, args);
                }
            });
        }
    };

    // Toggle individual settings
    const toggleSetting = key => {
        settings[key] = !settings[key];
        saveSettings();
        applyBypasses();
        GM_notification({
            text: `${key} is now ${settings[key] ? 'enabled' : 'disabled'}.`,
            title: 'Setting Toggled',
            timeout: 2500
        });
    };

    // Register menu commands for toggling settings
    Object.keys(settings).forEach(key => {
        GM_registerMenuCommand(`${key} ${settings[key] ? 'ON' : 'OFF'}`, () => toggleSetting(key));
    });

    applyBypasses();

    // Observe DOM changes to reapply bypasses if necessary
    const observer = new MutationObserver(() => applyBypasses());
    observer.observe(document.documentElement, { childList: true, subtree: true });

    // Reapply bypasses on page navigation events to ensure consistency
    ['load', 'popstate', 'pushstate', 'replacestate'].forEach(event =>
        window.addEventListener(event, applyBypasses, true)
    );
})();