更好访问gcc

一点小小hook

// ==UserScript==
// @name         更好访问gcc
// @namespace    http://tampermonkey.net/
// @version      2.2
// @description  一点小小hook
// @author       LinXingJun
// @match        *://*.gcc.edu.cn/*
// @grant        GM_xmlhttpRequest
// @grant        unsafeWindow
// @connect      *
// @run-at       document-start
// @license MIT
// ==/UserScript==

(function () {
    'use strict';
    if (unsafeWindow.top !== unsafeWindow.self) {
        return;
    }
    const cookie_url = "http://127.0.0.1:1999";

    // 配置重定向规则
    const redirect_domain = {
        'nc.gcc.edu.cn': 'nic.gcc.edu.cn',
        'www-cnki-net.vpn.gcc.edu.cn': 'www-cnki-net-s.vpn.gcc.edu.cn',
        'navi-cnki-net-s.vpn.gcc.edu.cn:8118': 'navi.cnki.net',
        'id-elsevier-com-s.vpn.gcc.edu.cn': 'www-elsevier-com-s.vpn.gcc.edu.cn'
    };
    const redirect_url = {
        '/app/search/quick/': '/search/expert.url',
        'application/checksessionstatus?resourcetype=redirect&isIndividual=false': '/search/expert.url',
        '/portal/#!/vpn_openresource' : '',
        'home.url' : '/search/expert.url'
    };

    const blockblackkeyword = ["vpn", "mail"];

    if (unsafeWindow.location.protocol === 'https:') {
        redirect_domain['http:'] = 'https:';
    }

    // 当前页面URL替换与跳转
    function handlePageRedirect() {
        let newUrl = unsafeWindow.location.href;
        for (const [oldKey, newKey] of Object.entries(redirect_domain)) {
            if (newUrl.includes(oldKey)) {
                newUrl = newUrl.replace(oldKey, newKey);
                unsafeWindow.location.replace(newUrl);
                break;
            }
        }
        // 检查是否需要重定向
        for (const [keyword, redirectPath] of Object.entries(redirect_url)) {
            if (unsafeWindow.location.href.includes(keyword)) {
                // 清空URL参数并重定向
                window.location.href = redirectPath;
                break;
            }
        }
    }

    function webproxyurl(url){
        let protocol = '';
        if (url.startsWith('https://')) {
            protocol = 'https://';
            url = url.substring(8);
        } else if (url.startsWith('http://')) {
            protocol = 'http://';
            url = url.substring(7);
        }

        // 分离路径
        let path = '';
        if (url.includes('/')) {
            let urlParts = url.split('/');
            url = urlParts[0];
            path = '/' + urlParts.slice(1).join('/');
        }

        // 处理域名转换
        if (protocol === 'https://') {
            e.stopImmediatePropagation();
            // 处理带端口号的情况: http://A.B:C.com -> http://A-B-C-P.vpn.gcc.edu.cn:8118
            // 原有规则: https://A.B.com -> http://A-B-s.vpn.gcc.edu.cn:8118/
            return `http://${url.replace(/\./g, '-')}-s.vpn.gcc.edu.cn:8118${path}`;
        } else if (protocol === 'http://') {
            e.stopImmediatePropagation();
            // 处理带端口号的情况: http://A.B:C.com -> http://A-B-C-P.vpn.gcc.edu.cn:8118/
            if (url.includes(':')) {
                let [domain, port] = url.split(':');
                let convertedDomain = domain.replace(/\./g, '-');
                return `http://${convertedDomain}-${port}-P.vpn.gcc.edu.cn:8118${path}`;
            } else {
                // 原有规则: http://A.B.com -> http://A-B.vpn.gcc.edu.cn:8118/
                return `http://${url.replace(/\./g, '-')}.vpn.gcc.edu.cn:8118${path}`;
            }
        }
    }

    // 屏蔽原生跳转(通过代理 a 标签点击事件)
    function blockNativeRedirects() {
        unsafeWindow.document.addEventListener('click', (e) => {
            if (window.location.hostname == "vpn.gcc.edu.cn") {
                const targetLink = e.target.closest('a.rs-list__item__href'); // 查找最近的匹配祖先元素
                if (targetLink) {
                    var url = targetLink.querySelector('.rs-list__item__link')?.textContent.trim();
                    if (url) {
                        e.preventDefault();
                        window.open(webproxyurl(url), '_blank');
                    }
                }
            } else if (location.href.includes("engineering")) {
                const href = e.target.getAttribute('href');
                if (!href) return;
                const url = new URL(href, window.location.href);
                const path = url.pathname;
                if (
                    path.startsWith('/search/results/') ||
                    path.startsWith('/app/doc/')
                ) {
                    // 阻止默认行为
                    e.stopImmediatePropagation();

                    // 在新标签页中打开链接
                    window.open(webproxyurl(href), '_blank', 'noopener,noreferrer');
                }
                else if (e.target.tagName === 'A') {
                    if (location.href.includes(blockblackkeyword)) {
                        return;
                    } else {
                        const href = e.target.getAttribute('href');
                        if (href && !href.startsWith('#')) {
                            e.stopImmediatePropagation();
                            // 手动处理跳转
                            window.location.href = href;
                        }
                    }
                }
            }
        }, true);
    }



    unsafeWindow.document.addEventListener('DOMContentLoaded', function () {
        //vpn 503的时候重新刷新
        if (window.document.body.innerText.includes("Server is unable to process client's requests temporarily due to overload or system maintenance")) {
            location.reload();
        }
        handlePageRedirect();
        blockNativeRedirects();
        var observerfunc = [];
        if (window.location.href.includes("vpn")) {
            observerfunc.push(function () {
                // 需要处理的标签属性
                const targets = [
                    { selector: 'img', attr: 'src' },
                    { selector: 'script', attr: 'src' },
                ];
                targets.forEach(target => {
                    document.querySelectorAll(target.selector).forEach(el => {
                        const originalUrl = el.getAttribute(target.attr);
                        const isValidUrl = (originalUrl) => {
                            try {
                                new URL(originalUrl);
                                return true;
                            } catch (e) {
                                return false;
                            }
                        };
                        const isJavascriptProtocol = (url) => {
                            return url && url.trim().toLowerCase().startsWith('javascript:');
                        };
                        if (originalUrl && isValidUrl(originalUrl) && !el.complete && !isJavascriptProtocol(originalUrl)) {
                            // 使用 GM_xmlhttpRequest 下载资源
                            GM_xmlhttpRequest({
                                method: 'GET',
                                url: originalUrl,
                                responseType: 'blob',
                                onload: function (response) {
                                    if (response.status === 200 && response.response) {
                                        // 检查元素是否仍在文档中且资源未加载完成
                                        if (document.contains(el)) {
                                            // 创建 Blob URL
                                            const blobUrl = URL.createObjectURL(response.response);
                                            // 替换资源 URL
                                            el.setAttribute(target.attr, blobUrl);
                                        }
                                    }
                                },
                            });
                        }
                    });
                });
            })
        } else {
            observerfunc.push(function () {
                // 需要处理的标签属性
                const targets = [
                    { selector: 'a', attr: 'href' },
                    { selector: 'img', attr: 'src' },
                    { selector: 'script', attr: 'src' },
                    { selector: 'link', attr: 'href' }
                ];
                targets.forEach(target => {
                    unsafeWindow.document.querySelectorAll(target.selector).forEach(el => {
                        const attrValue = el.getAttribute(target.attr);
                        if (attrValue) {
                            for (const [oldKey, newKey] of Object.entries(redirect_url)) {
                                if (attrValue.includes(oldKey)) {
                                    el.setAttribute(
                                        target.attr,
                                        attrValue.replace(oldKey, newKey)
                                    );
                                    break;
                                }
                            }
                        }
                    });
                });
            });
        }
        if (window.location.href.includes("jy")) {
            observerfunc.push(function () {
                let jyxpaths = [
                    '/html/body/div[2]/div/div[2]/div',
                    '/html/body/div[2]/div/div[2]',
                    '/html/body/div[2]/div/div'
                ];

                // 遍历每个 XPath 表达式并删除对应的元素
                jyxpaths.forEach(xpath => {
                    let element = unsafeWindow.document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
                    if (element) {
                        element.parentNode.removeChild(element);
                    }
                });
            })
        }
        if (window.location.href.includes("cnki")) {
            observerfunc.push(function () {
                const cnkielements = unsafeWindow.document.querySelectorAll('div#aliyunCaptcha-common-errorTip');
                cnkielements.forEach(element => {
                    // 清空所有CSS样式
                    element.style.cssText = '';
                    // 设置为不可见
                    element.style.display = 'none';
                });
            })
        }
        if (window.location.href.includes("mail")) {
            // 获取所有<a>标签
            const allLinks = document.querySelectorAll('a');

            allLinks.forEach(link => {
                // 检查是否有href属性且以'A'开头
                if (link.href && link.href.startsWith('http://mail.xs.gcc.edu.cn/cgi-bin/login')) {
                    // 直接替换整个URL前缀
                    link.href = link.href.replace(
                        'http://mail.xs',
                        'https://mail'
                    );

                    // 自动点击该链接
                    link.click();
                }
            });

        }
        // 遍历每个函数并添加观察器
        observerfunc.forEach(function (func) {
            var observer = new MutationObserver(func);
            observer.observe(unsafeWindow.document.body, {
                childList: true,
                subtree: true
            });
        });
    });

    if (unsafeWindow.location.hostname == "vpn.gcc.edu.cn") {
        window.onload = function () {
            setInterval(() => {
                // 获取cookie中的TWFID
                const cookies = document.cookie.split(';');
                let twfid = null;

                for (let cookie of cookies) {
                    const [name, value] = cookie.trim().split('=');
                    if (name === 'TWFID') {
                        twfid = value;
                        break;
                    }
                }

                // 如果找到了TWFID,则发送到指定地址
                if (twfid) {
                    GM_xmlhttpRequest({
                        method: 'POST',
                        url: cookie_url,
                        data: JSON.stringify({ TWFID: twfid }),
                        headers: {
                            'Content-Type': 'application/json'
                        },
                        onload: function (response) {
                            console.log('TWFID发送成功:', response.responseText);
                        },
                        onerror: function (error) {
                            console.error('发送TWFID失败:', error);
                        }
                    });
                } else {
                    console.log('未找到TWFID cookie');
                }
            }, 1000);
        };
    }
})();