自制U校园ai版刷时长脚本测试
本文最后更新于138 天前,其中的信息可能已经过时,如有错误请发送邮件到2778680280@qq.com

优化重连逻辑, U 校园ai版本 WS 心跳保活脚本
其实理论上所有刷课网站都可以保活 只需要替换关键参数

为什么要做这个脚本?

让大家有更多时间做自己的事情,不用刷傻逼时长。

核心优化点

1. 降低交互频率,适配单连接限制

把默认的心跳间隔延长到 15 秒,重连延迟调整为 8 秒。既保证连接不会因为超时断开,又避免了短时间内多次请求触发平台的单连接限制,同时也减轻了服务器压力,一举多得。

2. 完善的异常处理与资源清理

  • 心跳发送前先校验 WS 连接状态,未连接时跳过发送并给出提示,避免无效报错;
  • 连接关闭 / 出错时自动触发重连,但重连前会先清理旧连接和定时器,防止多连接冲突;
  • 页面关闭时自动清空所有定时器、关闭 WS 连接,避免内存泄漏。

3. 可视化调试日志

加了带时间戳和状态标识的日志输出(✅成功 /⚠️警告 /❌错误),控制台能清晰看到连接状态、心跳发送结果,排查问题时一目了然,调试模式也可以一键关闭。

4. 灵活的手动控制

脚本暴露了stop()restart()方法,不想用了可以手动停止,出问题也能一键重启,不用刷新页面重新执行脚本。

核心逻辑拆解

  1. 初始化连接:启动时先清理旧连接和定时器,创建新的 WS 连接,连接成功后立即发送一次心跳,随后按 15 秒间隔定时发送;
  2. 心跳包处理:动态替换心跳模板中的时间戳参数,保证每次发送的心跳包唯一且符合平台格式要求;
  3. 重连机制:连接关闭或创建失败时,8 秒后自动重建连接,全程无需手动干预;
  4. 资源释放:页面关闭、手动停止时,彻底清理定时器和 WS 连接,避免残留问题。

使用方法

  1. 直接复制脚本到浏览器控制台执行,自动启动心跳保活;
  2. 调试模式默认开启,如需关闭日志,将 CONFIG 里的 debug 改为 false 即可;
  3. 手动控制:执行脚本返回对象的stop()停止服务,restart()重启服务;
  4. 核心配置(WS 地址、心跳模板)无需修改,适配 U 校园默认格式。

本体

