VPN资源链接转换器

自动转换VPN资源链接格式

// ==UserScript==
// @name         VPN资源链接转换器
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  自动转换VPN资源链接格式
// @match        *://*.vpn.gcc.edu.cn:*/*
// @grant        none
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    // 转换URL的函数
    function transformUrl(url) {
        try {
            // 如果是相对路径,先转换为绝对路径
            if (url.startsWith('//') || url.startsWith('/')) {
                const currentUrl = new URL(window.location.href);
                url = new URL(url, currentUrl.origin).href;
            } else if (!url.startsWith('http')) {
                // 处理相对路径
                const currentUrl = new URL(window.location.href);
                const baseUrl = currentUrl.origin + currentUrl.pathname;
                const basePath = baseUrl.substring(0, baseUrl.lastIndexOf('/') + 1);
                url = new URL(url, basePath).href;
            }

            // 解析URL
            let parsedUrl = new URL(url);

            // 1. 域名中的"-"转换为"."
            parsedUrl.hostname = parsedUrl.hostname.replace(/-/g, '.');

            // 2. 移除端口 :8118
            if (parsedUrl.port === '8118') {
                parsedUrl.port = '';
            }

            // 3. http修改成https
            if (parsedUrl.protocol === 'http:') {
                parsedUrl.protocol = 'https:';
            }

            // 4. 移除 "-s.vpn.gcc.edu.cn" 部分
            parsedUrl.hostname = parsedUrl.hostname.replace(/-s\.vpn\.gcc\.edu\.cn/g, '');

            return parsedUrl.href;
        } catch (e) {
            console.error('URL转换失败:', url, e);
            return url;
        }
    }

    // 处理CSS资源
    function processCSSResources() {
        const links = document.querySelectorAll('link[rel="stylesheet"]');
        links.forEach(link => {
            if (link.href && link.href.includes('vpn.gcc.edu.cn')) {
                const originalHref = link.href;
                const newHref = transformUrl(originalHref);
                if (newHref !== originalHref) {
                    link.href = newHref;
                }
            }
        });

        // 处理内联样式中的背景图片
        const elementsWithStyle = document.querySelectorAll('[style*="background"]');
        elementsWithStyle.forEach(element => {
            const style = element.getAttribute('style');
            if (style && style.includes('vpn.gcc.edu.cn')) {
                const urlMatch = style.match(/url\(['"]?([^'"]+)['"]?\)/);
                if (urlMatch && urlMatch[1]) {
                    const originalUrl = urlMatch[1];
                    const newUrl = transformUrl(originalUrl);
                    if (newUrl !== originalUrl) {
                        const newStyle = style.replace(originalUrl, newUrl);
                        element.setAttribute('style', newStyle);
                    }
                }
            }
        });
    }

    // 处理图片资源
    function processImageResources() {
        const images = document.querySelectorAll('img[src*="vpn.gcc.edu.cn"]');
        images.forEach(img => {
            if (img.src) {
                const originalSrc = img.src;
                const newSrc = transformUrl(originalSrc);
                if (newSrc !== originalSrc) {
                    img.src = newSrc;
                }
            }
        });

        // 处理srcset属性
        const imgsWithSrcset = document.querySelectorAll('img[srcset*="vpn.gcc.edu.cn"]');
        imgsWithSrcset.forEach(img => {
            if (img.srcset) {
                let newSrcset = img.srcset;
                const urls = img.srcset.match(/https?:\/\/[^\s,]+/g);
                if (urls) {
                    urls.forEach(url => {
                        const newUrl = transformUrl(url);
                        if (newUrl !== url) {
                            newSrcset = newSrcset.replace(url, newUrl);
                        }
                    });
                }
                img.srcset = newSrcset;
            }
        });
    }

    // 处理页面中的所有相关资源
    function processAllResources() {
        processCSSResources();
        processImageResources();
    }

    // 监听DOM变化,处理动态加载的资源
    const observer = new MutationObserver(function(mutations) {
        let shouldProcess = false;
        mutations.forEach(function(mutation) {
            mutation.addedNodes.forEach(function(node) {
                if (node.nodeType === 1) { // Element节点
                    if (node.tagName === 'LINK' || node.tagName === 'IMG' || node.tagName === 'SCRIPT') {
                        shouldProcess = true;
                    } else if (node.querySelectorAll) {
                        if (node.querySelectorAll('link, img, script').length > 0) {
                            shouldProcess = true;
                        }
                    }
                }
            });
        });
        if (shouldProcess) {
            setTimeout(processAllResources, 100);
        }
    });

    // 开始处理
    processAllResources();

    // 监听DOM变化
    observer.observe(document.body, {
        childList: true,
        subtree: true
    });

    // 页面加载完成后再次处理
    window.addEventListener('load', processAllResources);
})();