// ==UserScript== // @name anti-rickroll // @version 12.6 // @description 申诉 // @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:360px; 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; } .btn-appeal { background: transparent; color: #888; font-size: 12px; margin-top: 10px; text-decoration: underline; cursor: pointer; border: none; } #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; } 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'); if (u.hostname.includes('bing.com') && u.pathname.includes('/ck/a')) { let rawU = u.searchParams.get('u'); if (rawU) { try { return atob(rawU.substring(2).replace(/-/g, '+').replace(/_/g, '/')); } catch (e) {} } } 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; }); } function smartExit(isIncoming) { if (!isIncoming) { document.getElementById('rick-breaker-overlay')?.remove(); return; } if (document.referrer && !document.referrer.includes(window.location.hostname)) { window.location.replace(document.referrer); } else if (window.history.length > 1) { window.history.back(); } else { window.close(); setTimeout(() => { window.location.href = "about:blank"; }, 150); } } // --- 2. 申诉逻辑 --- function appealRickroll(url, btnElement) { const originalText = btnElement.innerText; btnElement.innerText = "正在提交申诉..."; btnElement.disabled = true; GM_xmlhttpRequest({ method: "POST", url: API_ENDPOINT, data: JSON.stringify({ url: url, isAppeal: true, title: document.title, snippet: document.body ? document.body.innerText.substring(0, 500) : "" }), headers: { "Content-Type": "application/json" }, onload: (res) => { const d = JSON.parse(res.responseText); if (!d.isRickroll) { btnElement.innerText = "✅ 申诉成功!"; setTimeout(() => { window.location.href = url + (url.includes('#') ? '&' : '#') + 'force-pass'; }, 1000); } else { btnElement.innerText = "❌ AI 依然认为是 Rickroll"; setTimeout(() => { btnElement.innerText = originalText; btnElement.disabled = false; }, 2000); } } }); } // --- 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 = `
此链接已被云端标记为 Rickroll。