网站限制解除脚本

解锁复制/粘贴/右键,彻底屏蔽 debugger 循环和 eval/Function 注入。

// ==UserScript==
// @name         网站限制解除脚本
// @namespace    https://web.zyxn.dpdns.org
// @version      4.0
// @description  解锁复制/粘贴/右键,彻底屏蔽 debugger 循环和 eval/Function 注入。
// @author       flkGit
// @match        *://*/*
// @run-at       document-start
// @grant        none
// @license MIT
// ==/UserScript==

(function(){
  'use strict';

  // --- 基础解锁:右键/复制/粘贴 + F12保护 ---
  const SENSITIVE_EVENTS = [
    'copy', 'paste', 'cut', 'contextmenu', 'selectstart', 'dragstart',
    'keydown', 'keyup', 'keypress'  // 包含键盘事件保护F12等
  ];

  // 高优先级事件拦截
  for (const ev of SENSITIVE_EVENTS) {
    window.addEventListener(ev, e => {
      // 特殊保护开发者工具快捷键
      if (e.type.startsWith('key')) {
        const isF12 = e.keyCode === 123;
        const isDevTools = e.ctrlKey && e.shiftKey && e.keyCode === 73; // Ctrl+Shift+I
        const isConsole = e.ctrlKey && e.shiftKey && e.keyCode === 74;  // Ctrl+Shift+J
        const isViewSource = e.ctrlKey && e.keyCode === 85;             // Ctrl+U
        const isInspect = e.ctrlKey && e.shiftKey && e.keyCode === 67;  // Ctrl+Shift+C

        if (isF12 || isDevTools || isConsole || isViewSource || isInspect) {
          e.stopImmediatePropagation();
          return; // 让浏览器处理这些快捷键
        }
      }

      // 其他敏感事件全部放行
      e.stopImmediatePropagation();
    }, true);
  }

  // 清理内联事件处理器
  function cleanInline() {
    const inlineEvents = ['oncopy', 'onpaste', 'oncut', 'oncontextmenu', 'onselectstart', 'onkeydown', 'onkeyup'];
    const targets = [document, document.documentElement, document.body].filter(Boolean);

    for (const target of targets) {
      for (const attr of inlineEvents) {
        if (target[attr]) target[attr] = null;
      }
    }
  }

  // 定期清理 + 页面变化时清理
  const cleanTimer = setInterval(cleanInline, 2000);
  if (typeof MutationObserver !== 'undefined') {
    new MutationObserver(cleanInline).observe(document, {childList: true, subtree: true});
  }

  // 页面卸载前清理定时器
  window.addEventListener('beforeunload', () => clearInterval(cleanTimer));

  // 强制CSS样式解锁
  function injectUnlockCSS() {
    if (document.head) {
      const style = document.createElement('style');
      style.textContent = `
        * {
          -webkit-user-select: text !important;
          -moz-user-select: text !important;
          user-select: text !important;
          -webkit-touch-callout: default !important;
          -webkit-user-drag: element !important;
          pointer-events: auto !important;
        }
      `;
      document.head.appendChild(style);
    }
  }

  // 立即注入CSS,DOM加载后再次注入
  injectUnlockCSS();
  document.addEventListener('DOMContentLoaded', injectUnlockCSS);

  // 强制允许 execCommand
  const origExecCommand = document.execCommand;
  document.execCommand = function(cmd, showUI, value) {
    return origExecCommand.call(this, cmd, showUI, value) || true; // 强制返回true
  };

  // === 增强版 Debugger 拦截系统 ===
  function createDebuggerBlocker() {
    const logBlocked = (type, info) => console.warn(`[Debugger Blocked] ${type}:`, info);

    // 1. 重写核心函数
    const originals = {
      eval: window.eval,
      Function: window.Function,
      setTimeout: window.setTimeout,
      setInterval: window.setInterval
    };

    // 检测debugger的正则(更严格)
    const debuggerRegex = /\bdebugger\b/;

    // 重写 eval
    window.eval = function(code) {
      if (typeof code === 'string' && debuggerRegex.test(code)) {
        logBlocked('eval', code.slice(0, 100));
        return undefined;
      }
      return originals.eval.call(this, code);
    };

    // 重写 Function 构造器
    window.Function = function(...args) {
      const code = args[args.length - 1];
      if (typeof code === 'string' && debuggerRegex.test(code)) {
        logBlocked('Function', code.slice(0, 100));
        return () => {}; // 返回无害的空函数
      }
      return originals.Function.apply(this, args);
    };

    // 重写定时器函数
    const wrapTimer = (original, name) => function(callback, delay, ...args) {
      if (typeof callback === 'string' && debuggerRegex.test(callback)) {
        logBlocked(name + ' string', callback.slice(0, 100));
        return original.call(this, () => {}, delay, ...args);
      }

      if (typeof callback === 'function') {
        try {
          const funcStr = callback.toString();
          if (debuggerRegex.test(funcStr)) {
            logBlocked(name + ' function', funcStr.slice(0, 100));
            return original.call(this, () => {}, delay, ...args);
          }
        } catch (e) {
          // 如果toString()失败,可能是native函数,放行
        }
      }

      return original.call(this, callback, delay, ...args);
    };

    window.setTimeout = wrapTimer(originals.setTimeout, 'setTimeout');
    window.setInterval = wrapTimer(originals.setInterval, 'setInterval');

    // 2. 主动清理现有定时器
    let cleanupActive = true;
    const cleanupDebuggers = () => {
      if (!cleanupActive) return;

      try {
        // 获取当前最高的timer ID
        const testId = setTimeout(() => {}, 0);
        clearTimeout(testId);

        // 清理可疑的定时器(延迟很短的)
        for (let i = Math.max(1, testId - 1000); i <= testId; i++) {
          try {
            clearTimeout(i);
            clearInterval(i);
          } catch (e) {}
        }
      } catch (e) {}
    };

    // 启动清理任务
    const cleanupTimer = setInterval(cleanupDebuggers, 3000);

    // 15秒后停止清理
    setTimeout(() => {
      cleanupActive = false;
      clearInterval(cleanupTimer);
      logBlocked('cleanup', '定时器清理任务已完成');
    }, 15000);

    // 3. 保护 console 对象
    try {
      const originalClear = console.clear;
      Object.defineProperty(console, 'clear', {
        value: function() {
          logBlocked('console.clear', '阻止清除控制台');
        },
        writable: false,
        configurable: false
      });
    } catch (e) {}
  }

  // 立即启动debugger拦截
  createDebuggerBlocker();

  // === 页面加载完成后的额外保护 ===
  const finalSetup = () => {
    cleanInline();
    injectUnlockCSS();

    // 移除可能的CSS限制
    const restrictiveStyles = document.querySelectorAll('style, link[rel="stylesheet"]');
    restrictiveStyles.forEach(style => {
      try {
        if (style.textContent && /user-select\s*:\s*none|pointer-events\s*:\s*none/.test(style.textContent)) {
          style.textContent = style.textContent
            .replace(/user-select\s*:\s*none/gi, 'user-select: text')
            .replace(/pointer-events\s*:\s*none/gi, 'pointer-events: auto');
        }
      } catch (e) {}
    });
  };

  // 多个时机执行最终设置
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', finalSetup);
  } else {
    finalSetup();
  }

  window.addEventListener('load', () => setTimeout(finalSetup, 500));

  console.info('[Unlocker v4.0] 已启用:F12保护 + 复制解锁 + Debugger全面拦截');
})();