// ==UserScript== // @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 サイトのほとんどを殺すために渡し、あなたは、コピー切り取り、テキスト、右クリックメニューを選択することは禁止の制限を解除することができます // @author 六斤八两 // @version 1.0.0 // @license LGPLv3 // @match *://*/* // @grant GM_registerMenuCommand // @grant GM_getValue // @grant GM_setValue // @require https://unpkg.com/sweetalert2@10.16.6/dist/sweetalert2.min.js // @run-at document-start // @namespace https://greasyfork.org/users/1446006 // @downloadURL https://update.greasyfork.icu/scripts/535746/%F0%9F%9B%A0%EF%B8%8F%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/535746/%F0%9F%9B%A0%EF%B8%8F%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 = { // 用户自定义排除列表 // 基础黑名单(不可删除) + 用户自定义排除列表 base_blacklist: GM_getValue('base_blacklist', [ 'youtube.com', 'wikipedia.org', 'mail.qq.com', 'translate.google.com' ]), // 合并后的排除列表(仅用于显示) exclude_list: function() { return this.base_blacklist.concat(GM_getValue('exclude_list', [])) .filter((v, i, a) => a.indexOf(v) === i); } }; // 要处理的 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() { // 注册菜单项 const isExcluded = lists.exclude_list().includes(location.host); GM_registerMenuCommand(`当前网站:${isExcluded ? '❌' : '✔️'}`, () => { const currentList = lists.exclude_list(); const newList = isExcluded ? currentList.filter(h => h !== location.host) : [...currentList, location.host]; GM_setValue('exclude_list', newList); window.location.reload(); }); // 状态显示弹窗 GM_registerMenuCommand('📜 当前状态', () => { createPopup(); }); // 如果当前网站在排除列表中则不执行后续逻辑 if (isExcluded) return; // 获取当前域名的规则 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: 318px; min-height: 340px; padding-bottom: 40px; background: #2d2d2d; border: 1px solid #444; border-radius: 12px; box-shadow: 0 4px 20px rgba(0,0,0,0.3); 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; color: #fff; } #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.3); } .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.2); } .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.8; } .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 = `
当前状态
✅ 已处理事件:
${eventNames.join(', ')}
感谢赞赏
排除设置
已排除域名(每行一个):
`; // 添加容器到文档中 document.body.appendChild(container); // 添加保存事件监听 document.getElementById('saveExcludeList').addEventListener('click', () => { const domains = document.getElementById('excludeDomains').value .split('\n') .map(d => d.trim()) .filter(d => d.length > 0); // 分离基础黑名单和用户自定义列表 const baseEntries = domains.filter(d => lists.base_blacklist.includes(d)); const customEntries = domains.filter(d => !lists.base_blacklist.includes(d)); GM_setValue('base_blacklist', baseEntries); GM_setValue('exclude_list', customEntries); window.location.reload(); }); // 窗口控制功能 let isMaximized = false; let originalSize = { width: '480px', height: '350px' }; 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 || '350px' }; 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); } } // 确保在DOM加载完成后初始化 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();