网页复制限制解除

解除网站复制限制、去除复制水印

目前為 2024-10-31 提交的版本,檢視 最新版本

// ==UserScript==
// @name         网页复制限制解除
// @namespace    http://tampermonkey.net/
// @version      1.4
// @description  解除网站复制限制、去除复制水印
// @author       Heavrnl
// @license      MIT
// @match        *://*/*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_registerMenuCommand
// @grant        GM_addStyle
// ==/UserScript==

(function () {
    'use strict';

    // 检查是否在 iframe 中
    const isInIframe = window !== window.top;

    // 添加设置界面的样式
    GM_addStyle(`
        .watermark-settings {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: white;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 0 10px rgba(0,0,0,0.3);
            z-index: 10000;
            width: 500px;
            font-family: Arial, sans-serif;
        }
        .watermark-settings h2 {
            margin: 0 0 15px 0;
            color: #333;
        }
        .watermark-settings .buttons {
            display: flex;
            justify-content: flex-end;
            gap: 10px;
        }
        .watermark-settings button {
            padding: 8px 15px;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }
        .watermark-settings .save {
            background: #28a745;
            color: white;
        }
        .watermark-settings .cancel {
            background: #dc3545;
            color: white;
        }
        .watermark-settings .overlay {
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: rgba(0,0,0,0.5);
            z-index: 9999;
        }
    `);

    // 初始化设置 - 只在主页面中执行
    if (!isInIframe) {
        if (GM_getValue('watermarkSites') === undefined) {
            GM_setValue('watermarkSites', {});  // 使用对象存储各网站的去水印状态
        }
        if (GM_getValue('copySites') === undefined) {
            GM_setValue('copySites', {});  // 使用对象存储各网站的复制解除状态
        }
    }

    // 检查当前网站的复制解除状态
    const isCopyEnabled = () => {
        const currentHost = window.location.hostname;
        const copySites = GM_getValue('copySites', {});
        return copySites[currentHost] || false;
    };

    // 修改去水印功能
    function removeWatermark() {
        const currentHost = window.location.hostname;
        const watermarkSites = GM_getValue('watermarkSites', {});

        if (!watermarkSites[currentHost]) return;

        document.addEventListener('copy', function(e) {
            e.stopPropagation();
            const selection = window.getSelection();
            e.clipboardData.setData('text/plain', selection.toString());
            e.preventDefault();
        }, true);
    }

    // 创建并添加按钮
    const button = document.createElement("button");
    // 使用 SVG 图标替代文字
    const svgIcon = `
        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
            <path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path>
            <rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect>
        </svg>`;

    button.innerHTML = svgIcon;

    // 根据存储的状态设置按钮样式
    const isEnabled = GM_getValue('enableCopyRemoval', false);
    const getButtonStyle = (enabled) => `
        position: fixed;
        right: 10px;
        bottom: 15%;
        z-index: 9999;
        width: 32px;
        height: 32px;
        padding: 6px;
        background-color: ${enabled ? 'rgba(220, 53, 69, 0.3)' : 'rgba(40, 167, 69, 0.3)'};
        color: white;
        border: none;
        border-radius: 50%;
        cursor: pointer;
        transition: all 0.3s ease;
        display: flex;
        align-items: center;
        justify-content: center;
        opacity: 0.3;
    `;

    button.style.cssText = getButtonStyle(isEnabled);

    // 悬停效果
    button.onmouseenter = () => {
        button.style.opacity = "1";
        const currentHost = window.location.hostname;
        const copySites = GM_getValue('copySites', {});
        const isEnabled = copySites[currentHost] || false;
        button.style.backgroundColor = isEnabled ?
            'rgba(220, 53, 69, 0.9)' :
            'rgba(40, 167, 69, 0.9)';
    };

    button.onmouseleave = () => {
        button.style.opacity = "0.3";
        const currentHost = window.location.hostname;
        const copySites = GM_getValue('copySites', {});
        const isEnabled = copySites[currentHost] || false;
        button.style.backgroundColor = isEnabled ?
            'rgba(220, 53, 69, 0.3)' :
            'rgba(40, 167, 69, 0.3)';
    };

    document.body.appendChild(button);

    // 修改点击按钮时切换状态的代码
    const handleButtonClick = () => {
        const currentHost = window.location.hostname;
        const copySites = GM_getValue('copySites', {});
        const currentState = copySites[currentHost] || false;

        if (!currentState) {
            // 启用当前网站的复制解除
            copySites[currentHost] = true;
            GM_setValue('copySites', copySites);
            // 立即启用复制解除
            enableCopyAndRemoveOverlay();
            // 更新按钮样式
            button.style.backgroundColor = 'rgba(220, 53, 69, 0.3)';

            // 立即应用额外的复制解除措施
            const style = document.createElement('style');
            style.innerHTML = `
                * {
                    -webkit-user-select: text !important;
                    -moz-user-select: text !important;
                    -ms-user-select: text !important;
                    user-select: text !important;
                    -webkit-touch-callout: default !important;
                }
                ::selection {
                    background-color: #338FFF !important;
                    color: #fff !important;
                }
            `;
            document.head.appendChild(style);

            // 立即移除所有元素的复制限制
            document.querySelectorAll('*').forEach(element => {
                element.style.userSelect = "text";
                element.style.webkitUserSelect = "text";
                element.style.msUserSelect = "text";
                element.style.MozUserSelect = "text";

                // 移除事件监听器
                element.oncontextmenu = null;
                element.onselectstart = null;
                element.onselect = null;
                element.oncopy = null;
                element.onbeforecopy = null;
                element.oncut = null;
                element.onpaste = null;
                element.ondrag = null;
                element.ondragstart = null;
            });

            // 立即覆盖文档级别的事件
            document.oncontextmenu = null;
            document.onselectstart = null;
            document.oncopy = null;
            document.oncut = null;
            document.onpaste = null;

            // 添加复制事件监听器
            document.addEventListener('copy', function(e) {
                e.stopPropagation();
                const selection = window.getSelection();
                e.clipboardData.setData('text/plain', selection.toString());
            }, true);

        } else {
            // 禁用当前网站的复制解除
            copySites[currentHost] = false;
            GM_setValue('copySites', copySites);
            location.reload(); // 刷新页面以恢复原始状态
        }
    };

    // 绑定点击事件
    button.addEventListener("click", handleButtonClick);

    // 移除复制限制及遮挡层的功能
    const enableCopyAndRemoveOverlay = () => {
        const currentHost = window.location.hostname;
        const copySites = GM_getValue('copySites', {});

        if (!copySites[currentHost]) return;

        // 处理CSDN特定的复制限制
        document.querySelectorAll('*').forEach(element => {
            // 移除CSDN特定的user-select限制
            if (element.classList.contains('htmledit_views') ||
                element.classList.contains('markdown_views') ||
                element.classList.contains('article_content')) {
                element.style.cssText = `
                    -webkit-user-select: text !important;
                    -moz-user-select: text !important;
                    -ms-user-select: text !important;
                    user-select: text !important;
                `;
            }

            // 移除CSDN的事件监听器
            element.oncontextmenu = null;
            element.onselectstart = null;
            element.onselect = null;
            element.oncopy = null;
            element.onbeforecopy = null;
            element.oncut = null;
            element.onpaste = null;
            element.ondrag = null;
            element.ondragstart = null;
        });

        // 覆盖CSDN的复制事件处理
        document.addEventListener('copy', function(e) {
            e.stopPropagation();
            const selection = window.getSelection();
            e.clipboardData.setData('text/plain', selection.toString());
        }, true);

        // 移除CSDN的遮罩层和弹窗
        const removeOverlays = () => {
            const overlays = document.querySelectorAll('.login-mark, .login-box');
            overlays.forEach(overlay => overlay.remove());
        };

        // 定期检查并移除遮罩
        setInterval(removeOverlays, 100);

        // 移除所有元素的复制限制
        document.querySelectorAll('*').forEach(element => {
            // 允许选择文本
            element.style.userSelect = "text";
            element.style.webkitUserSelect = "text";
            element.style.msUserSelect = "text";
            element.style.MozUserSelect = "text";

            // 移除事件监听器
            element.onselectstart = null;
            element.oncontextmenu = null;
            element.onmousedown = null;
            element.onkeydown = null;
            element.oncopy = null;
            element.oncut = null;
            element.ondrag = null;
            element.ondragstart = null;

            // 移除 unselectable 属性
            element.removeAttribute('unselectable');
            element.removeAttribute('oncontextmenu');
            element.removeAttribute('oncopy');
            element.removeAttribute('oncut');
            element.removeAttribute('onselectstart');
        });

        // 移除遮挡层
        document.querySelectorAll('*').forEach(element => {
            const style = window.getComputedStyle(element);
            if ((style.position === 'absolute' || style.position === 'fixed') &&
                (style.opacity === '0' || parseFloat(style.opacity) < 0.1) &&
                style.zIndex > 0) {
                element.remove();
            }
        });

        // 覆盖常见的禁用右键和复制的方法
        document.oncontextmenu = null;
        document.onselectstart = null;
        document.oncopy = null;
        document.oncut = null;
        document.onpaste = null;
        document.onkeydown = null;
        document.onmousedown = null;

        // 覆盖 window 对象上的限制方法
        window.oncontextmenu = null;
        window.onselectstart = null;
        window.oncopy = null;
        window.oncut = null;
        window.onpaste = null;
        window.onkeydown = null;
        window.onmousedown = null;

        // 阻止页面使用 addEventListener 添加新的限制
        const originalAddEventListener = EventTarget.prototype.addEventListener;
        EventTarget.prototype.addEventListener = function(type, listener, options) {
            if (type === 'contextmenu' || type === 'selectstart' ||
                type === 'copy' || type === 'cut' || type === 'paste' ||
                type === 'keydown' || type === 'mousedown') {
                return;
            }
            originalAddEventListener.call(this, type, listener, options);
        };

        // 移除 CSS 限制
        const style = document.createElement('style');
        style.innerHTML = `
            * {
                -webkit-user-select: text !important;
                -moz-user-select: text !important;
                -ms-user-select: text !important;
                user-select: text !important;
                -webkit-touch-callout: default !important;
            }
            ::selection {
                background-color: #338FFF !important;
                color: #fff !important;
            }
        `;
        document.head.appendChild(style);

        // 添加百度文库的特殊处理
        if (location.hostname.includes('wenku.baidu.com')) {
            // 移除文字选择限制
            document.querySelectorAll('.reader-word-layer').forEach(element => {
                element.style.userSelect = 'text';
                element.style.webkitUserSelect = 'text';
                element.style.MozUserSelect = 'text';
                element.style.msUserSelect = 'text';
            });

            // 移除复制拦截
            document.addEventListener('copy', function(e) {
                e.stopPropagation();
                const selection = window.getSelection();
                e.clipboardData.setData('text/plain', selection.toString());
            }, true);

            // 移除CSS档遮罩
            const removeWenkuOverlay = () => {
                const overlays = document.querySelectorAll('.reader-mask, .vip-pop-wrap, .show-pay-modal, .payment-modal-wrap');
                overlays.forEach(overlay => overlay.remove());
            };

            // 定期检查并移除遮罩
            setInterval(removeWenkuOverlay, 500);

            // 修改文档容器样式
            const readerContainer = document.querySelector('.reader-container');
            if (readerContainer) {
                readerContainer.style.height = 'auto';
                readerContainer.style.overflow = 'visible';
            }
        }
    };

    // 修改 MutationObserver,只在功能开启时才观察
    const observer = new MutationObserver(() => {
        if (GM_getValue('enableCopyRemoval', false)) {
            enableCopyAndRemoveOverlay();
        }
    });
    observer.observe(document.body, { childList: true, subtree: true });

    // 创建并添加去水印按钮
    const watermarkButton = document.createElement("button");
    const watermarkSvgIcon = `
        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
            <line x1="1" y1="1" x2="23" y2="23"></line>
            <path d="M21 21H3a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h18a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2z"></path>
        </svg>`;

    watermarkButton.innerHTML = watermarkSvgIcon;

    // 获取去水印功能的状态
    const isWatermarkEnabled = () => {
        const currentHost = window.location.hostname;
        const watermarkSites = GM_getValue('watermarkSites', {});
        return watermarkSites[currentHost] || false;
    };

    // 设置去水印按钮样式
    const getWatermarkButtonStyle = (enabled) => `
        position: fixed;
        right: 10px;
        bottom: 10%;
        z-index: 9999;
        width: 32px;
        height: 32px;
        padding: 6px;
        background-color: ${enabled ? 'rgba(220, 53, 69, 0.3)' : 'rgba(40, 167, 69, 0.3)'};
        color: white;
        border: none;
        border-radius: 50%;
        cursor: pointer;
        transition: all 0.3s ease;
        display: flex;
        align-items: center;
        justify-content: center;
        opacity: 0.3;
    `;

    watermarkButton.style.cssText = getWatermarkButtonStyle(isWatermarkEnabled());

    // 去水印按钮的悬停效果
    watermarkButton.onmouseenter = () => {
        watermarkButton.style.opacity = "1";
        const currentHost = window.location.hostname;
        const watermarkSites = GM_getValue('watermarkSites', {});
        const isEnabled = watermarkSites[currentHost] || false;
        watermarkButton.style.backgroundColor = isEnabled ?
            'rgba(220, 53, 69, 0.9)' :
            'rgba(40, 167, 69, 0.9)';
    };

    watermarkButton.onmouseleave = () => {
        watermarkButton.style.opacity = "0.3";
        const currentHost = window.location.hostname;
        const watermarkSites = GM_getValue('watermarkSites', {});
        const isEnabled = watermarkSites[currentHost] || false;
        watermarkButton.style.backgroundColor = isEnabled ?
            'rgba(220, 53, 69, 0.3)' :
            'rgba(40, 167, 69, 0.3)';
    };

    // 去水印按钮点击事件
    watermarkButton.addEventListener("click", () => {
        const currentHost = window.location.hostname;
        const watermarkSites = GM_getValue('watermarkSites', {});
        const currentState = watermarkSites[currentHost] || false;

        watermarkSites[currentHost] = !currentState;
        GM_setValue('watermarkSites', watermarkSites);

        // 立即应用新状态
        if (!currentState) {
            removeWatermark();
        } else {
            location.reload(); // 如果是关闭状态,需要刷新页面
        }

        // 更新按钮样式
        watermarkButton.style.cssText = getWatermarkButtonStyle(!currentState);
    });

    document.body.appendChild(watermarkButton);

    // 添加按钮组样式
    GM_addStyle(`
        .float-button-group {
            position: fixed;
            right: 10px;
            bottom: 15%;
            z-index: 9999;
            display: flex;
            flex-direction: column;
            gap: 8px;
        }
        .float-button {
            width: 32px;
            height: 32px;
            padding: 6px;
            background-color: rgba(40, 167, 69, 0.3);
            color: white;
            border: none;
            border-radius: 50%;
            cursor: pointer;
            transition: all 0.3s ease;
            display: flex;
            align-items: center;
            justify-content: center;
            opacity: 0.3;
        }
    `);

    // 创建按钮组容器
    const buttonGroup = document.createElement('div');
    buttonGroup.className = 'float-button-group';

    // 创建复制解除按钮
    const copyButton = document.createElement("button");
    copyButton.className = 'float-button';
    copyButton.innerHTML = svgIcon;

    // 创建去水印按钮
    const watermarkBtn = document.createElement("button");
    watermarkBtn.className = 'float-button';
    watermarkBtn.innerHTML = watermarkSvgIcon;

    // 更新按钮状态的函数
    const updateButtonStyle = (btn, enabled) => {
        btn.style.backgroundColor = enabled ?
            'rgba(220, 53, 69, 0.3)' :
            'rgba(40, 167, 69, 0.3)';
    };

    // 设置初始状态
    const copyEnabled = isCopyEnabled();
    updateButtonStyle(copyButton, copyEnabled);

    const watermarkEnabled = isWatermarkEnabled();
    updateButtonStyle(watermarkBtn, watermarkEnabled);

    // 复制按钮的悬停效果
    copyButton.onmouseenter = () => {
        copyButton.style.opacity = "1";
        const isEnabled = isCopyEnabled();
        copyButton.style.backgroundColor = isEnabled ?
            'rgba(220, 53, 69, 0.9)' :
            'rgba(40, 167, 69, 0.9)';
    };

    copyButton.onmouseleave = () => {
        copyButton.style.opacity = "0.3";
        const isEnabled = isCopyEnabled();
        copyButton.style.backgroundColor = isEnabled ?
            'rgba(220, 53, 69, 0.3)' :
            'rgba(40, 167, 69, 0.3)';
    };

    // 去水印按钮的悬停效果
    watermarkBtn.onmouseenter = () => {
        watermarkBtn.style.opacity = "1";
        const currentHost = window.location.hostname;
        const watermarkSites = GM_getValue('watermarkSites', {});
        const isEnabled = watermarkSites[currentHost] || false;
        watermarkBtn.style.backgroundColor = isEnabled ?
            'rgba(220, 53, 69, 0.9)' :
            'rgba(40, 167, 69, 0.9)';
    };

    watermarkBtn.onmouseleave = () => {
        watermarkBtn.style.opacity = "0.3";
        const currentHost = window.location.hostname;
        const watermarkSites = GM_getValue('watermarkSites', {});
        const isEnabled = watermarkSites[currentHost] || false;
        watermarkBtn.style.backgroundColor = isEnabled ?
            'rgba(220, 53, 69, 0.3)' :
            'rgba(40, 167, 69, 0.3)';
    };

    // 绑定点击事件
    copyButton.addEventListener("click", handleButtonClick);
    watermarkBtn.addEventListener("click", handleWatermarkButtonClick);

    // 将按钮添加到按钮组
    buttonGroup.appendChild(copyButton);
    buttonGroup.appendChild(watermarkBtn);

    // 将按钮组添加到页面
    document.body.appendChild(buttonGroup);

    // 移除之前直接添加到body的按钮
    const oldButtons = document.querySelectorAll('button[style*="position: fixed"]');
    oldButtons.forEach(btn => btn.remove());
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址