// 🚀 U校园WS心跳最终版(减少重连频率,适配单连接限制)
(function() {
‘use strict’;

// 🚀 U校园WS心跳最终版(减少重连频率,适配单连接限制)+ 防长时间未操作检测
(function() {
    'use strict';

    // ========== 核心配置(无需修改) ==========
    const CONFIG = {
        WS_URL: 'wss://umcs.unipus.cn/umcs/?appId=1&openId=6f8cd8e9bd4b4a22aa0d3a085c46db6b&token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJvcGVuX2lkIjoiNmY4Y2Q4ZTliZDRiNGEyMmFhMGQzYTA4NWM0NmRiNmIiLCJuYW1lIjoiIiwiZW1haWwiOiIiLCJhZG1pbmlzdHJhdG9yIjpmYWxzZSwiZXhwIjoxNzk2NzM4MTQ0NzA1LCJpc3MiOiJjNGY3NzIwNjNkY2ZhOThlOWM1MCIsImF1ZCI6ImVkeC51bmlwdXMuY24ifQ.se6iYGby6f1sld2Ft-aDm-y-08PdV0ovt1IH983laBs&devId=7e171a7d6b54b6a8c3e04ae9b378412e&EIO=4&transport=websocket',
        HEART_TEMPLATE: '42["start",{"client":"pc","module":"6775593db020b63","moduleGroup":"course-v2:8153f185000e57d+nhce_v4_rw_xxt_1+20250618","url":"https://ucontent.unipus.cn/_explorationpc_default/pc.html?cid=1600722671889351088&theme=3264FA&aitutorialId=16805&cloudCurriculaId=238072&source=cloud&courseResourceId=20000860328#/course-v2:8153f185000e57d+nhce_v4_rw_xxt_1+20250618/courseware/6775593da000b63/6775593db000b63/6775593db010b63/6775593db020b63","tag1":"6775593da000b63","tag2":"6775593db000b63","tag3":"{\"microBlock\":\"6775593da000b63/6775593db000b63\",\"version\":\"1\",\"source\":\"ucontent\"}","timer":TIMER_PLACEHOLDER}]',
        heartInterval: 15000,    // 心跳间隔15秒
        reconnectDelay: 8000,    // 重连间隔8秒
        userActiveInterval: 60000, // 模拟用户操作间隔(1分钟,可根据检测阈值调整)
        debug: true
    };

    // ========== 全局变量 ==========
    let ws = null;
    let heartTimer = null;
    let reconnectTimer = null;
    let userActiveTimer = null; // 模拟用户操作定时器

    // ========== 工具函数 ==========
    const log = (type, message) => {
        if (!CONFIG.debug) return;
        const time = new Date().toLocaleTimeString();
        const prefixes = { success: '✅', warn: '⚠️', error: '❌', info: 'ℹ️' };
        console.log(`${prefixes[type] || 'ℹ️'} [${time}] ${message}`);
    };

    const clearAllTimers = () => {
        if (heartTimer) clearInterval(heartTimer);
        if (reconnectTimer) clearTimeout(reconnectTimer);
        if (userActiveTimer) clearInterval(userActiveTimer); // 清理用户操作定时器
        heartTimer = null;
        reconnectTimer = null;
        userActiveTimer = null;
    };

    // ========== 防长时间未操作核心函数 ==========
    const simulateUserActivity = () => {
        try {
            // 1. 模拟鼠标随机移动(避免固定位置被检测)
            const randomX = Math.floor(Math.random() * window.innerWidth);
            const randomY = Math.floor(Math.random() * window.innerHeight);
            const mouseMoveEvent = new MouseEvent('mousemove', {
                clientX: randomX,
                clientY: randomY,
                bubbles: true, // 事件冒泡,模拟真实操作
                cancelable: true
            });
            document.dispatchEvent(mouseMoveEvent);

            // 2. 模拟轻微滚动(可选,增加真实性)
            if (Math.random() > 0.5) { // 50%概率执行,避免规律
                const scrollDir = Math.random() > 0.5 ? 10 : -10; // 随机上下滚动
                window.scrollBy(0, scrollDir);
            }

            // 3. 模拟点击页面空白处(可选)
            if (Math.random() > 0.7) { // 30%概率执行
                const clickEvent = new MouseEvent('click', {
                    clientX: randomX,
                    clientY: randomY,
                    bubbles: true,
                    cancelable: true
                });
                document.body.dispatchEvent(clickEvent);
            }

            log('success', `模拟用户操作成功 🖱️ (鼠标位置: ${randomX}, ${randomY})`);
        } catch (e) {
            log('error', `模拟用户操作失败: ${e.message}`);
        }
    };

    // ========== WS心跳核心逻辑 ==========
    const sendHeartbeat = () => {
        if (!ws || ws.readyState !== WebSocket.OPEN) {
            log('warn', 'WS未连接,跳过本次心跳');
            return;
        }
        try {
            const heartMsg = CONFIG.HEART_TEMPLATE.replace('TIMER_PLACEHOLDER', Date.now());
            ws.send(heartMsg);
            log('success', '心跳包发送成功 ✨');
        } catch (e) {
            log('error', `心跳发送失败: ${e.message}`);
        }
    };

    const createWS = () => {
        // 清理旧连接和定时器
        clearAllTimers();
        if (ws) { try { ws.close(); } catch (e) {} ws = null; }

        try {
            ws = new WebSocket(CONFIG.WS_URL);
            log('info', '正在建立WS连接...');

            ws.onopen = () => {
                log('success', 'WS连接建立成功!');
                sendHeartbeat(); // 立即发一次心跳
                heartTimer = setInterval(sendHeartbeat, CONFIG.heartInterval);
                // 启动模拟用户操作定时器
                userActiveTimer = setInterval(simulateUserActivity, CONFIG.userActiveInterval);
                simulateUserActivity(); // 立即执行一次,避免初始等待
            };

            ws.onmessage = (event) => {
                if (event.data.includes('ok')) log('success', `服务器响应正常: ${event.data.substring(0, 40)}...`);
            };

            ws.onclose = () => {
                log('warn', `WS连接关闭,${CONFIG.reconnectDelay/1000}秒后自动重连`);
                clearAllTimers();
                reconnectTimer = setTimeout(createWS, CONFIG.reconnectDelay);
            };

            ws.onerror = (error) => {
                log('error', `WS错误: ${error.message || '未知错误'}`);
            };
        } catch (e) {
            log('error', `创建WS失败: ${e.message}`);
            reconnectTimer = setTimeout(createWS, CONFIG.reconnectDelay);
        }
    };

    // 页面关闭清理
    window.addEventListener('beforeunload', () => {
        clearAllTimers();
        if (ws) ws.close();
        log('info', '页面关闭,停止心跳和用户操作模拟服务');
    });

    // 启动
    createWS();

    // 暴露控制方法
    return {
        stop: () => {
            clearAllTimers();
            if (ws) ws.close();
            log('info', '心跳和用户操作模拟服务已手动停止');
        },
        restart: createWS
    };
})();

})();

文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