Greasy Fork is available in English.

ChatGPT降智风险检测✅(优化版)MaynorAI

ChatGPT会对某些IP进行无提示的服务降级,Plus用户模型会降至4-Mini,此脚本检测账号IP情况用于让你判断是否降智✅。

// ==UserScript==
// @name         ChatGPT降智风险检测✅(优化版)MaynorAI
// @namespace    https://github.com/KoriIku/chatgpt-degrade-checker
// @homepage     https://github.com/KoriIku/chatgpt-degrade-checker
// @author       修改自KoriIku
// @icon         data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NCA2NCI+PHBhdGggZmlsbD0iIzJjM2U1MCIgZD0iTTMyIDJDMTUuNDMyIDIgMiAxNS40MzIgMiAzMnMxMy40MzIgMzAgMzAgMzAgMzAtMTMuNDMyIDMwLTMwUzQ4LjU2OCAyIDMyIDJ6bTAgNTRjLTEzLjIzMyAwLTI0LTEwLjc2Ny0yNC0yNFMxOC43NjcgOCAzMiA4czI0IDEwLjc2NyAyNCAyNFM0NS4yMzMgNTYgMzIgNTZ6Ii8+PHBhdGggZmlsbD0iIzNkYzJmZiIgZD0iTTMyIDEyYy0xMS4wNDYgMC0yMCA4Ljk1NC0yMCAyMHM4Ljk1NCAyMCAyMCAyMCAyMC04Ljk1NCAyMC0yMFM0My4wNDYgMTIgMzIgMTJ6bTAgMzZjLTguODM3IDAtMTYtNy4xNjMtMTYtMTZzNy4xNjMtMTYgMTYtMTYgMTYgNy4xNjMgMTYgMTZTNDAuODM3IDQ4IDMyIDQ4eiIvPjxwYXRoIGZpbGw9IiMwMGZmN2YiIGQ9Ik0zMiAyMGMtNi42MjcgMC0xMiA1LjM3My0xMiAxMnM1LjM3MyAxMiAxMiAxMiAxMi01LjM3MyAxMi0xMlMzOC42MjcgMjAgMzIgMjB6bTAgMjBjLTQuNDE4IDAtOC0zLjU4Mi04LThzMy41ODItOCA4LTggOCAzLjU4MiA4IDgtMy41ODIgOC04IDh6Ii8+PGNpcmNsZSBmaWxsPSIjZmZmIiBjeD0iMzIiIGN5PSIzMiIgcj0iNCIvPjwvc3ZnPg==
// @version      1.3
// @description  ChatGPT会对某些IP进行无提示的服务降级,Plus用户模型会降至4-Mini,此脚本检测账号IP情况用于让你判断是否降智✅。
// @match        *://chatgpt.com/*
// @match        *://chatgpt-plus.top/*
// @match        *://*.chatgpt-plus.top/*
// @match        *://*.maynor1024.live/*
// @grant        none
// @license AGPLv3
// ==/UserScript==

