// ==UserScript== // @name 安徽专业技术人员继续教育在线|如需自动下一集、自动换课程、[秒过]、[考试答题]等高级功能见收费版本:http://doc.zhanyc.cn/pages/ahzjjyzx/ // @namespace free // @version 1.0 // @description 当前是免费版本,只包含了视频页面自动播放、解除播放暂停限制、自动关闭弹窗功能。永久授权、免费更新!如需自动下一集、自动换课程、[秒过]、[考试答题]、全自动无人值守高级功能可升级付费版本|接各类脚本开发、代挂工作,微信:zhanyc_cn 个人网站:http://doc.zhanyc.cn // @include *://*zjzx.ah.cn* // @include *://*.zjzx.ah.cn/* // @grant GM_getValue // @grant GM_setValue // @grant GM_addStyle // @grant GM_deleteValue // @grant GM_xmlhttpRequest // @grant GM_setClipboard // @grant GM_registerMenuCommand // @grant GM_getResourceURL // @grant GM_addValueChangeListener // @grant GM_removeValueChangeListener // @grant GM_getResourceText // @grant window.close // @run-at document-end // @require http://libs.baidu.com/jquery/2.0.0/jquery.min.js // ==/UserScript== (function () { let $jq = $; unsafeWindow.$jq = $; let docUrl = "http://doc.zhanyc.cn/pages/ahzjjyzx/"; let FREEJS = { pageData: { videoMGIndex: null, confirmRunZIndex: 19991018, waitTime: 0, video: { index: null, }, }, async init() { console.log("%c FREEJS init", "background:rgb(0,0,0);color:#fff"); FREEJS.addStyle(); FREEJS.setHook(); FREEJS.runByUrl(location.href); }, async runByUrl(url) { clearInterval(FREEJS.pageData.video.index) FREEJS.pageData.video.index = null url = url.toLocaleLowerCase() if (top == window) { FREEJS.page_top() } if (url.includes("courseplay".toLocaleLowerCase())) { FREEJS.page_video(); } else if (url.includes("/personcenter".toLocaleLowerCase())) { FREEJS.page_list(); } }, page_top() { FREEJS.waitOf(a => FREEJS.getElByText($(".el-common_show_roll_pc b"), "关闭") != null).then(a => { setTimeout(() => { $(".el-common_show_roll_pc b").click() }, 3000); }) }, async page_list() { console.log("%c page_list", "background:rgb(0,0,0);color:#fff"); FREEJS.updatePanelText("当前为课程列表页面,请手动点击课程进入学习,脚本将自动播放视频") }, async page_video() { console.log("%c page_video", "background:rgb(0,0,0);color:#fff"); let timeout = 2; let lastTime = null; let checkTimeTimesBak = 60; let checkTimeTimes = checkTimeTimesBak; if (FREEJS.pageData.video.index != null) { return; } setTimeout(async () => { let time = FREEJS.getCurTime() await FREEJS.waitTimeout(5000) if (FREEJS.getCurTime() == time) { FREEJS.updatePanelText("貌似卡住了,3秒后刷新页面") await FREEJS.waitTimeout(3000) location.reload() } }, 60 * 1000); FREEJS.updatePanelText("视频自动播放中...") FREEJS.pageData.video.index = setInterval(async () => { try { if (FREEJS.pageData.waitTime > 0) { FREEJS.pageData.waitTime -= timeout; return; } if ($(".xgplayer-error-text:visible").text().includes('请刷新试试')) { FREEJS.updatePanelText("检测到错误提示,准备刷新页面") await FREEJS.waitTimeout(3000) location.reload() return } if (!FREEJS.getVideo()) { console.log("%c FREEJS no video", "background:rgb(0,0,0);color:#fff"); return; } let curTime = FREEJS.getCurTime(); if (curTime == lastTime) { lastTime = FREEJS.getCurTime(); checkTimeTimes -= timeout; if (checkTimeTimes <= 0) { checkTimeTimes = checkTimeTimesBak; FREEJS.updatePanelText("貌似卡死了,请手动返回列表页面") FREEJS.pageData.waitTime = 10; return; } } else { lastTime = curTime; checkTimeTimes = checkTimeTimesBak; } FREEJS.getVideo().volume = 0; let title = `进度:${FREEJS.getCurTime().toFixed(0)}/${FREEJS.getTotalTime().toFixed(0)}`; $("title").text(title); FREEJS.updatePanelText(`视频自动播放中 | ${title}`) console.log("%c video run", "background:rgb(255,0,0);color:#fff"); let isFinish = await FREEJS.isPlayFinish(); if (isFinish) { FREEJS.pageData.waitTime = 15; FREEJS.updatePanelText("视频即将结束") clearInterval(FREEJS.pageData.video.index) FREEJS.pageData.video.index = null return; } let isPlay = await FREEJS.videoIsPlay(); if (!isPlay) { if (!isFinish) { FREEJS.play(); } } } catch (e) { console.error("视频页面定时器出错", e); } }, timeout * 1000); }, play() { FREEJS.getVideo().volume = 0; setTimeout(() => { FREEJS.getVideo().play(); }, 200); }, getVideo() { return $("video")[0]; }, isPlayFinish() { try { return ( FREEJS.getTotalTime() > 0 && FREEJS.getCurTime() + 5 >= FREEJS.getTotalTime() ); } catch (e) { return false; } }, getCurTime() { let res = 0; try { res = FREEJS.getVideo().currentTime; } catch (e) { console.error(e); } return res; }, getTotalTime() { let res = 0; try { res = FREEJS.getVideo().duration; } catch (e) { console.error(e); } return res; }, async videoIsPlay() { return new Promise((resolve) => { try { let curTime = $("video")[0].currentTime; setTimeout(() => { let time1 = $("video")[0].currentTime; let res = time1 > curTime; if (res) { setTimeout(() => { let time2 = $("video")[0].currentTime; let res2 = time2 > time1; resolve(res2); }, 100); } else { return resolve(false); } }, 100); } catch (e) { resolve(false); } }); }, addStyle() { GM_addStyle(` .zfk-btn{background-color:#0fbcf9;color:#fff;padding:4px 12px;border:none;box-sizing:content-box;font-size:14px;height:20px;border-radius:4px;cursor:pointer;display:inline-block;border:1px solid transparent;white-space:nowrap;user-select:none;text-align:center;vertical-align:middle}.zfk-btn:hover{opacity:.8}.zfk-btn.success{background-color:#38b03f}.zfk-btn.warning{background-color:#f1a325}.zfk-btn.info{background-color:#03b8cf}.zfk-btn.danger{background-color:#ea644a} `); }, // ========== 悬浮引流面板 ========== initFloatPanel() { if ($("#freejs-float-panel").length > 0) return; let panelHtml = `
脚本运行中(免费版) ×
初始化中...
🔥 付费脚本:一次购买 · 永久使用 · 永久更新
✔ 当前免费功能:
   • 解除视频暂停限制
   • 视频自动播放
   • 自动关闭弹窗
