// ==UserScript== // @name anti-rickroll // @version 12.5 // @description fixed bing // @author dext // @match *://*/* // @grant GM_xmlhttpRequest // @grant GM_addStyle // @connect anti-rickroll.dext.top // @run-at document-start // @namespace http://tampermonkey.net/ // @downloadURL none // ==/UserScript== (function() { 'use strict'; const API_ENDPOINT = "https://anti-rickroll.dext.top"; const cache = new Map(); const queue = []; let activeRequests = 0; const MAX_CONCURRENT = 3; // --- 0. 免死金牌判定 --- if (window.location.hash.includes('force-pass') || window.location.search.includes('force-pass')) { return; } GM_addStyle(` #rick-breaker-overlay { position: fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.98); z-index:2147483647; display:flex; justify-content:center; align-items:center; backdrop-filter:blur(25px); } .rick-card { background:#fff; padding:40px; border-radius:24px; width:350px; text-align:center; border:6px solid #ff4444; box-shadow: 0 20px 60px rgba(0,0,0,0.8); font-family: sans-serif; } .rick-btn { padding:15px; border-radius:12px; cursor:pointer; border:none; font-weight:bold; width:100%; margin-top:15px; font-size:16px; transition: 0.2s; } .btn-safe { background:#eee; color:#333; } .btn-safe:hover { background:#ddd; } .btn-danger { background:#ff4444; color:#fff; font-size:11px; opacity:0.5; } .btn-danger:hover { opacity:1; } #rick-report-btn { position: fixed; bottom: 20px; left: 20px; z-index: 2147483646; background: rgba(0,0,0,0.7); color: white; padding: 8px 15px; border-radius: 20px; cursor: pointer; font-size: 13px; backdrop-filter: blur(5px); border: 1px solid rgba(255,255,255,0.2); display: flex; align-items: center; gap: 8px; } #rick-report-btn:hover { background: #ff4444; } a.rickroll-danger { outline: 3px dashed #ff4444 !important; outline-offset: 2px; background: rgba(255,0,0,0.1) !important; } `); // --- 1. 工具函数:脱壳与内链判定 --- function getCleanUrl(url) { try { const u = new URL(url); // 谷歌 & 百度脱壳 if (u.hostname.includes('google.com') && u.searchParams.has('q')) return u.searchParams.get('q'); if (u.hostname.includes('baidu.com') && u.searchParams.has('url')) return u.searchParams.get('url'); // 必应(Bing) Base64 深度脱壳 if (u.hostname.includes('bing.com') && u.pathname.includes('/ck/a')) { let rawU = u.searchParams.get('u'); if (rawU) { try { // 去掉 a1 前缀并解码 return atob(rawU.substring(2).replace(/-/g, '+').replace(/_/g, '/')); } catch (e) { return url; } } } return u.origin + u.pathname + u.search; } catch (e) { return url; } } function isInternal(url) { try { const t = new URL(url); const curr = window.location.hostname; // 必应重定向链接不视为内链 if (curr.includes('bing.com') && t.pathname.includes('/ck/a')) return false; return t.hostname === curr; } catch (e) { return true; } } function silenceMedia() { document.querySelectorAll('video, audio').forEach(m => { m.pause(); m.muted = true; }); } // --- 2. 智能退出逻辑 --- function smartExit(isIncoming) { if (!isIncoming) { document.getElementById('rick-breaker-overlay')?.remove(); return; } const referrer = document.referrer; if (referrer && !referrer.includes(window.location.hostname)) { window.location.replace(referrer); } else if (window.history.length > 1) { window.history.back(); } else { window.close(); setTimeout(() => { window.location.href = "about:blank"; }, 150); } } // --- 3. UI 渲染逻辑 --- function renderOverlay(title, url, isIncoming = false) { if (document.getElementById('rick-breaker-overlay')) return; const silencer = setInterval(silenceMedia, 200); const overlay = document.createElement('div'); overlay.id = 'rick-breaker-overlay'; overlay.innerHTML = `
🛑

${title}

此路径被识别为 Rickroll

