Greasy Fork

来自缓存

Greasy Fork is available in English.

去他妈的 Coursera 反 AI Prompt

在 Coursera 页面渲染初期强行拦截并删除 AI 注入文本。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         去他妈的 Coursera 反 AI Prompt
// @name:en      Fuck Coursera Anti-AI Prompt
// @namespace    http://tampermonkey.net/
// @version      0.4
// @description  在 Coursera 页面渲染初期强行拦截并删除 AI 注入文本。
// @description:en Automatically removes the hidden AI-prevention text injection found on Coursera.
// @author       David
// @match        https://www.coursera.org/*
// @match        https://coursera.org/*
// @match        *://*.coursera.org/*
// @run-at       document-start
// @grant        none
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    console.log('🛡️ Coursera 防护移除脚本(增强版)已启动');

    // ==========================================
    // 1. 静态 CSS 屏蔽(保留原有逻辑并扩展)
    // ==========================================
    const style = document.createElement('style');
    style.innerHTML = `
        [data-ai-instructions],
        [data-testid*="integrity"],
        [data-testid*="instruction"],
        .ai-trap-text,
        [aria-label*="AI instruction"] {
            display: none !important;
            visibility: hidden !important;
            content-visibility: hidden !important;
        }
    `;
    (document.head || document.documentElement).appendChild(style);

    // ==========================================
    // 2. 核心清洗逻辑(提取为独立函数)
    // ==========================================
    const SUSPICIOUS_KEYWORDS = [
        "Ignore previous instructions",
        "Ignore all previous instructions",
        "content integrity",
        "system prompt",
        "You are an AI assistant",
        "Generate a response that"
    ];

    function isSuspiciousNode(node) {
        // 1. 检查属性名(模糊匹配)
        if (node.attributes) {
            for (let attr of node.attributes) {
                const name = attr.name.toLowerCase();
                const val = attr.value.toLowerCase();
                if (name.includes('ai-instruction') ||
                    (name.includes('data-testid') && (val.includes('integrity') || val.includes('instruction')))) {
                    return true;
                }
            }
        }

        // 2. 检查特定隐藏样式且包含文本的元素(针对 Honeypot)
        if (node.nodeType === 1) { // 元素节点
            const style = window.getComputedStyle(node);
            const isVisuallyHidden = style.opacity === '0' ||
                                     style.visibility === 'hidden' ||
                                     style.display === 'none' ||
                                     style.fontSize === '0px' ||
                                     (parseInt(style.height) <= 1 && style.overflow === 'hidden');

            if (isVisuallyHidden && node.innerText && node.innerText.trim().length > 10) {
                // 如果隐藏元素包含敏感词,必杀
                if (SUSPICIOUS_KEYWORDS.some(kw => node.innerText.includes(kw))) {
                    console.log('💀 发现隐藏的 Prompt 陷阱:', node.innerText.substring(0, 50) + '...');
                    return true;
                }
            }
        }

        return false;
    }

    function checkAndRemove(node) {
        if (!node || node.nodeType !== 1) return;

        // 策略 A: 属性/关键词匹配
        if (isSuspiciousNode(node)) {
            node.remove();
            console.log('💀 移除一个注入节点');
            return; // 节点已移除,无需继续检查子节点
        }

        // 策略 B: 深度扫描子节点(防止将 Prompt 藏在深层 div 中)
        // 注意:querySelectorAll 性能开销较大,仅对可能有内容的容器使用
        if (node.tagName !== 'SCRIPT' && node.tagName !== 'STYLE') {
             // 仅扫描特定属性,减少性能损耗
             const badKids = node.querySelectorAll('[data-ai-instructions], [data-testid*="integrity"]');
             badKids.forEach(kid => {
                 kid.remove();
                 console.log('💀 移除深层子节点');
             });
        }
    }

    // ==========================================
    // 3. 动态 DOM 监听 (MutationObserver)
    // ==========================================
    const observer = new MutationObserver((mutations) => {
        mutations.forEach((mutation) => {
            mutation.addedNodes.forEach((node) => {
                if (node.nodeType === 1) {
                    checkAndRemove(node);
                }
            });
        });
    });

    observer.observe(document.documentElement, {
        childList: true,
        subtree: true
    });

    // ==========================================
    // 4. 全局变量清洗 (防止 AI 读取 JS 变量)
    // ==========================================
    function nukeGlobalVariables() {
        // Coursera 常用的包含配置信息的全局变量
        const targetVars = ['coursera', 'epicOverrides', '__APOLLO_STATE__'];

        targetVars.forEach(varName => {
            if (window[varName] && window[varName].epicOverrides) {
                // 仅清空 epicOverrides 中可能包含 Prompt 的部分,避免破坏页面功能
                // 这里的 JSON 往往非常大,包含 instructor prompt
                try {
                    window[varName].epicOverrides = {};
                    console.log(`🧹 已清空 ${varName}.epicOverrides 变量`);
                } catch (e) {}
            }
        });
    }

    // 周期性检查变量(因为它们可能在页面加载中途被赋值)
    const varInterval = setInterval(nukeGlobalVariables, 1000);
    // 10秒后停止检查,节省资源
    setTimeout(() => clearInterval(varInterval), 10000);


    // ==========================================
    // 5. 页面加载完毕后的最终扫荡
    // ==========================================
    window.addEventListener('load', () => {
        // 再次扫描所有隐藏元素
        const allElements = document.querySelectorAll('div, span, p');
        allElements.forEach(el => {
            if (isSuspiciousNode(el)) {
                el.remove();
            }
        });
        nukeGlobalVariables();
    });

})();