Greasy Fork

Greasy Fork is available in English.

anti-rickroll

Fuckrickroll

当前为 2026-02-07 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         anti-rickroll
// @namespace    http://tampermonkey.net/
// @version      11.2
// @description  Fuckrickroll
// @author       dext
// @match        *://*/*
// @grant        GM_xmlhttpRequest
// @grant        GM_addStyle
// @connect      anti-rickroll.dext.top
// @run-at       document-start
// ==/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;

    // 标记位检测:如果 URL 包含 #force-pass,则当前页面彻底不扫描、不拦截
    if (window.location.hash.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.85); z-index:2147483647; display:flex; justify-content:center; align-items:center; backdrop-filter:blur(20px); }
        .rick-card { background:#fff; padding:40px; border-radius:24px; width:350px; text-align:center; border:5px solid #ff4444; box-shadow: 0 20px 50px rgba(0,0,0,0.5); font-family: sans-serif; }
        .rick-btn { padding:14px; border-radius:12px; cursor:pointer; border:none; font-weight:bold; width:100%; margin-top:12px; font-size:15px; transition: 0.2s; }
        .btn-safe { background:#f0f0f0; color:#333; }
        .btn-danger { background:#ff4444; color:#fff; font-size:11px; opacity:0.6; }
        .btn-danger:hover { opacity:1; }
        a.rickroll-danger { outline: 2px dashed #ff4444 !important; outline-offset: 2px; background: rgba(255,0,0,0.1) !important; }
    `);

    // 辅助:停止页面一切媒体播放
    function silencePage() {
        document.querySelectorAll('video, audio').forEach(m => {
            m.pause();
            m.muted = true;
        });
    }

    // 1. 脱壳逻辑
    function getRealUrl(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');
        } catch (e) {}
        return url;
    }

    // 2. 核心拦截渲染 (支持新标签页和当前页)
    function renderOverlay(title, url, isIncoming = false) {
        if (document.getElementById('rick-breaker-overlay')) return;

        // 持续静音检测
        const silencer = setInterval(silencePage, 200);

        const overlay = document.createElement('div');
        overlay.id = 'rick-breaker-overlay';
        overlay.innerHTML = `
            <div class="rick-card">
                <div style="font-size:50px">🚫</div>
                <h2 style="color:#ff4444; margin:10px 0;">${title}</h2>
                <p style="color:#666; font-size:14px;">目标已被识别为 <b>Rickroll</b>。<br>页面已被安全冻结。</p>
                <button class="rick-btn btn-safe" id="r-back">立刻返回</button>
                <button class="rick-btn btn-danger" id="r-go">我非要看 (不再拦截)</button>
            </div>`;

        // 针对“入境拦截”,直接附加到 html 上
        (document.body || document.documentElement).appendChild(overlay);

        document.getElementById('r-back').onclick = () => {
            if (isIncoming && window.history.length > 1) {
                window.history.back();
            } else {
                overlay.remove();
                clearInterval(silencer);
            }
        };

        document.getElementById('r-go').onclick = () => {
            clearInterval(silencer);
            overlay.remove();
            // 在当前 URL 后面打标,并重新加载以绕过脚本拦截
            if (isIncoming) {
                window.location.replace(window.location.href + (window.location.hash ? '&' : '#') + 'force-pass');
            } else {
                const a = document.createElement('a');
                a.href = url + (url.includes('#') ? '&' : '#') + 'force-pass';
                a.target = "_blank"; // 强制看的时候通常是在新标签页
                document.body.appendChild(a);
                a.click();
            }
        };
    }

    // 3. 入境自检
    function checkIncoming() {
        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 data = JSON.parse(res.responseText);
                    if (data.isRickroll) {
                        silencePage();
                        renderOverlay("入境风险拦截", url, true);
                    }
                } catch (e) {}
            }
        });
    }

    // 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 data = JSON.parse(res.responseText);
                    cache.set(url, data.isRickroll);
                    if (data.isRickroll) {
                        document.querySelectorAll('a').forEach(a => {
                            if(getRealUrl(a.href) === url) a.classList.add('rickroll-danger');
                        });
                    }
                } catch (e) {}
                activeRequests--; processQueue();
            }
        });
    }

    function scanPage() {
        const EXCLUDE = /\.(jpg|jpeg|png|gif|css|js|woff|zip|pdf|mp4)($|\?)/i;
        document.querySelectorAll('a[href]').forEach(a => {
            const url = getRealUrl(a.href);
            if (!url.startsWith('http') || url.includes(window.location.hostname) || EXCLUDE.test(url) || cache.has(url)) return;
            cache.set(url, 'pending');
            queue.push(url);
        });
        processQueue();
    }

    // 5. 点击接管
    window.addEventListener('click', function(e) {
        const a = e.target.closest('a');
        if (!a || !a.href || !a.href.startsWith('http')) return;
        if (a.href.includes('force-pass') || a.dataset.rickSafe === '1') return;

        const url = getRealUrl(a.href);
        e.preventDefault();
        e.stopPropagation();

        GM_xmlhttpRequest({
            method: "POST",
            url: API_ENDPOINT,
            data: JSON.stringify({ url }),
            headers: { "Content-Type": "application/json" },
            onload: (res) => {
                try {
                    const data = JSON.parse(res.responseText);
                    if (data.isRickroll) {
                        renderOverlay("重定向拦截", url, false);
                    } else {
                        a.dataset.rickSafe = '1';
                        a.click();
                    }
                } catch (e) { a.dataset.rickSafe = '1'; a.click(); }
            }
        });
    }, true);

    checkIncoming();
    window.addEventListener('DOMContentLoaded', scanPage);
    setInterval(scanPage, 5000);
})();