// ==UserScript== // @namespace https://www.github.com/Cat7373/ // @name 网页限制解除 // @name:en Remove web limits // @name:zh 网页限制解除 // @name:zh-CN 网页限制解除 // @name:zh-TW 網頁限制解除 // @name:ja ウェブの規制緩和 // @description 通杀大部分网站,可以解除禁止复制、剪切、选择文本、右键菜单的限制。 // @description:en Pass to kill most of the site, you can lift the restrictions prohibited to copy, cut, select the text, right-click menu. // @description:zh 通杀大部分网站,可以解除禁止复制、剪切、选择文本、右键菜单的限制。 // @description:zh-CN 通杀大部分网站,可以解除禁止复制、剪切、选择文本、右键菜单的限制。 // @description:zh-TW 通殺大部分網站,可以解除禁止復制、剪切、選擇文本、右鍵菜單的限制。 // @description:ja サイトのほとんどを殺すために渡し、あなたは、コピー切り取り、テキスト、右クリックメニューを選択することは禁止の制限を解除することができます。 // @homepageURL https://cat7373.github.io/remove-web-limits/ // @supportURL https://github.com/Cat7373/remove-web-limits/issues/ // @author Cat73 // @version 1.3 // @license LGPLv3 // @compatible chrome Chrome_46.0.2490.86 + TamperMonkey + 脚本_1.3 测试通过 // @compatible firefox Firefox_42.0 + GreaseMonkey + 脚本_1.2.1 测试通过 // @compatible opera Opera_33.0.1990.115 + TamperMonkey + 脚本_1.1.3 测试通过 // @compatible safari 未测试 // @match *://*/* // @grant none // @run-at document-start // @downloadURL https://update.greasyfork.icu/scripts/533931/%E7%BD%91%E9%A1%B5%E9%99%90%E5%88%B6%E8%A7%A3%E9%99%A4.user.js // @updateURL https://update.greasyfork.icu/scripts/533931/%E7%BD%91%E9%A1%B5%E9%99%90%E5%88%B6%E8%A7%A3%E9%99%A4.meta.js // ==/UserScript== (function() { 'use strict'; // 域名规则列表 var rules = { black_rule: { name: "black", hook_eventNames: "", unhook_eventNames: "" }, default_rule: { name: "default", hook_eventNames: "contextmenu|select|selectstart|copy|cut|dragstart", unhook_eventNames: "mousedown|mouseup|keydown|keyup", dom0: true, hook_addEventListener: true, hook_preventDefault: true, hook_set_returnValue: true, add_css: true } }; // 域名列表 var lists = { // 黑名单 black_list: [ /.*\.youtube\.com.*/, /.*\.wikipedia\.org.*/, /mail\.qq\.com.*/, /translate\.google\..*/ ] }; // 要处理的 event 列表 var hook_eventNames, unhook_eventNames, eventNames; // 储存名称 var storageName = getRandStr('qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM', parseInt(Math.random() * 12 + 8)); // 储存被 Hook 的函数 var EventTarget_addEventListener = EventTarget.prototype.addEventListener; var document_addEventListener = document.addEventListener; var Event_preventDefault = Event.prototype.preventDefault; // Hook addEventListener proc function addEventListener(type, func, useCapture) { var _addEventListener = this === document ? document_addEventListener : EventTarget_addEventListener; if(hook_eventNames.indexOf(type) >= 0) { _addEventListener.apply(this, [type, returnTrue, useCapture]); } else if(this && unhook_eventNames.indexOf(type) >= 0) { var funcsName = storageName + type + (useCapture ? 't' : 'f'); if(this[funcsName] === undefined) { this[funcsName] = []; _addEventListener.apply(this, [type, useCapture ? unhook_t : unhook_f, useCapture]); } this[funcsName].push(func); } else { _addEventListener.apply(this, arguments); } } // 清理循环 function clearLoop() { var elements = getElements(); for(var i in elements) { for(var j in eventNames) { var name = 'on' + eventNames[j]; if(elements[i][name] !== null && elements[i][name] !== onxxx) { if(unhook_eventNames.indexOf(eventNames[j]) >= 0) { elements[i][storageName + name] = elements[i][name]; elements[i][name] = onxxx; } else { elements[i][name] = null; } } } } } // 返回true的函数 function returnTrue(e) { return true; } function unhook_t(e) { return unhook(e, this, storageName + e.type + 't'); } function unhook_f(e) { return unhook(e, this, storageName + e.type + 'f'); } function unhook(e, self, funcsName) { var list = self[funcsName]; for(var i in list) { list[i](e); } e.returnValue = true; return true; } function onxxx(e) { var name = storageName + 'on' + e.type; this[name](e); e.returnValue = true; return true; } // 获取随机字符串 function getRandStr(chs, len) { var str = ''; while(len--) { str += chs[parseInt(Math.random() * chs.length)]; } return str; } // 获取所有元素 包括document function getElements() { var elements = Array.prototype.slice.call(document.getElementsByTagName('*')); elements.push(document); return elements; } // 添加css function addStyle(css) { var style = document.createElement('style'); style.innerHTML = css; document.head.appendChild(style); } // 获取目标域名应该使用的规则 function getRule(url) { function testUrl(list, url) { for(var i in list) { if(list[i].test(url)) { return true; } } return false; } if(testUrl(lists.black_list, url)) { return rules.black_rule; } return rules.default_rule; } // 初始化 function init() { // 获取当前域名的规则 var url = window.location.host + window.location.pathname; var rule = getRule(url); // 设置 event 列表 hook_eventNames = rule.hook_eventNames.split("|"); // TODO Allowed to return value unhook_eventNames = rule.unhook_eventNames.split("|"); eventNames = hook_eventNames.concat(unhook_eventNames); // 调用清理 DOM0 event 方法的循环 if(rule.dom0) { setInterval(clearLoop, 30 * 1000); setTimeout(clearLoop, 2500); window.addEventListener('load', clearLoop, true); clearLoop(); } // hook addEventListener if(rule.hook_addEventListener) { EventTarget.prototype.addEventListener = addEventListener; document.addEventListener = addEventListener; } // hook preventDefault if(rule.hook_preventDefault) { Event.prototype.preventDefault = function() { if(eventNames.indexOf(this.type) < 0) { Event_preventDefault.apply(this, arguments); } }; } // Hook set returnValue if(rule.hook_set_returnValue) { Event.prototype.__defineSetter__('returnValue', function() { if(this.returnValue !== true && eventNames.indexOf(this.type) >= 0) { this.returnValue = true; } }); } console.debug('url: ' + url, 'storageName:' + storageName, 'rule: ' + rule.name); // 添加CSS if(rule.add_css) { addStyle(` html, * { -webkit-user-select:text!important; -moz-user-select:text!important; user-select:text!important; -ms-user-select:text!important; -khtml-user-select:text!important; } /* 悬浮窗样式 */ #rml-popup { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 480px; height: 380px; background: #f8f9fa; border: 1px solid #007bff; border-radius: 12px; box-shadow: 0 4px 20px rgba(0,0,0,0.15); z-index: 9999; font-family: "微软雅黑", sans-serif; padding: 20px; cursor: grab; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; backdrop-filter: blur(4px); touch-action: none; overflow: auto; } #rml-popup * { user-select: none !important; -webkit-user-select: none !important; -moz-user-select: none !important; -ms-user-select: none !important; } #rml-popup:active { cursor: grabbing; box-shadow: 0 8px 30px rgba(0,0,0,0.2); } .window-controls { position: absolute; top: 5px; right: 5px; display: flex; gap: 8px; } .control-btn { width: 24px; height: 24px; border-radius: 50%; border: none; cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: 14px; color: white; transition: transform 0.2s ease, opacity 0.2s ease; box-shadow: 0 2px 4px rgba(0,0,0,0.1); } .close-btn { background: #ff5f57; } .min-btn { background: #ffbd2e; } .max-btn { background: #28c940; } .control-btn:hover { filter: brightness(0.9); } .collapsed { height: 60px !important; overflow: hidden; opacity: 0.9; } .collapsed .input-group, .collapsed .platform-buttons, .collapsed .donate-section, .collapsed .warning { display: none; } .collapsed .window-controls { top: 18px; } `); } // 创建控制弹窗 function createPopup() { // 创建容器并添加控制按钮 const container = document.createElement('div'); container.id = 'rml-popup'; container.innerHTML = `
`; document.body.appendChild(container); // 窗口控制功能 let isMaximized = false; let originalSize = { width: '480px', height: '380px' }; container.querySelector('.min-btn').addEventListener('click', () => { container.classList.toggle('collapsed'); }); container.querySelector('.max-btn').addEventListener('click', () => { if (!isMaximized) { originalSize = { width: container.style.width || '480px', height: container.style.height || '380px' }; container.style.width = '95vw'; container.style.height = '95vh'; isMaximized = true; } else { container.style.width = originalSize.width; container.style.height = originalSize.height; isMaximized = false; } }); container.querySelector('.close-btn').addEventListener('click', () => { container.remove(); }); // 优化后的拖拽功能 let isDragging = false; let startX, startY, initialX, initialY; const handleMouseDown = (e) => { if (e.target.closest('button')) return; isDragging = true; startX = e.clientX; startY = e.clientY; initialX = container.offsetLeft; initialY = container.offsetTop; container.style.transition = 'none'; }; const handleMouseMove = (e) => { if (!isDragging) return; const dx = e.clientX - startX; const dy = e.clientY - startY; // 边界检测 let newX = initialX + dx; let newY = initialY + dy; // 全屏拖动范围 newX = initialX + dx; newY = initialY + dy; container.style.left = `${newX}px`; container.style.top = `${newY}px`; }; const handleMouseUp = () => { if (!isDragging) return; isDragging = false; container.style.transition = 'none'; }; container.addEventListener('mousedown', handleMouseDown); document.addEventListener('mousemove', handleMouseMove); document.addEventListener('mouseup', handleMouseUp); document.addEventListener('mouseleave', handleMouseUp); } createPopup(); } // 确保在DOM加载完成后初始化 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();