CDN & Server Info Displayer (Pure Liquid Glass)

[v4.9.0 回归纯粹] 根据反馈,移除所有3D交互和动态光泽。回归并优化经典的液态玻璃动画效果,恢复实用的面板拖动功能。

当前为 2025-06-17 提交的版本,查看 最新版本

// ==UserScript==
// @name         CDN & Server Info Displayer (Pure Liquid Glass)
// @name:en      CDN & Server Info Displayer (Pure Liquid Glass)
// @namespace    http://tampermonkey.net/
// @version      4.9.0
// @description  [v4.9.0 回归纯粹] 根据反馈,移除所有3D交互和动态光泽。回归并优化经典的液态玻璃动画效果,恢复实用的面板拖动功能。
// @description:en [v4.9.0 Pure Edition] Based on feedback, all 3D interaction and dynamic glare have been removed. This version returns to and refines the classic liquid glass animation, restoring the practical drag-and-drop feature.
// @author       Gemini (AI Refined Build)
// @license      MIT
// @match        *://*/*
// @grant        GM_addStyle
// @run-at       document-idle
// ==/UserScript==

(function() {
    'use strict';

    // --- Configuration ---
    const config = {
        initialPosition: { bottom: '15px', right: '15px' },
        panelBgColor: 'rgba(30, 30, 40, 0.65)',      // 深邃的玻璃背景色
        panelTextColor: '#ffffff',
        borderColor: 'rgba(255, 255, 255, 0.2)',    // 玻璃边缘高光
        minWindowSize: { width: 400, height: 300 },
        initial_delay: 2500,
        retry_delay: 7000,
        max_retries: 4,
        excludePatterns: [
            /(\/|&)pay(pal|ment)/i, /\/checkout|\/billing/i, /\/login|\/signin|\/auth/i,
            /\/phpmyadmin/i, /(\/ads\/|ad_id=|advertisement)/i, /doubleclick\.net/i,
        ]
    };

    window.cdnScriptStatus = window.cdnScriptStatus || {};

    // --- Core Info Parsing Functions (Unchanged) ---
    function getCacheStatus(h) {
        const headersToCheck=[h.get('cache-status'),h.get('x-cache-status'),h.get('x-cache'),h.get('x-edge-cache-status'),h.get('x-sucuri-cache'),h.get('x-vercel-cache'),h.get('x-qc-cache'),h.get('cf-cache-status'),h.get('x-response-cache'),h.get('x-bdcdn-cache-status'),h.get('cdn-cache'),h.get('bunny-cache-state')];for(const value of headersToCheck){if(!value)continue;const upperVal=value.toUpperCase();if(upperVal.includes('HIT'))return 'HIT';if(upperVal.includes('MISS'))return 'MISS';if(upperVal.includes('BYPASS'))return 'BYPASS';if(upperVal.includes('DYNAMIC'))return 'DYNAMIC';if(upperVal.includes('UPDATING'))return 'UPDATING';if(upperVal.includes('STALE'))return 'STALE';if(upperVal.includes('EXPIRED'))return 'EXPIRED';}if(parseInt(h.get('age'),10)>0)return 'HIT (inferred)';return 'N/A';
    }
    const cdnProviders = { 'Cloudflare':{headers:['cf-ray'],serverHeaders:['cloudflare'],priority:10,getInfo:(h)=>({provider:'Cloudflare',cache:h.get('cf-cache-status')?.toUpperCase()||'N/A',pop:h.get('cf-ray')?.slice(-3).toUpperCase()||'N/A',extra:`Ray ID: ${h.get('cf-ray')||'N/A'}`})},'AWS CloudFront':{headers:['x-amz-cf-pop','x-amz-cf-id'],priority:9,getInfo:(h)=>({provider:'AWS CloudFront',cache:getCacheStatus(h),pop:(h.get('x-amz-cf-pop')||'N/A').substring(0,3),extra:`CF ID: ${h.get('x-amz-cf-id')||'N/A'}`})},'Fastly':{headers:['x-fastly-request-id','x-served-by'],priority:9,getInfo:(h)=>({provider:'Fastly',cache:getCacheStatus(h),pop:h.get('x-served-by')?.split('-').pop()||'N/A',extra:`ReqID: ${h.get('x-fastly-request-id')||'N/A'}`})},'Vercel':{headers:['x-vercel-id'],priority:10,getInfo:(h)=>{let pop='N/A';const vercelId=h.get('x-vercel-id');if(vercelId){const regionPart=vercelId.split('::')[0];const match=regionPart.match(/^[a-zA-Z]+/);if(match)pop=match[0].toUpperCase();}return{provider:'Vercel',cache:getCacheStatus(h),pop:pop,extra:`ID: ${h.get('x-vercel-id')||'N/A'}`};}},};
    function parseInfo(h) {
        const lowerCaseHeaders=new Map();for(const[key,value]of h.entries()){lowerCaseHeaders.set(key.toLowerCase(),value);}let detectedProviders=[];for(const[_,cdn]of Object.entries(cdnProviders)){let isMatch=false;if(cdn.headers?.some(header=>lowerCaseHeaders.has(header.toLowerCase())))isMatch=true;if(!isMatch&&cdn.serverHeaders?.some(server=>(lowerCaseHeaders.get('server')||'').toLowerCase().includes(server.toLowerCase())))isMatch=true;if(isMatch)detectedProviders.push({...cdn.getInfo(lowerCaseHeaders),priority:cdn.priority||5});}if(detectedProviders.length>0){detectedProviders.sort((a,b)=>b.priority-a.priority);return detectedProviders[0];}const server=lowerCaseHeaders.get('server');if(server)return{provider:server,cache:getCacheStatus(lowerCaseHeaders),pop:'N/A',extra:'No CDN detected'};return{provider:'Unknown',cache:'N/A',pop:'N/A',extra:'No CDN or Server info'};
    }

    // --- UI Functions ---
    function getPanelCSS() {
        return `
            @keyframes moveBlob1 {
                0%   { transform: translate(0, 0) scale(1); }
                50%  { transform: translate(60px, -80px) scale(1.2); }
                100% { transform: translate(0, 0) scale(1); }
            }
            @keyframes moveBlob2 {
                0%   { transform: translate(0, 0) scale(1); }
                50%  { transform: translate(-80px, 70px) scale(0.8); }
                100% { transform: translate(0, 0) scale(1); }
            }
            :host {
                all: initial;
                position: fixed;
                z-index: 2147483647;
                bottom: ${config.initialPosition.bottom};
                right: ${config.initialPosition.right};
            }
            #cdn-info-panel-enhanced {
                position: relative;
                overflow: hidden;
                padding: 16px 20px;
                border-radius: 18px;
                font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
                font-size: 13px;
                color: ${config.panelTextColor};
                background: ${config.panelBgColor};
                backdrop-filter: blur(18px);
                -webkit-backdrop-filter: blur(18px);
                border: 1px solid ${config.borderColor};
                box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.3);
                cursor: move; /* 恢复可拖动鼠标样式 */
                user-select: none;
                transition: all 0.3s ease;
                min-width: 230px;
            }
            #cdn-info-panel-enhanced:hover {
                transform: scale(1.02);
                box-shadow: 0 8px 40px 0 rgba(0, 0, 0, 0.4);
            }
            /* 背景流体光球 1 */
            #cdn-info-panel-enhanced::before {
                content: '';
                position: absolute;
                z-index: -1;
                top: -15%;
                left: -20%;
                width: 160px;
                height: 160px;
                background: radial-gradient(circle, #095fab, transparent 60%);
                filter: blur(60px);
                animation: moveBlob1 18s ease-in-out infinite alternate;
            }
            /* 背景流体光球 2 */
            #cdn-info-panel-enhanced::after {
                content: '';
                position: absolute;
                z-index: -1;
                bottom: -20%;
                right: -25%;
                width: 180px;
                height: 180px;
                background: radial-gradient(circle, #6f2b8c, transparent 70%);
                filter: blur(70px);
                animation: moveBlob2 22s ease-in-out infinite alternate;
            }
            .close-btn { position: absolute; top: 4px; right: 4px; width: 20px; height: 20px; border-radius: 50%; background: rgba(0,0,0,0.2); color: white; border: none; cursor: pointer; font-size: 14px; display: flex; align-items: center; justify-content: center; transition: all 0.2s; line-height: 20px; z-index: 2;}
            .close-btn:hover { background: rgba(231, 76, 60, 0.8); transform: scale(1.1); }
            /* 文本样式 */
            .panel-header, .info-line { text-shadow: 0 1px 2px rgba(0, 0, 0, 0.25); position: relative; z-index: 1; }
            .panel-header { font-weight: 600; font-size: 14px; margin-bottom: 8px; color: #ffffff; text-align: center; border-bottom: 1px solid rgba(255, 255, 255, 0.2); padding-bottom: 8px; }
            .info-line { display: flex; justify-content: space-between; align-items: center; margin: 8px 0; }
            .info-label { font-weight: 400; color: #e0e0e0; font-size: 12px; }
            .info-value { font-weight: 600; max-width: 140px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: right; }
            .cache-HIT { color: #50fa7b !important; }
            .cache-MISS, .cache-BYPASS { color: #ff79c6 !important; }
        `;
    }

    function createDisplayPanel(info) {
        if (!info || document.getElementById('cdn-info-host-enhanced')) return;
        const host = document.createElement('div');
        host.id = 'cdn-info-host-enhanced';
        document.body.appendChild(host);
        const shadowRoot = host.attachShadow({ mode: 'open' });

        const styleEl = document.createElement('style');
        styleEl.textContent = getPanelCSS();
        shadowRoot.appendChild(styleEl);

        const panel = document.createElement('div');
        panel.id = 'cdn-info-panel-enhanced';
        const cacheStatus = info.cache.toUpperCase();
        const providerLabel = info.provider.includes('CDN') || info.provider.includes('Cloud') ? 'CDN' : 'Server';

        panel.innerHTML = `
            <button class="close-btn" title="Close">×</button>
            <div class="panel-header">CDN & Server Info</div>
            <div class="info-line"><span class="info-label">${providerLabel}</span><span class="info-value" title="${info.provider}">${info.provider}</span></div>
            <div class="info-line"><span class="info-label">Cache</span><span class="info-value ${cacheStatus.includes('HIT') ? 'cache-HIT' : 'cache-MISS'}">${info.cache}</span></div>
            <div class="info-line"><span class="info-label">POP</span><span class="info-value" title="${info.pop}">${info.pop}</span></div>
        `;
        shadowRoot.appendChild(panel);
        shadowRoot.querySelector('.close-btn').addEventListener('click', (e) => {
            e.stopPropagation();
            host.remove();
        });

        // 恢复拖动功能
        makeDraggable(host);
    }

    function makeDraggable(element) {
        let isDragging = false, startX = 0, startY = 0, elementX = 0, elementY = 0;
        const dragTarget = element.shadowRoot.querySelector('#cdn-info-panel-enhanced');

        dragTarget.addEventListener('mousedown', (e) => {
            if (e.target.classList.contains('close-btn')) return;
            isDragging = true;
            startX = e.clientX;
            startY = e.clientY;
            const rect = element.getBoundingClientRect();
            elementX = rect.left;
            elementY = rect.top;
            document.addEventListener('mousemove', drag);
            document.addEventListener('mouseup', dragEnd);
        });

        function drag(e) {
            if (!isDragging) return;
            e.preventDefault();
            const newX = elementX + e.clientX - startX;
            const newY = elementY + e.clientY - startY;
            const maxX = window.innerWidth - element.offsetWidth;
            const maxY = window.innerHeight - element.offsetHeight;
            element.style.left = `${Math.max(0, Math.min(newX, maxX))}px`;
            element.style.top = `${Math.max(0, Math.min(newY, maxY))}px`;
            element.style.right = 'auto';
            element.style.bottom = 'auto';
        }

        function dragEnd() {
            isDragging = false;
            document.removeEventListener('mousemove', drag);
            document.removeEventListener('mouseup', dragEnd);
        }
    }

    // --- Core Execution Logic (Unchanged) ---
    function shouldExcludePage() {
        if(window!==window.top&&(window.innerWidth<config.minWindowSize.width||window.innerHeight<config.minWindowSize.height))return true;const url=window.location.href.toLowerCase();if(config.excludePatterns.some(pattern=>pattern.test(url))){console.log('[CDN Detector] Excluded by URL pattern.');return true;}return false;
    }
    async function runExecution(retriesLeft) {
        const currentHref=window.location.href;const status=window.cdnScriptStatus;if(status[currentHref]==='succeeded'||shouldExcludePage()||document.getElementById('cdn-info-host-enhanced')){return;}console.log(`[CDN Detector] Attempting to fetch headers... Retries left: ${retriesLeft}`);try{const response=await fetch(currentHref,{method:'HEAD',cache:'no-store',redirect:'follow',headers:{'User-Agent':navigator.userAgent,'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',}});const info=parseInfo(response.headers);createDisplayPanel(info);status[currentHref]='succeeded';console.log('[CDN Detector] Success! Panel created.');}catch(error){console.warn(`[CDN Detector] Fetch failed: ${error.message}. This often indicates an active security challenge.`);status[currentHref]='retrying';if(retriesLeft>0){console.log(`[CDN Detector] Retrying in ${config.retry_delay/1000} seconds...`);setTimeout(()=>runExecution(retriesLeft-1),config.retry_delay);}else{console.error('[CDN Detector] Max retries reached. Aborting for this page.');status[currentHref]='failed';}}
    }
    function main() {
        setTimeout(()=>{runExecution(config.max_retries);},config.initial_delay);let lastUrl=location.href;const observer=new MutationObserver(()=>{if(location.href!==lastUrl){console.log('[CDN Detector] URL changed (SPA), resetting...');lastUrl=location.href;const oldPanel=document.getElementById('cdn-info-host-enhanced');if(oldPanel)oldPanel.remove();setTimeout(()=>{runExecution(config.max_retries);},config.initial_delay);}});if(document.body){observer.observe(document.body,{childList:true,subtree:true});}else{new MutationObserver((_,obs)=>{if(document.body){observer.observe(document.body,{childList:true,subtree:true});obs.disconnect();}}).observe(document.documentElement,{childList:true});}
    }

    main();

})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址