Greasy Fork

Greasy Fork is available in English.

【最强】【最全面】【全网页可用】【持续更新中】解除禁止复制和粘贴限制并支持手动粘贴

⭐学习通⭐pta⭐csdn⭐飞书云文档⭐破解所有网站【禁止复制】和【禁止粘贴】限制,支持【模拟人工输入】。安装后,打开目标网页即可解除限制。若粘贴解锁不生效,可以使用ctrl+m呼出浮动输入框进行模拟人工输入,详情请阅读下方说明。有疑问或者反馈都可以发我邮箱啊:[email protected]

当前为 2024-11-17 提交的版本,查看 最新版本

// ==UserScript==
// @name         【最强】【最全面】【全网页可用】【持续更新中】解除禁止复制和粘贴限制并支持手动粘贴
// @namespace    http://jiangning_sama/pojie_cpoy.net/
// @version      7.2.3
// @description  ⭐学习通⭐pta⭐csdn⭐飞书云文档⭐破解所有网站【禁止复制】和【禁止粘贴】限制,支持【模拟人工输入】。安装后,打开目标网页即可解除限制。若粘贴解锁不生效,可以使用ctrl+m呼出浮动输入框进行模拟人工输入,详情请阅读下方说明。有疑问或者反馈都可以发我邮箱啊:[email protected]
// @author       江宁sama
// @match        *://*/*
// @exclude      https://chatgpt.com/*
// @exclude      https://www.bilibili.com/*
// @exclude      https://www.bing.com/*
// @exclude      https://fanyi.*/*
// @grant        none
// @run-at       document-start
// @license      MIT
// ==/UserScript==

/*
 * 免责声明:
 * 本脚本为教育和学习用途而开发,旨在帮助用户了解网页元素的控制与交互操作。
 * 使用本脚本即表示用户同意自行承担由此带来的一切风险和后果,开发者不对因使用本脚本
 * 造成的任何直接或间接损失负责。
 * 
 * 请勿使用本脚本用于任何违反服务条款、侵害他人权益或违反当地法律法规的行为。
 * 建议仅在个人测试环境中使用,不建议用于生产环境或未经授权的网页。
 * 
 * 使用前请务必仔细阅读本免责声明,开发者保留随时更改或终止该脚本的权利。
 */

