// ==UserScript== // @name 防止未经授权的自动复制 // @version 24 // @description 在非选词复制时显示小红点提示用户以防止未经授权的自动复制,脚本菜单还增加了禁止写入剪贴板功能。 // @grant GM_setClipboard // @grant GM_registerMenuCommand // @grant GM_setValue // @grant GM_getValue // @run-at document-start // @match *://*/* // @namespace https://greasyfork.org/users/452911 // @downloadURL none // ==/UserScript== (function() { 'use strict'; // 获取当前域名 const domain = window.location.hostname; // 获取当前域名对应的脚本启用状态 let isClipboardEnabled = GM_getValue(domain + "_clipboard", true); // 默认启用剪贴板操作 let isCopyEventEnabled = GM_getValue(domain + "_copyEvent", true); // 创建油猴菜单:启用/禁用剪贴板操作,启用/禁用复制事件提示 GM_registerMenuCommand(isClipboardEnabled ? '点击禁止剪贴板写入' : '点击允许剪贴板写入', () => { isClipboardEnabled = !isClipboardEnabled; // 切换剪贴板操作启用状态 GM_setValue(domain + "_clipboard", isClipboardEnabled); // 保存启用状态 toggleClipboardProtection(isClipboardEnabled); // 动态启用/禁用剪贴板操作 window.location.reload(); // 刷新网页 }); GM_registerMenuCommand(isCopyEventEnabled ? '禁用复制事件提示' : '启用复制事件提示', () => { isCopyEventEnabled = !isCopyEventEnabled; // 切换复制事件启用状态 GM_setValue(domain + "_copyEvent", isCopyEventEnabled); // 保存启用状态 if (!isCopyEventEnabled) { window.location.reload(); // 刷新网页 } }); // 初始状态下动态启用或禁用剪贴板操作 toggleClipboardProtection(isClipboardEnabled); if (!isCopyEventEnabled) return; // 如果复制事件提示被禁用,则不执行以下代码 let hasCopied = false; let timeoutId = null; let dot = null; // 处理复制事件 const handleCopy = function(event) { event.preventDefault(); const selection = window.getSelection().toString(); if (!hasCopied && selection.trim().length > 0) { hasCopied = true; createDot(selection); } }; // 创建红色提示点 const createDot = function(selection) { dot = document.createElement('div'); dot.style.width = '20px'; dot.style.height = '20px'; dot.style.zIndex = '9999'; dot.style.background = 'rgba(255, 0, 0, 0.2)'; 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() { if (dot && dot.parentNode) { document.body.removeChild(dot); } hasCopied = false; timeoutId = null; }, 4000); }; // 复制到剪贴板的辅助函数 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) => { copyToClipboard(text); resolve(); }); }; // 监听复制事件 document.addEventListener('copy', handleCopy, { capture: true }); // 监听页面卸载事件,清除定时器 window.addEventListener('beforeunload', function() { if (timeoutId) { clearTimeout(timeoutId); } }); let startX = null; let startY = null; // 监听触摸事件,防止触摸滑动时误触复制 document.addEventListener('touchstart', function(e) { startX = e.touches[0].clientX; startY = e.touches[0].clientY; }); document.addEventListener('touchmove', function(e) { const currentX = e.touches[0].clientX; const currentY = e.touches[0].clientY; const diffX = Math.abs(currentX - startX); const diffY = Math.abs(currentY - startY); if ((diffX > 10 || diffY > 10) && dot) { document.body.removeChild(dot); hasCopied = false; if (timeoutId) { clearTimeout(timeoutId); timeoutId = null; } } }); // 动态禁用剪贴板相关操作 function toggleClipboardProtection(enabled) { if (!enabled) { // 禁用剪贴板操作 ['execCommand', 'writeText', 'write'].forEach(method => { const target = method === 'execCommand' ? document : navigator.clipboard; Object.defineProperty(target, method, { value: () => { console.log(`禁止使用 ${method} 方法`); }, writable: false, configurable: false }); }); } } })();