Greasy Fork

Greasy Fork is available in English.

防止未经授权的自动复制

在非选词复制时显示小红点提示用户以防止未经授权的自动复制。

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

// ==UserScript==
// @name 防止未经授权的自动复制
// @version 20
// @author ChatGPT
// @description 在非选词复制时显示小红点提示用户以防止未经授权的自动复制。
// @grant GM_setClipboard
// @run-at document-start
// @match *://*/*
// @namespace http://greasyfork.icu/users/452911
// ==/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 && 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 handleSelectionChange = function() {
    if (window.getSelection().toString().trim().length === 0) {
      // 当没有选中文本时,重新启用复制事件监听
      document.addEventListener('copy', handleCopy, { capture: true });
    } else {
      // 当有选中文本时,移除复制事件监听,避免在selectionchange时触发
      document.removeEventListener('copy', handleCopy, { capture: true });
    }
  };

  document.addEventListener('selectionchange', handleSelectionChange);

  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;
      }
    }
  });
})();