// ==UserScript== // @name 防止未经授权的自动复制 // @version 17 // @author ChatGPT // @description 在非选词复制时显示小红点提示用户以防止未经授权的自动复制。 // @grant GM_setClipboard // @run-at document-start // @match *://*/* // @namespace https://greasyfork.org/users/452911 // @downloadURL none // ==/UserScript== (function() { 'use strict'; let hasCopied = false; let timeoutId = null; let dot = null; const handleCopy = function(event) { event.preventDefault(); const selection = window.getSelection().toString(); if (!hasCopied) { hasCopied = true; dot = document.createElement('div'); dot.style.width = '20px'; dot.style.height = '20px'; dot.style.zIndex = '9999'; dot.style.background = 'red'; dot.style.background = 'rgba(255, 0, 0, 0.2)'; // 将小红点透明度改为20% dot.style.borderRadius = '50%'; dot.style.position = 'fixed'; dot.style.top = '50%'; dot.style.right = '10px'; dot.style.transform = 'translateY(-50%)'; dot.style.cursor = 'pointer'; dot.addEventListener('click', function() { const shouldCopy = confirm(selection); if (shouldCopy) { if (typeof GM_setClipboard === "function") { GM_setClipboard(selection); } else { copyToClipboard(selection); } } document.body.removeChild(dot); hasCopied = false; }); document.body.appendChild(dot); timeoutId = setTimeout(function() { document.body.removeChild(dot); hasCopied = false; timeoutId = null; }, 2000); // 设置延时时间,单位为毫秒 } }; const handleSelectionChange = function() { const selection = window.getSelection().toString(); if (selection.length === 0) { document.addEventListener('copy', handleCopy, { capture: true }); event.stopPropagation(); } else { document.removeEventListener('copy', handleCopy, { capture: true }); event.stopPropagation(); } }; const copyToClipboard = function(text) { const textArea = document.createElement('textarea'); textArea.value = text; document.body.appendChild(textArea); textArea.select(); document.execCommand('copy'); document.body.removeChild(textArea); }; // 重写 navigator.clipboard.writeText navigator.clipboard.writeText = function(text) { return new Promise((resolve, reject) => { const textArea = document.createElement('textarea'); textArea.value = text; document.body.appendChild(textArea); textArea.select(); try { const successful = document.execCommand('copy'); if (successful) { resolve(); } else { reject(new Error('Failed to copy text to clipboard')); } } catch (err) { reject(err); } finally { document.body.removeChild(textArea); } }); }; const observeMutations = function() { const observer = new MutationObserver(function(mutationsList) { mutationsList.forEach(function(mutation) { if (mutation.type === 'childList') { const addedNodes = mutation.addedNodes; const removedNodes = mutation.removedNodes; addedNodes.forEach(function(node) { if (node.nodeType === Node.ELEMENT_NODE) { node.addEventListener('copy', handleCopy, { capture: true }); } }); removedNodes.forEach(function(node) { if (node.nodeType === Node.ELEMENT_NODE) { node.removeEventListener('copy', handleCopy, { capture: true }); } }); } }); }); observer.observe(document.body, { childList: true, subtree: true }); }; document.addEventListener('copy', handleCopy, { capture: true }); document.addEventListener('selectionchange', handleSelectionChange); window.addEventListener('scroll', function() { if (dot) { dot.style.display = 'none'; hasCopied = false; // 隐藏后重置复制状态 clearTimeout(timeoutId); // 取消延时隐藏 } }); // 在页面卸载前清除延时器 window.addEventListener('beforeunload', function() { if (timeoutId) { clearTimeout(timeoutId); } }); observeMutations(); // 添加手势操作 let startY, endY; document.addEventListener('touchstart', function(e) { startY = e.touches[0].clientY; }); document.addEventListener('touchend', function(e) { endY = e.changedTouches[0].clientY; if (startY - endY > 50 && dot) { dot.style.display = 'none'; hasCopied = false; // 隐藏后重置复制状态 clearTimeout(timeoutId); // 取消延时隐藏 } }); })();