更好访问gcc

一点小小hook

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==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);
        };
    }
})();