★ 付费版专属功能:
   • 自动下一集 / 自动换课程
   • [秒过] 快速完成学习
   • [考试答题] 自动答题
   • 全自动无人值守
立即升级全功能版本 →
接各类脚本开发、代挂工作
微信:zhanyc_cn
`; $("body").append(panelHtml); $("#freejs-panel-close").click(function () { $("#freejs-float-panel").hide(); }); // 拖拽 let isDragging = false, startX, startY, startLeft, startTop; $("#freejs-panel-header").on("mousedown", function (e) { if ($(e.target).is("#freejs-panel-close")) return; isDragging = true; startX = e.clientX; startY = e.clientY; let $panel = $("#freejs-float-panel"); startLeft = $panel.position().left; startTop = $panel.position().top; e.preventDefault(); }); $(document).on("mousemove", function (e) { if (!isDragging) return; let dx = e.clientX - startX; let dy = e.clientY - startY; $("#freejs-float-panel").css({ left: startLeft + dx + "px", top: startTop + dy + "px" }); }); $(document).on("mouseup", function () { isDragging = false; }); }, updatePanelText(text) { $("#freejs-panel-status").text(text); }, // ========== 工具方法 ========== waitTimeout(timeout) { return new Promise((resolve) => { setTimeout(() => resolve(), timeout); }); }, waitOf(fun, interval = 1000, timeout = 60) { console.log("%c waitOf", "background:rgb(0,0,0);color:#fff", fun); return new Promise((resolve, reject) => { let _timeOut = timeout * 1000; try { if (fun()) { return resolve(); } } catch (e) { console.error(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) { console.error(e); } }, interval); }); }, getGMData(item, def) { return GM_getValue(item, def); }, setGMData(item, val) { return GM_setValue(item, val); }, delGMData(item) { return GM_deleteValue(item); }, now() { return new Date().getTime(); }, getElByText(query, text, mode = "eq", visible = true) { let $el = null; text = text.trim() $(query).each((i, el) => { if (visible && !$(el).is(":visible")) { return true; } if (mode == "eq" && $(el).text().trim() == text) { $el = $(el); return false; } else if ( mode == "startsWith" && $(el).text().trim().startsWith(text) ) { $el = $(el); return false; } else if (mode == "endsWith" && $(el).text().trim().endsWith(text)) { $el = $(el); return false; } }); return $el; }, getElListByText(query, text, mode = "eq", visible = true) { let arr = []; $(query).each((i, el) => { if (visible && !$(query).is(":visible")) { return true; } if (mode == "eq" && $(el).text().trim() == text) { arr.push($(el)); } else if ( mode == "startsWith" && $(el).text().trim().startsWith(text) ) { arr.push($(el)); } else if (mode == "endsWith" && $(el).text().trim().endsWith(text)) { arr.push($(el)); } }); return arr; }, setHook() { try { ah.proxy( { onRequest: (config, handler) => { handler.next(config); }, onError: (err, handler) => { console.log(err.type); handler.next(err); }, onResponse: (response, handler) => { try { let url = response.config.url; if (url.includes("/stdCustLearnRecord/learnSave/v1.lyai")) { let body = JSON.parse(response.response); FREEJS.updatePanelText("当前进度:" + body.data.completionRate + "%") if (body.data.completionRate >= 100) { FREEJS.updatePanelText("视频播放完成!请手动返回列表页面选择下一课程") } response.response = JSON.stringify(body) } } finally { handler.next(response); } }, }, unsafeWindow.window ); } catch (e) { console.error(e) } }, }; // ========== 引流悬浮面板初始化 ========== FREEJS.initFloatPanel(); setTimeout(() => { if (typeof (zfk) == 'undefined') { FREEJS.init(); } else { console.log('skip init'); } }, 3000); if (!unsafeWindow.FREEJS) unsafeWindow.FREEJS = FREEJS; })();