广州商学院学习通防网卡

小小的hook

当前为 2025-05-22 提交的版本,查看 最新版本

// ==UserScript==
// @name         广州商学院学习通防网卡
// @namespace    http://tampermonkey.net/
// @version      1.2
// @author       LinXingJun
// @description  小小的hook
// @run-at       document-start
// @match        *://*.chaoxing.com/*
// @grant        GM_xmlhttpRequest
// @grant        unsafeWindow
// @connect      i.mooc.chaoxing.com
// @license MIT
// ==/UserScript==

const videoSelector = 'video';
const retryOnErrorMap = new WeakMap();

// 创建错误处理函数
function createRetryOnvideoError(video) {
    return function () {
        console.log("重新加载视频...");
        this.load();
    };
}

// 为指定的 video 元素绑定错误监听器
function videobindErrorListener(video) {
    // 如果已有监听器,先移除
    const existingHandler = retryOnErrorMap.get(video);
    if (existingHandler) {
        video.removeEventListener('error', existingHandler, true);
    }

    // 创建新监听器
    const handler = createRetryOnvideoError.bind(video)();
    video.addEventListener('error', handler, true);

    // 保存引用
    retryOnErrorMap.set(video, handler);
}

// 初始化绑定所有现有的 <video> 元素
function videoinit() {
    unsafeWindow.document.querySelectorAll(videoSelector).forEach(videobindErrorListener);
}

// MutationObserver 回调:检测新增的 <video> 元素
function handlevideoDOMChanges(mutationsList) {
    for (const mutation of mutationsList) {
        if (mutation.type === 'childList') {
            mutation.addedNodes.forEach(node => {
                if (node.nodeType === 1) { // 是元素节点
                    if (node.matches(videoSelector)) {
                        videobindErrorListener(node);
                    } else {
                        node.querySelectorAll(videoSelector).forEach(videobindErrorListener);
                    }
                }
            });
        }
    }
}

// 启动监听器
function startvideoObserving() {
    const observer = new MutationObserver(handlevideoDOMChanges);
    observer.observe(unsafeWindow.document.body || unsafeWindow.document.documentElement, {
        childList: true,
        subtree: true
    });
}


(function () {
    'use strict';
    if (unsafeWindow.top !== unsafeWindow.self && unsafeWindow.location.protocol === 'https:') {
        console.log("由于你家gcc的神奇运维,可能会遭遇到混合内容报错")
    }
    // 保存原生的 setInterval
    const originalSetInterval = unsafeWindow.setInterval;

    // 重写 setInterval
    unsafeWindow.setInterval = function (callback, delay) {
        // 仅当原间隔为 30000 时修改为 10
        if (delay === 30000) {
            delay = 10;
            console.log("延迟修改成功");
        }
        // 调用原生 setInterval
        return originalSetInterval.apply(this, arguments);
    };

    videoinit();
    unsafeWindow.document.addEventListener("DOMContentLoaded", (event) => {
        startvideoObserving();
        const originalOpen = unsafeWindow.XMLHttpRequest.prototype.open;
        const originalSend = unsafeWindow.XMLHttpRequest.prototype.send;
        const originalSetRequestHeader = unsafeWindow.XMLHttpRequest.prototype.setRequestHeader;

        // 存储请求头和请求体
        const requestHeaders = new WeakMap();
        const requestBodyStore = new WeakMap();

        // 覆盖setRequestHeader以保存请求头
        unsafeWindow.XMLHttpRequest.prototype.setRequestHeader = function (header, value) {
            if (!requestHeaders.has(this)) {
                requestHeaders.set(this, new Map());
            }
            requestHeaders.get(this).set(header, value);
            return originalSetRequestHeader.apply(this, arguments);
        };

        // 覆盖open以保存请求参数
        unsafeWindow.XMLHttpRequest.prototype.open = function (method, url, async, user, password) {
            this._method = method;
            this._url = url;
            this._async = async;
            this._user = user;
            this._password = password;
            return originalOpen.apply(this, arguments);
        };

        // 覆盖send以保存请求体并实现重试逻辑
        unsafeWindow.XMLHttpRequest.prototype.send = function (body) {
            // 保存请求体
            requestBodyStore.set(this, body);
            // 检查是否是目标URL和POST请求
            if (
                this._method.toUpperCase() === 'POST' && this._url.includes("/mooc-ans/work")
            ) {
                console.log("正在跟踪", this._url);
                const retry = () => {
                    const newXHR = new unsafeWindow.XMLHttpRequest();
                    newXHR.open(this._method, this._url, this._async, this._user, this._password);

                    // 恢复请求头
                    if (requestHeaders.has(this)) {
                        const headers = requestHeaders.get(this);
                        headers.forEach((value, key) => {
                            newXHR.setRequestHeader(key, value);
                        });
                    }

                    // 重新发送请求
                    newXHR.send(requestBodyStore.get(this));
                };

                // 监听错误和超时事件
                this.addEventListener('error', () => {
                    console.log('请求失败(网络错误),正在重试:', this._url);
                    retry();
                });

                this.addEventListener('timeout', () => {
                    console.log('请求超时,正在重试:', this._url);
                    retry();
                });
            }

            return originalSend.apply(this, arguments);
        };
    });

})();

QingJ © 2025

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