Greasy Fork

Greasy Fork is available in English.

anti-rickroll

静默扫描页面链接,预先缓存检测结果,点击瞬发警告

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         anti-rickroll
// @namespace    http://tampermonkey.net/
// @version      2.0
// @description  静默扫描页面链接,预先缓存检测结果,点击瞬发警告
// @author       dext
// @match        *://*/*
// @grant        GM_xmlhttpRequest
// @grant        GM_addStyle
// @connect      anti-rickroll.dext.top
// @run-at       document-idle
// ==/UserScript==

(function() {
    'use strict';

    const API_ENDPOINT = "https://anti-rickroll.dext.top";
    const cache = new Map(); // 缓存:URL -> isRickroll (true/false)
    const scanning = new Set(); // 正在扫描中的URL,避免重复请求

    // 极简弹窗样式
    GM_addStyle(`
        #rick-guard-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.8); z-index: 2147483647; display: flex; justify-content: center; align-items: center; backdrop-filter: blur(5px); }
        .rick-modal { background: #fff; padding: 30px; border-radius: 12px; width: 320px; text-align: center; font-family: sans-serif; }
        .rick-btns { display: flex; gap: 10px; margin-top: 20px; }
        .rick-btn { flex: 1; padding: 10px; border-radius: 6px; cursor: pointer; border: none; font-weight: bold; }
        .btn-go { background: #ff4444; color: white; }
        .btn-cancel { background: #f0f0f0; }
    `);

    // 核心:扫描页面上的链接
    function scanLinks() {
        const links = Array.from(document.querySelectorAll('a[href]'));
        links.forEach(a => {
            const url = a.href;
            // 过滤掉非http、锚点、已处理过的
            if (!url.startsWith('http') || cache.has(url) || scanning.has(url)) return;

            // 过滤常见的大型信任网站,减少 API 压力
            const domain = new URL(url).hostname;
            if (domain.includes('google.com') || domain.includes('baidu.com') || domain.includes('github.com')) {
                cache.set(url, false);
                return;
            }

            scanning.add(url);
            
            GM_xmlhttpRequest({
                method: "POST",
                url: API_ENDPOINT,
                headers: { "Content-Type": "application/json" },
                data: JSON.stringify({ url: url }),
                onload: function(res) {
                    try {
                        const data = JSON.parse(res.responseText);
                        cache.set(url, data.isRickroll);
                        // 如果确定是诈骗,可以给链接加个淡淡的红边提醒(可选)
                        // if(data.isRickroll) a.style.outline = "1px dashed rgba(255,0,0,0.5)";
                    } catch (e) {}
                    scanning.delete(url);
                },
                onerror: () => scanning.delete(url)
            });
        });
    }

    // 初始扫描
    setTimeout(scanLinks, 1000);

    // 监听动态加载的内容(如瀑布流)
    const observer = new MutationObserver(scanLinks);
    observer.observe(document.body, { childList: true, subtree: true });

    // 点击拦截逻辑
    window.addEventListener('click', function(e) {
        const a = e.target.closest('a');
        if (!a || !a.href) return;

        const isRick = cache.get(a.href);

        // 如果缓存里确认是 Rickroll
        if (isRick === true) {
            e.preventDefault();
            e.stopPropagation();
            showWarning(a.href, a);
            return;
        }

        // 如果还没检测完 (isRick 为 undefined),则放行,或者你可以选择拦截等待
        // 这里选择直接放行以保证用户体验,因为大部分链接是安全的
    }, true);

    function showWarning(url, originalElement) {
        const overlay = document.createElement('div');
        overlay.id = 'rick-guard-overlay';
        overlay.innerHTML = `
            <div class="rick-modal">
                <h2 style="color:#ff4444;margin:0">诈骗链接警告</h2>
                <p style="color:#666">该链接经 AI 识别为 Rickroll 或钓鱼网页,是否继续访问?</p>
                <div class="rick-btns">
                    <button class="rick-btn btn-cancel" id="r-close">取消</button>
                    <button class="rick-btn btn-go" id="r-go">继续访问</button>
                </div>
            </div>
        `;
        document.body.appendChild(overlay);
        document.getElementById('r-close').onclick = () => overlay.remove();
        document.getElementById('r-go').onclick = () => {
            overlay.remove();
            cache.set(url, false); // 暂时标记为安全以允许跳转
            window.location.href = url;
        };
    }
})();