(function () {
    'use strict';

    const isFeishuPage = /feishu\.cn|larkoffice\.com/.test(window.location.hostname);

    // 飞书专用功能
    function feishuScript() {
        const overrideEventListeners = () => {
            const rawAddEventListener = EventTarget.prototype.addEventListener;
            EventTarget.prototype.addEventListener = function (type, listener, options) {
                if (type === 'copy' || type === 'contextmenu') {
                    rawAddEventListener.call(this, type, event => {
                        event.stopImmediatePropagation();
                        if (type === 'contextmenu') {
                            return listener(event);
                        }
                    }, options);
                    return;
                }
                rawAddEventListener.call(this, type, listener, options);
            };
        };

        const overrideXHR = () => {
            const rawOpen = XMLHttpRequest.prototype.open;
            XMLHttpRequest.prototype.open = function (method, url, ...rest) {
                this.addEventListener('readystatechange', function () {
                    if (this.readyState === 4 && url.includes('space/api/suite/permission/document/actions/state/')) {
                        let response = this.responseText;
                        try {
                            const jsonResponse = JSON.parse(response);
                            if (jsonResponse.data && jsonResponse.data.actions && jsonResponse.data.actions.copy !== 1) {
                                jsonResponse.data.actions.copy = 1;
                                Object.defineProperty(this, 'responseText', { value: JSON.stringify(jsonResponse) });
                                Object.defineProperty(this, 'response', { value: jsonResponse });
                            }
                        } catch (e) {
                            console.error('Failed to modify response:', e);
                        }
                    }
                }, false);
                rawOpen.call(this, method, url, ...rest);
            };
        };

        overrideEventListeners();
        overrideXHR();
    }

    // 通用功能
    function universalUnlockScript() {
        const removeVipMask = () => {
            // 查询所有可能的遮罩层
            const masks = document.querySelectorAll('div[class*="hide-article"], div[class*="overlay"], div[class*="mask"]');
            masks.forEach(mask => {
                mask.style.display = 'none'; // 隐藏遮罩层
                mask.remove(); // 移除遮罩层
            });

            // 清理可能的样式限制
            document.body.style.overflow = 'auto'; // 恢复滚动条
            document.body.style.pointerEvents = 'auto'; // 恢复交互
        };

        const forceRemoveStyles = () => {
            const styles = document.querySelectorAll('*');
            styles.forEach(el => {
                el.style.userSelect = 'auto';
                el.style.pointerEvents = 'auto';
            });
        };

        const observeVipMask = () => {
            // 使用 MutationObserver 动态监听遮罩层的插入
            const observer = new MutationObserver(() => {
                removeVipMask();
            });
            observer.observe(document.body, { childList: true, subtree: true });

            // 在 DOMContentLoaded 时运行一次,移除已有遮罩层
            removeVipMask();
        };

        const removeSpecificEventListeners = () => {
            ['copy', 'cut', 'paste', 'contextmenu', 'selectstart'].forEach(event => {
                document.body.addEventListener(event, e => e.stopImmediatePropagation(), true);
            });
        };

        const unlockCssRestrictions = () => {
            Array.from(document.querySelectorAll('*:not([data-unlock-applied])')).forEach(el => {
                el.style.userSelect = 'auto';
                el.style.pointerEvents = 'auto';
                el.setAttribute('data-unlock-applied', 'true'); // 防止重复设置
            });
        };

        const interceptXHR = () => {
            const rawOpen = XMLHttpRequest.prototype.open;
            XMLHttpRequest.prototype.open = function (method, url, ...rest) {
                this.addEventListener('readystatechange', () => {
                    if (this.readyState === 4) {
                        let response = this.responseText;
                        try {
                            const jsonResponse = JSON.parse(response);
                            if (jsonResponse.data && jsonResponse.data.actions && jsonResponse.data.actions.copy !== 1) {
                                jsonResponse.data.actions.copy = 1;
                                Object.defineProperty(this, 'responseText', { value: JSON.stringify(jsonResponse) });
                                Object.defineProperty(this, 'response', { value: jsonResponse });
                            }
                        } catch (e) {
                            console.error('Failed to modify response:', e);
                        }
                    }
                }, false);
                rawOpen.call(this, method, url, ...rest);
            };
        };

        const customCopyHandler = () => {
            document.addEventListener('keydown', e => {
                if (e.ctrlKey && e.key === 'c') {
                    e.preventDefault();
                    e.stopPropagation();
                    try {
                        document.execCommand('copy');
                        console.log("Content copied to clipboard!");
                    } catch (err) {
                        console.error("Copy operation failed:", err);
                    }
                }
            }, true);
        };

        observeVipMask();
        removeSpecificEventListeners();
        unlockCssRestrictions();
        interceptXHR();
        customCopyHandler();
    }

    // 手动粘贴功能
    let targetElement = null;

    document.addEventListener('keydown', function (event) {
        if (event.ctrlKey && event.key === 'm') {
            event.preventDefault();
            targetElement = document.activeElement;
            createFloatingInputBox();
        }
    });

    function createFloatingInputBox() {
        if (document.getElementById('floatingInputBox')) return;

        const floatingBox = document.createElement('div');
        floatingBox.id = 'floatingInputBox';
        floatingBox.style.position = 'fixed';
        floatingBox.style.top = '20px';
        floatingBox.style.right = '20px';
        floatingBox.style.width = '300px';
        floatingBox.style.padding = '10px';
        floatingBox.style.backgroundColor = 'white';
        floatingBox.style.border = '1px solid black';
        floatingBox.style.zIndex = '10000';

        const closeButton = document.createElement('button');
        closeButton.textContent = '关闭';
        closeButton.style.marginBottom = '10px';
        closeButton.onclick = () => document.body.removeChild(floatingBox);

        const textarea = document.createElement('textarea');
        textarea.style.width = '100%';
        textarea.style.height = '80px';
        textarea.placeholder = '在此粘贴内容,然后按 Enter';
        textarea.addEventListener('keydown', function (e) {
            if (e.key === 'Enter') {
                e.preventDefault();
                const text = textarea.value;
                document.body.removeChild(floatingBox);
                if (targetElement) {
                    typeTextSlowly(targetElement, text);
                }
            } else if (e.key === 'Escape') {
                document.body.removeChild(floatingBox);
            }
        });

        floatingBox.appendChild(closeButton);
        floatingBox.appendChild(textarea);
        document.body.appendChild(floatingBox);
        textarea.focus();
    }

    function typeTextSlowly(element, text) {
        let i = 0;

        function typeChar() {
            if (i < text.length) {
                insertChar(element, text[i]);
                i++;
                requestAnimationFrame(typeChar);
            }
        }
        typeChar();
    }

    function insertChar(element, char) {
        if (element.tagName === 'INPUT' || element.tagName === 'TEXTAREA') {
            const start = element.selectionStart;
            const end = element.selectionEnd;
            const value = element.value;
            element.value = value.substring(0, start) + char + value.substring(end);
            element.selectionStart = element.selectionEnd = start + 1;

            const inputEvent = new Event('input', { bubbles: true });
            element.dispatchEvent(inputEvent);
        } else if (element.isContentEditable) {
            const textNode = document.createTextNode(char);
            const selection = window.getSelection();
            const range = selection.getRangeAt(0);

            range.insertNode(textNode);
            range.setStartAfter(textNode);
            selection.removeAllRanges();
            selection.addRange(range);
        }
    }

    // 初始化
    document.addEventListener('DOMContentLoaded', () => {
        if (isFeishuPage) {
            feishuScript();
        } else {
            universalUnlockScript();
        }
    });
})();