去除飞书&netshort水印

综合两个脚本,破解飞书&netshort的复制和右键限制

目前為 2024-12-14 提交的版本,檢視 最新版本

// ==UserScript==
// @name         去除飞书&netshort水印
// @namespace    Tampermonkey BETA
// @version      1.0
// @description  综合两个脚本,破解飞书&netshort的复制和右键限制
// @author       向也
// @match        *://*.feishu.cn/*
// @match        *://*.netshort.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=feishu.cn
// @grant        none
// @license      MIT

// ==/UserScript==

(function () {
    'use strict';

    console.log('改进飞书体验已启动');

    // 破解右键限制
    function overrideContextmenu() {
        const originalAddEventListener = document.body.addEventListener;
        document.body.addEventListener = function (type, listener, options) {
            if (type === 'contextmenu') {
                listener = () => true; // 允许右键菜单显示
            }
            originalAddEventListener.call(document.body, type, listener, options);
        };
    }
    overrideContextmenu();

    // 破解复制限制
    function overrideXhrOpen() {
        const originalOpen = XMLHttpRequest.prototype.open;
        XMLHttpRequest.prototype.open = function (...args) {
            const [method, url] = args;
            if (method !== 'POST' || !url.includes('space/api/suite/permission/document/actions/state/')) {
                return originalOpen.apply(this, args);
            }

            this.addEventListener('readystatechange', function () {
                if (this.readyState !== 4) return;
                let response = this.response;
                try {
                    response = JSON.parse(response);
                } catch (e) {}

                if (response?.data?.actions?.copy !== 1) {
                    response.data.actions.copy = 1;

                    Object.defineProperty(this, 'response', {
                        get() {
                            return JSON.stringify(response);
                        }
                    });

                    Object.defineProperty(this, 'responseText', {
                        get() {
                            return JSON.stringify(response);
                        }
                    });
                }
            });

            return originalOpen.apply(this, args);
        };
    }
    overrideXhrOpen();

    // 添加点击复制图片功能
    function addImageCopy() {
        const images = document.querySelectorAll('img');
        images.forEach(image => {
            image.addEventListener('click', () => {
                const img = new Image();
                img.src = image.src;
                img.style.display = 'none';
                document.body.appendChild(img);

                navigator.clipboard.writeImage(img).then(() => {
                    console.log('Image copied to clipboard:', img.src);
                    img.remove();
                }).catch(err => {
                    console.error('Failed to copy image:', err);
                    img.remove();
                });
            });
        });
    }
    addImageCopy();

    // 去除水印的CSS样式
    function removeWatermarks() {
        if (typeof GM_addStyle === 'undefined') {
            this.GM_addStyle = function (aCss) {
                const head = document.getElementsByTagName('head')[0];
                if (head) {
                    const style = document.createElement('style');
                    style.setAttribute('type', 'text/css');
                    style.textContent = aCss;
                    head.appendChild(style);
                }
            };
        }

        const bgImageNone = '{background-image: none !important;}';
        const selectors = [
            '[class*="watermark"]',
            '[style*="pointer-events: none"]',
            '.ssrWaterMark',
            'body>div>div>div>div[style*="position: fixed"]:not(:has(*))',
            '[class*="TIAWBFTROSIDWYKTTIAW"]',
            'body>div[style*="position: fixed"]:not(:has(*))',
            '#watermark-cache-container',
            'body>div[style*="inset: 0px;"]:not(:has(*))',
            '.chatMessages>div[style*="inset: 0px;"]'
        ];

        selectors.forEach(selector => {
            GM_addStyle(`${selector}${bgImageNone}`);
        });
    }
    removeWatermarks();
})();