`; (document.body || document.documentElement).appendChild(overlay); document.getElementById('r-back').onclick = () => { clearInterval(silencer); smartExit(isIncoming); }; document.getElementById('r-go').onclick = () => { clearInterval(silencer); overlay.remove(); const separator = url.includes('#') ? '&' : '#'; const jumpUrl = url + separator + 'force-pass'; if (isIncoming) { window.location.replace(jumpUrl); } else { const a = document.createElement('a'); a.href = jumpUrl; a.target = "_blank"; a.click(); } }; } // --- 4. 扫描与并发控制 --- function processQueue() { if (queue.length === 0 || activeRequests >= MAX_CONCURRENT) return; const url = queue.shift(); activeRequests++; GM_xmlhttpRequest({ method: "POST", url: API_ENDPOINT, data: JSON.stringify({ url }), headers: { "Content-Type": "application/json" }, onload: (res) => { try { const d = JSON.parse(res.responseText); cache.set(url, { isRickroll: !!d.isRickroll, status: 'done' }); if (d.isRickroll) { document.querySelectorAll(`a`).forEach(a => { if(getCleanUrl(a.href) === url) a.classList.add('rickroll-danger'); }); } } catch (e) {} activeRequests--; processQueue(); }, onerror: () => { activeRequests--; processQueue(); } }); } function scan() { const EX = /\.(jpg|jpeg|png|gif|css|js|woff|zip|pdf|mp4)($|\?)/i; document.querySelectorAll('a[href]').forEach(a => { const url = getCleanUrl(a.href); if (!url.startsWith('http') || isInternal(url) || EX.test(url) || cache.has(url)) return; cache.set(url, { isRickroll: false, status: 'pending' }); queue.push(url); }); processQueue(); } // --- 5. 事件监听:点击拦截 --- window.addEventListener('click', (e) => { const a = e.target.closest('a'); if (!a || !a.href.startsWith('http')) return; const url = getCleanUrl(a.href); if (isInternal(url) || a.dataset.rickSafe === '1' || url.includes('force-pass')) return; const res = cache.get(url); if (res && res.status === 'done' && res.isRickroll) { e.preventDefault(); e.stopPropagation(); renderOverlay("链路风险拦截", url, false); return; } e.preventDefault(); e.stopPropagation(); GM_xmlhttpRequest({ method: "POST", url: API_ENDPOINT, data: JSON.stringify({ url }), headers: { "Content-Type": "application/json" }, onload: (res) => { try { const d = JSON.parse(res.responseText); cache.set(url, { isRickroll: !!d.isRickroll, status: 'done' }); if (d.isRickroll) renderOverlay("实时风险拦截", url, false); else { a.dataset.rickSafe = '1'; a.click(); } } catch (e) { a.dataset.rickSafe = '1'; a.click(); } } }); }, true); // --- 6. 举报按钮逻辑 --- function createReportButton() { if (document.getElementById('rick-report-btn') || sessionStorage.getItem('rick-btn-hidden') === '1') return; const btn = document.createElement('div'); btn.id = 'rick-report-btn'; btn.innerHTML = `🛡️ 我被骗了!×`; document.body.appendChild(btn); document.getElementById('rick-do-report').onclick = () => { const b = document.getElementById('rick-report-btn'); b.innerText = "🔍 AI 正在存入云端..."; GM_xmlhttpRequest({ method: "POST", url: API_ENDPOINT, data: JSON.stringify({ url: window.location.href, isFeedback: true, title: document.title, snippet: document.body ? document.body.innerText.substring(0, 800) : "" }), headers: { "Content-Type": "application/json" }, onload: (res) => { try { const d = JSON.parse(res.responseText); if (d.isRickroll) { b.innerText = "✅ 举报成功!"; setTimeout(() => renderOverlay("举报生效拦截", window.location.href, true), 800); } else { b.innerText = "❌ AI 判定安全"; setTimeout(() => b.remove(), 2000); } } catch(e) { b.remove(); } } }); }; document.getElementById('rick-close-report').onclick = (e) => { e.stopPropagation(); btn.remove(); sessionStorage.setItem('rick-btn-hidden', '1'); }; } // --- 7. 入境与自启动 --- function checkCurrent() { const url = window.location.href; if (url.length < 25 || /google|baidu|bing/.test(window.location.hostname)) return; GM_xmlhttpRequest({ method: "POST", url: API_ENDPOINT, data: JSON.stringify({ url }), headers: { "Content-Type": "application/json" }, onload: (res) => { try { const d = JSON.parse(res.responseText); if (d.isRickroll) { window.stop(); renderOverlay("入境风险拦截", url, true); } } catch (e) {} } }); } checkCurrent(); window.addEventListener('load', () => { createReportButton(); setInterval(scan, 4000); }); })();