(function() {
    'use strict';

    // 创建显示框
    const displayBox = document.createElement('div');
    displayBox.style.position = 'fixed';
    displayBox.style.top = '50%';
    displayBox.style.right = '20px';
    displayBox.style.transform = 'translateY(-50%)';
    displayBox.style.width = '220px';
    displayBox.style.padding = '10px';
    displayBox.style.backgroundColor = 'rgba(0, 0, 0, 0.7)';
    displayBox.style.color = '#fff';
    displayBox.style.fontSize = '14px';
    displayBox.style.borderRadius = '8px';
    displayBox.style.boxShadow = '0 4px 8px rgba(0, 0, 0, 0.3)';
    displayBox.style.zIndex = '10000';
    displayBox.style.transition = 'all 0.3s ease';
    displayBox.style.display = 'none';

    displayBox.innerHTML = `
        <div style="margin-bottom: 10px;">
            <strong>PoW 信息</strong>
        </div>
        <div id="content">
            PoW难度: <span id="difficulty">N/A</span><span id="difficulty-level" style="margin-left: 3px"></span>
            <span id="difficulty-tooltip" style="
                cursor: pointer;
                color: #fff;
                font-size: 12px;
                display: inline-block;
                width: 14px;
                height: 14px;
                line-height: 14px;
                text-align: center;
                border-radius: 50%;
                border: 1px solid #fff;
                margin-left: 3px;
            ">?</span><br>
            IP质量: <span id="ip-quality">N/A</span><br>
            <span id="persona-container" style="display: none">用户类型: <span id="persona">N/A</span></span>
        </div>
        <div style="
            margin-top: 12px;
            padding-top: 8px;
            border-top: 0.5px solid rgba(255, 255, 255, 0.15);
            font-size: 10px;
            color: rgba(255, 255, 255, 0.5);
            text-align: center;
            letter-spacing: 0.3px;
        ">
            ChatGPT Degrade Checker
    </div>`;
    document.body.appendChild(displayBox);

    // 创建收缩状态的指示器
    const collapsedIndicator = document.createElement('div');
    collapsedIndicator.style.position = 'fixed';
    collapsedIndicator.style.top = '50%';
    collapsedIndicator.style.right = '20px';
    collapsedIndicator.style.transform = 'translateY(-50%)';
    collapsedIndicator.style.width = '32px';
    collapsedIndicator.style.height = '32px';
    collapsedIndicator.style.backgroundColor = 'transparent';
    collapsedIndicator.style.borderRadius = '50%';
    collapsedIndicator.style.cursor = 'pointer';
    collapsedIndicator.style.zIndex = '10000';
    collapsedIndicator.style.padding = '4px';
    collapsedIndicator.style.display = 'flex';
    collapsedIndicator.style.alignItems = 'center';
    collapsedIndicator.style.justifyContent = 'center';
    collapsedIndicator.style.transition = 'all 0.3s ease';
    collapsedIndicator.style.opacity = '0'; // 添加初始隐藏状态

    // 使用SVG作为指示器
    collapsedIndicator.innerHTML = `
    <svg id="status-icon" width="32" height="32" viewBox="0 0 64 64" style="transition: all 0.3s ease;">
        <defs>
            <linearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="100%">
                <stop offset="0%" style="stop-color:#3498db;stop-opacity:1" />
                <stop offset="100%" style="stop-color:#2ecc71;stop-opacity:1" />
            </linearGradient>
            <filter id="glow">
                <feGaussianBlur stdDeviation="2" result="coloredBlur"/>
                <feMerge>
                    <feMergeNode in="coloredBlur"/>
                    <feMergeNode in="SourceGraphic"/>
                </feMerge>
            </filter>
        </defs>
        <g id="icon-group" filter="url(#glow)">
            <circle cx="32" cy="32" r="28" fill="url(#gradient)" stroke="#fff" stroke-width="2"/>
            <circle cx="32" cy="32" r="20" fill="none" stroke="#fff" stroke-width="2" stroke-dasharray="100">
                <animateTransform
                    attributeName="transform"
                    attributeType="XML"
                    type="rotate"
                    from="0 32 32"
                    to="360 32 32"
                    dur="8s"
                    repeatCount="indefinite"/>
            </circle>
            <circle cx="32" cy="32" r="12" fill="none" stroke="#fff" stroke-width="2">
                <animate
                    attributeName="r"
                    values="12;14;12"
                    dur="2s"
                    repeatCount="indefinite"/>
            </circle>
            <circle id="center-dot" cx="32" cy="32" r="4" fill="#fff">
                <animate
                    attributeName="r"
                    values="4;6;4"
                    dur="2s"
                    repeatCount="indefinite"/>
            </circle>
        </g>
    </svg>`;
    document.body.appendChild(collapsedIndicator);

    // 鼠标悬停事件
    collapsedIndicator.addEventListener('mouseenter', function() {
        if (collapsedIndicator.style.opacity === '1') {
            displayBox.style.display = 'block';
        }
    });

    displayBox.addEventListener('mouseleave', function(e) {
        const x = e.clientX;
        const rightEdge = window.innerWidth;

        if (x <= rightEdge - 100) {
            displayBox.style.display = 'none';
        }
    });

    // 添加鼠标移动监听
    document.addEventListener('mousemove', function(e) {
        const x = e.clientX;
        const rightEdge = window.innerWidth;

        // 当鼠标在距离右边100px范围内时显示
        if (x > rightEdge - 100) {
            collapsedIndicator.style.opacity = '1';
        } else {
            collapsedIndicator.style.opacity = '0';
            displayBox.style.display = 'none';
        }
    });

    // 创建提示框
    const tooltip = document.createElement('div');
    tooltip.id = 'tooltip';
    tooltip.innerText = '这个值越小,代表PoW难度越高,ChatGPT认为你的IP风险越高。';
    tooltip.style.position = 'fixed';
    tooltip.style.backgroundColor = 'rgba(0, 0, 0, 0.8)';
    tooltip.style.color = '#fff';
    tooltip.style.padding = '8px 12px';
    tooltip.style.borderRadius = '5px';
    tooltip.style.fontSize = '12px';
    tooltip.style.visibility = 'hidden';
    tooltip.style.zIndex = '10001';
    tooltip.style.width = '240px';
    tooltip.style.lineHeight = '1.4';
    tooltip.style.pointerEvents = 'none';
    document.body.appendChild(tooltip);

    // 显示提示
    document.getElementById('difficulty-tooltip').addEventListener('mouseenter', function(event) {
        tooltip.style.visibility = 'visible';

        const tooltipWidth = 240;
        const windowWidth = window.innerWidth;
        const mouseX = event.clientX;
        const mouseY = event.clientY;

        let leftPosition = mouseX - tooltipWidth - 10;
        if (leftPosition < 10) {
            leftPosition = mouseX + 20;
        }

        let topPosition = mouseY - 40;

        tooltip.style.left = `${leftPosition}px`;
        tooltip.style.top = `${topPosition}px`;
    });

    // 隐藏提示
    document.getElementById('difficulty-tooltip').addEventListener('mouseleave', function() {
        tooltip.style.visibility = 'hidden';
    });

    // 更新difficulty指示器
    function updateDifficultyIndicator(difficulty) {
        const difficultyLevel = document.getElementById('difficulty-level');
        const ipQuality = document.getElementById('ip-quality');

        if (difficulty === 'N/A') {
            setIconColors('#888', '#666');
            difficultyLevel.innerText = '';
            ipQuality.innerHTML = 'N/A';
            return;
        }

        const cleanDifficulty = difficulty.replace('0x', '').replace(/^0+/, '');
        const hexLength = cleanDifficulty.length;

        let color, secondaryColor, textColor, level, qualityText;

        if (hexLength <= 2) {
            color = '#F44336';
            secondaryColor = '#d32f2f';
            textColor = '#ff6b6b';
            level = '(困难)';
            qualityText = '高风险';
        } else if (hexLength === 3) {
            color = '#FFC107';
            secondaryColor = '#ffa000';
            textColor = '#ffd700';
            level = '(中等)';
            qualityText = '中等';
        } else if (hexLength === 4) {
            color = '#8BC34A';
            secondaryColor = '#689f38';
            textColor = '#9acd32';
            level = '(简单)';
            qualityText = '良好';
        } else {
            color = '#4CAF50';
            secondaryColor = '#388e3c';
            textColor = '#98fb98';
            level = '(极易)';
            qualityText = '优秀';
        }

        setIconColors(color, secondaryColor);
        difficultyLevel.innerHTML = `<span style="color: ${textColor}">${level}</span>`;
        ipQuality.innerHTML = `<span style="color: ${textColor}">${qualityText}</span>`;
    }

    function setIconColors(primaryColor, secondaryColor) {
        const gradient = document.querySelector('#gradient');
        gradient.innerHTML = `
            <stop offset="0%" style="stop-color:${primaryColor};stop-opacity:1" />
            <stop offset="100%" style="stop-color:${secondaryColor};stop-opacity:1" />
        `;
    }

    // 拦截 fetch 请求
    const originalFetch = window.fetch;
    window.fetch = async function(resource, options) {
        const response = await originalFetch(resource, options);

        if ((resource.includes('/backend-api/sentinel/chat-requirements')||resource.includes('backend-anon/sentinel/chat-requirements')) && options.method === 'POST') {
            const clonedResponse = response.clone();
            clonedResponse.json().then(data => {
                const difficulty = data.proofofwork ? data.proofofwork.difficulty : 'N/A';
                const persona = data.persona || 'N/A';
                document.getElementById('difficulty').innerText = difficulty;

                const personaContainer = document.getElementById('persona-container');
                if (persona && !persona.toLowerCase().includes('free')) {
                    personaContainer.style.display = 'block';
                    document.getElementById('persona').innerText = persona;
                } else {
                    personaContainer.style.display = 'none';
                }

                updateDifficultyIndicator(difficulty);
            }).catch(e => console.error('解析响应时出错:', e));
        }
        return response;
    };
})();