// ==UserScript== // @name 🍀重庆医科大学|使用说明:http://doc.zhanyc.cn/pages/cqykdx/ // @namespace free // @version 1.1 // @description 当前是免费版本,只包含了列表自动打开、解除视频播放限制功能。如需自动下一集、自动换课程、全自动无人值守等高级功能可升级付费版本|接各类脚本开发、代挂任务,微信:zhanyc_cn 个人网站:http://doc.zhanyc.cn // @include *://*cqmu.edu.cn* // @include *://*.cqmu.edu.cn/* // @grant GM_getValue // @grant GM_setValue // @grant GM_deleteValue // @grant window.close // @run-at document-end // @require http://libs.baidu.com/jquery/2.0.0/jquery.min.js // @antifeature payment // @license Creative Commons // ==/UserScript== (function () { let $jq = $; unsafeWindow.$jq = $; let docUrl = "http://doc.zhanyc.cn/pages/cqykdx/"; let isDev = false; let xyb = { pageData: { videoTimer: null, videoCheckTimer: null, waitIndexArr: [], }, // 悬浮引流面板 showFloatingPanel() { if ($(".xyb-float-panel").length > 0) return; let panelHtml = `
🍀 重庆医科大学脚本
✅ 列表自动打开
✅ 解除视频暂停限制
脚本准备就绪
🔥 一次付费 · 永久使用 · 免费维护
如需使用全功能版本,请通过地址安装付费版本购买授权后可使用
✅ 5倍速
✅ 自动下一集
✅ 自动换课程
✅ 全自动无人值守
✅ 永久授权
👉 点击查看付费版本
接各类脚本开发、代挂、网站小程序开发工作
微信:zhanyc_cn
`; $("body").append(panelHtml); $(".xyb-panel-close").on("click", function () { $(".xyb-float-panel").remove(); }); }, updateStatus(msg) { let $panel = $(".xyb-float-panel"); if ($panel.length > 0) { $panel.find(".xyb-panel-status").text(msg); } }, // 初始化 async init() { console.log("%c xyb init", "background:rgb(0,0,0);color:#fff"); xyb.showFloatingPanel(); await xyb.waitUntil(() => $("body").length > 0); xyb.routeByUrl(location.href); // URL变更检测 let lastUrl = location.href; setInterval(() => { if (lastUrl != location.href) { lastUrl = location.href; // 清理定时器 if (xyb.pageData.videoTimer) { clearInterval(xyb.pageData.videoTimer); xyb.pageData.videoTimer = null; } if (xyb.pageData.videoCheckTimer) { clearTimeout(xyb.pageData.videoCheckTimer); xyb.pageData.videoCheckTimer = null; } xyb.pageData.waitIndexArr.forEach(idx => clearInterval(idx)); xyb.pageData.waitIndexArr = []; xyb.routeByUrl(location.href); } }, 500); }, // 路由 async routeByUrl(url) { url = url.toLowerCase(); if (url.includes("/courseadult")) { xyb.page_list(); } else if (url.includes("/studynotes")) { xyb.page_video(); } }, // 列表页面 - 自动打开未完成课程 async page_list() { console.log("%c page_list", "background:rgb(0,0,0);color:#fff"); xyb.updateStatus("正在加载课程列表..."); await xyb.waitUntil(() => $(".course-list .item:visible").length > 0); await xyb.sleep(1000); let $el = null; $(".course-list .item:visible").each((i, el) => { let jd = Number($(el).find(`[role="progressbar"]`).attr('aria-valuenow')); if (jd < 100) { $el = $(el); return false; } }); if ($el == null) { xyb.updateStatus("所有课程已完成"); return; } xyb.updateStatus("正在打开课程..."); await xyb.sleep(3000); $el.find('.itemButton button').click(); }, // 视频页面 - 解除播放限制 async page_video() { console.log("%c page_video", "background:rgb(0,0,0);color:#fff"); if (xyb.pageData.videoTimer != null) return; let lastTime = null; let stuckCount = 0; xyb.updateStatus("视频播放功能已启动"); // 卡住检测 xyb.pageData.videoCheckTimer = setTimeout(async () => { let t = xyb.getCurTime(); await xyb.sleep(5000); if (xyb.getCurTime() == t) { xyb.updateStatus("视频卡住,正在刷新页面..."); location.reload(); } }, 60 * 1000); // 主循环 xyb.pageData.videoTimer = setInterval(async () => { try { if (!xyb.getVideo()) return; // 点击大播放按钮 if ($(".vjs-big-play-button:visible").length > 0) { $(".vjs-big-play-button:visible").click(); return; } // 解除播放限制 - 自动播放 let isPlaying = await xyb.checkIsPlaying(); if (!isPlaying) { xyb.playVideo(); xyb.updateStatus("▶ 正在播放视频..."); } xyb.getVideo().volume = 0; let curTime = xyb.getCurTime(); let totalTime = xyb.getTotalTime(); // 卡住检测 if (curTime == lastTime) { stuckCount += 2; if (stuckCount >= 60) { xyb.updateStatus("视频卡住,正在刷新..."); location.reload(); return; } } else { stuckCount = 0; lastTime = curTime; } // 更新进度显示 let progress = totalTime > 0 ? (curTime / totalTime * 100).toFixed(1) : 0; let curStr = xyb.formatTime(curTime); let totalStr = xyb.formatTime(totalTime); xyb.updateStatus(`▶ 视频播放中 ${progress}% [${curStr}/${totalStr}]`); // 标题显示进度 $("title").text(`进度:${curTime.toFixed(0)}/${totalTime.toFixed(0)}`); // 检测播放完成 if (totalTime > 0 && curTime + 5 >= totalTime) { xyb.updateStatus("视频即将结束,准备下一个..."); clearInterval(xyb.pageData.videoTimer); xyb.pageData.videoTimer = null; xyb.goNextVideo(); } } catch (e) { console.error("视频页面定时器出错", e); } }, 2000); }, // 播放完成后点击下一个 goNextVideo() { setTimeout(() => { $(".opera.fr").click(); }, 10000); }, // 获取视频元素 getVideo() { return $("video")[0]; }, // 播放视频 playVideo() { let video = xyb.getVideo(); if (video) { video.volume = 0; setTimeout(() => { xyb.getVideo().play(); }, 200); } }, // 检测视频是否在播放 checkIsPlaying() { return new Promise((resolve) => { try { let curTime = xyb.getCurTime(); setTimeout(() => { let time1 = xyb.getCurTime(); if (time1 > curTime) { setTimeout(() => { let time2 = xyb.getCurTime(); resolve(time2 > time1); }, 100); } else { resolve(false); } }, 100); } catch (e) { resolve(false); } }); }, // 获取当前播放时间(硬编码) getCurTime() { try { return xyb.getVideo().currentTime; } catch (e) { return 0; } }, // 获取总时长(硬编码) getTotalTime() { try { return xyb.getVideo().duration; } catch (e) { return 0; } }, // 格式化时间为 HH:MM:SS formatTime(seconds) { seconds = Math.floor(Math.abs(seconds)); let hours = Math.floor(seconds / 3600); let minutes = Math.floor((seconds % 3600) / 60); let secs = seconds % 60; hours = (hours < 10) ? "0" + hours : hours; minutes = (minutes < 10) ? "0" + minutes : minutes; secs = (secs < 10) ? "0" + secs : secs; return hours + ":" + minutes + ":" + secs; }, // 等待条件满足 waitUntil(fun, interval = 1000, timeout = 60) { return new Promise((resolve, reject) => { let _timeOut = timeout * 1000; try { if (fun()) return resolve(); } catch (e) { } let index = setInterval(() => { try { if (timeout != -1) { _timeOut -= interval; if (_timeOut < 0) { clearInterval(index); return reject(); } } if (fun()) { clearInterval(index); return resolve(); } } catch (e) { } }, interval); xyb.pageData.waitIndexArr.push(index); }); }, // 延时 sleep(timeout) { return new Promise((resolve) => { setTimeout(resolve, timeout); }); }, }; // 3秒后初始化,检测付费版本是否在运行 setTimeout(() => { if (typeof (zfk) == 'undefined') { xyb.init(); } else { console.log('skip init'); } }, 3000); })();