// ==UserScript== // @name 复制授权拦截器 // @namespace https://viayoo.com/ // @version 2.61 // @description 复制必弹窗,2次允许后开始自由复制,3次拒绝永久禁用(变灰,点击灰点恢复变红),点击小红点恢复,红绿切换自由复制。 // @author Aloazny & Deepseek // @match *://*/* // @run-at document-start // @icon data:image/png;base64,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 // @grant GM_setClipboard // @license MIT // ==/UserScript== (function () { const KEY = 'copyAuth:v2'; if (window[KEY]) return; window[KEY] = true; let denyCount = 0, allowCount = 0, enabled = true, freeCopyMode = false, isShowingModal = false; const MAX_DENY = 3, AUTO_FREE_AFTER_ALLOW = 2; let dot = null, hideTimer = null; const safeSetClipboard = (text) => { return new Promise((resolve, reject) => { if (typeof GM_setClipboard === 'function') { try { GM_setClipboard(text); resolve(); return; } catch (err) {} } const ta = document.createElement('textarea'); ta.value = text; ta.style = 'position:fixed;opacity:0;pointer-events:none;'; document.body.appendChild(ta); ta.select(); try { const ok = document.execCommand('copy'); document.body.removeChild(ta); ok ? resolve() : reject(); } catch (err) { document.body.removeChild(ta); reject(err); } }); }; const showConfirm = (msg, txt = '') => { if (isShowingModal) return Promise.resolve(false); return new Promise(r => { isShowingModal = true; const modal = document.createElement('div'), dialog = document.createElement('div'), title = document.createElement('h3'), pre = document.createElement('div'), btns = document.createElement('div'), allow = document.createElement('button'), deny = document.createElement('button'); modal.style.cssText = 'position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.5);display:flex;align-items:center;justify-content:center;z-index:2147483647;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;backdrop-filter:blur(8px);padding:16px;box-sizing:border-box;'; dialog.style.cssText = 'background:rgba(255,255,255,.94);border-radius:18px;width:88vw;max-width:420px;text-align:center;box-shadow:0 12px 40px rgba(0,0,0,.25);display:flex;flex-direction:column;gap:16px;border:1px solid rgba(0,0,0,.06);overflow:hidden;'; title.style.cssText = 'margin:0;padding:0 20px;font-size:18px;font-weight:700;color:#111;line-height:1.3;'; pre.style.cssText = 'margin:0 20px;padding:14px;background:#f8f8f8;border-radius:12px;font-family:monospace;font-size:13px;color:#111;max-height:140px;overflow:auto;word-break:break-all;display:' + (txt?'block':'none') + ';line-height:1.4;'; btns.style.cssText = 'display:flex;gap:12px;margin:0 20px;padding-bottom:8px;'; allow.style.cssText = 'flex:1;height:48px;border:none;border-radius:14px;background:#007AFF;color:#fff;font-size:16px;font-weight:600;cursor:pointer;box-shadow:0 4px 14px rgba(0,122,255,.35);transition:transform .12s;'; deny.style.cssText = 'flex:1;height:48px;border:none;border-radius:14px;background:#FF3B30;color:#fff;font-size:16px;font-weight:600;cursor:pointer;box-shadow:0 4px 14px rgba(255,59,48,.35);transition:transform .12s;'; title.textContent = msg; pre.textContent = txt.slice(0,200)+(txt.length>200?'...':''); allow.textContent='允许'; deny.textContent='拒绝'; allow.onclick = () => { clean(); r(true); }; deny.onclick = () => { clean(); r(false); }; modal.onclick = e => e.target===modal && deny.onclick(); const clean = () => { modal.remove(); isShowingModal = false; }; ['touchstart','mousedown'].forEach(ev => { allow.addEventListener(ev, () => allow.style.transform = 'translateY(1px)', {passive:true}); deny.addEventListener(ev, () => deny.style.transform = 'translateY(1px)', {passive:true}); document.addEventListener(ev==='touchstart'?'touchend':'mouseup', () => { allow.style.transform = deny.style.transform = ''; }, {once:true, passive:true}); }); dialog.append(title, pre, btns); btns.append(deny, allow); modal.appendChild(dialog); document.body.appendChild(modal); allow.focus(); }); }; const updateDot = () => { if (!dot) return; dot.style.backgroundColor = freeCopyMode ? '#34C759' : (!enabled ? '#8E8E93' : '#FF3B30'); }; const showDot = () => { if (dot) { clearTimeout(hideTimer); return; } dot = document.createElement('div'); dot.style.cssText = 'position:fixed;bottom:45%;right:10px;width:20px;height:20px;border-radius:10px;background:#FF3B30;z-index:2147483647;opacity:0;transform:scale(0);border:2px solid #fff;box-shadow:0 2px 8px rgba(0,0,0,.3);transition:all .3s cubic-bezier(0.34,1.56,0.64,1);cursor:pointer;touch-action:none;'; document.body.appendChild(dot); requestAnimationFrame(() => { dot.style.opacity = '.8'; dot.style.transform = 'scale(1)'; }); updateDot(); let taps = 0, timer = null; const handleTap = () => { taps++; clearTimeout(timer); timer = setTimeout(() => { if (taps === 1) { if (enabled && !freeCopyMode) { freeCopyMode = true; enabled = true; updateDot(); } else if (freeCopyMode) { freeCopyMode = false; updateDot(); } else { enabled = true; denyCount = 0; updateDot(); } } else if (taps === 2) { freeCopyMode = enabled = true; denyCount = 0; updateDot(); } taps = 0; }, 300); }; dot.onclick = handleTap; dot.ontouchstart = e => { e.preventDefault(); handleTap(); }; }; const tryAutoFreeOnAllow = () => { allowCount++; if (allowCount >= AUTO_FREE_AFTER_ALLOW && !freeCopyMode) { freeCopyMode = true; enabled = true; if (dot) updateDot(); } }; const hideDotIfNeeded = () => { if (!dot) return; clearTimeout(hideTimer); if (freeCopyMode || !enabled) return; hideTimer = setTimeout(() => { if (dot) { dot.remove(); dot = null; } }, 3000); }; const setupCopyListener = (doc, win) => { doc.addEventListener('copy', e => { const sel = win.getSelection().toString().trim(); if (!sel) return; const fake = { setData: () => {}, getData: () => '', types: [] }; try { Object.defineProperty(e, 'clipboardData', { value: fake, writable: false }); } catch (err) {} e.preventDefault(); e.stopImmediatePropagation(); showDot(); if (!enabled || denyCount >= MAX_DENY) { hideDotIfNeeded(); return; } if (freeCopyMode) { safeSetClipboard(sel).catch(() => {}); hideDotIfNeeded(); return; } showConfirm('允许复制内容?', sel).then(ok => { if (ok) { safeSetClipboard(sel).catch(() => {}); tryAutoFreeOnAllow(); } else { denyCount++; if (denyCount >= MAX_DENY) { enabled = false; updateDot(); } } hideDotIfNeeded(); }); }, { capture: true, passive: false }); }; const init = () => { setupCopyListener(document, window); const obs = new MutationObserver(m => { for (const r of m) for (const n of r.addedNodes) if (n.nodeType === 1 && n.tagName === 'IFRAME') try { const d = n.contentDocument; if (d) setupCopyListener(d, n.contentWindow); } catch(e) {} }); obs.observe(document.documentElement, { childList: true, subtree: true }); document.querySelectorAll('iframe').forEach(iframe => { try { const d = iframe.contentDocument; if (d) setupCopyListener(d, iframe.contentWindow); } catch(e) {} }); }; if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => setTimeout(init, 0)); } else { setTimeout(init, 0); } })();