// ==UserScript== // @name 学起Plus、弘成教育挂课自动连续播放 // @namespace http://tampermonkey.net/ // @version 1.0 // @description 一个网课挂机自动连续播放工具,仅适用于学起Plus、弘成教育 sccchina.net chinaedu.net,反馈与交流QQ群:715307684,更新日期:2022年11月20日 // @author 哆哆啦啦梦 // @match *://*.chinaedu.net/* // @match *://*.sccchina.net/* // @match *://*.edu.cn/* // @match *://*.bnude.cn/* // @icon https://www.google.com/s2/favicons?sz=64&domain=chinaedu.net // @grant unsafeWindow // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @run-at document-end // @license GPLv3 // @downloadURL none // ==/UserScript== const lessionRules = { "play.html": { selector: ['.page-sidebar li>a>span[class="title"]'], }, "study.do": { beforeFun: () => { const catalogDiv = document.getElementById("catalogDiv"); if (catalogDiv.childElementCount === 0) { const catalog = document.getElementById("catalogA"); catalog && catalog.className.indexOf("Cur") === -1 && catalog.click(); } }, selector: ["#catalogDiv span[onclick]", "#catalogDiv span[class='tit']"], }, "mp4_video_index.html": { selector: [".ui-folder .ui-leaf span"], }, }; const currentRules = { "videolearning.html": { selector: [".page-sidebar li.active>a>span"], }, "play.html": { selector: [".page-breadcrumb li>a", ".page-sidebar li.active>a>span"], }, "mp4_video_index.html": { selector: [".ui-folder .ui-leaf.ui-selected span"], }, "study.do": { selector: [ "#catalogDiv .cur span", '.study-video-title span[class$="title"]', ], }, }; const videoRules = { "video.html": { selector: ["#videoFrame video"], }, "play.html": { selector: ["#draggable video"], }, "mp4_video_index.html": { selector: [".plyr__video-wrapper video"], }, "study.do": { selector: ["videobox video"], }, }; const noNeedAutoPlayRules = ["mp4_video_index"]; function isInNoNeedAutoPlay() { return noNeedAutoPlayRules.find((e) => document.URL.indexOf(e) > 0); } function urlIn(rules) { for (let key in rules) { if (document.URL.indexOf(key) > 0) { return true; } } return false; } function getDataForRules(rules) { for (let key in rules) { if (document.URL.indexOf(key) > 0) { for (let i = 0; i < rules[key].selector.length; i++) { rules[key].beforeFun && rules[key].beforeFun(rules[key].selector[i]); const res = document.querySelectorAll(rules[key].selector[i]); rules[key].afterFun && rules[key].afterFun(rules[key].selector[i], res); if (res.length > 0) { return res; } } } } return null; } function getCurrentLession() { const arr = getDataForRules(currentRules); if (arr) { GM_setValue("current", arr[arr.length - 1].innerText); } } function getLessionsInfo() { const arr = getDataForRules(lessionRules); if (arr) { const lessions = []; for (let i = 0; i < arr.length; i++) { const className = "api20221120-" + i; if (arr[i].className.indexOf(className) === -1) { arr[i].className += " " + className; } lessions.push({ title: arr[i].innerText, className }); } GM_setValue("lessions", lessions); } } let findVideoCount = 0; const findVideoMaxCount = 3; function getVideo() { const status = GM_getValue("play_end"); if (GM_getValue("video") || status) { return; } if (findVideoCount >= findVideoMaxCount) { if (status !== "not found") { GM_setValue("play_end", "not found"); findVideoCount = 0; } return; } if (document.querySelector("video")) { GM_setValue("video", document.URL); setTimeout(() => { playCheck(); }, 5000); } else { findVideoCount++; } } function playCheck() { if (GM_getValue("play_end")) { return; } const video = document.querySelector("video"); if (video) { video.muted = true; video.playbackRate = 1; const currentTime = video.currentTime.toFixed(1); const totalTime = video.duration.toFixed(1); console.log(`当前进度:${currentTime}/${totalTime}`); if (video.ended) { setTimeout(() => { GM_setValue("play_end", "over"); }, 5000); } else { if (video.paused) { console.log("视频被暂停,继续播放!"); video.play(); } setTimeout(() => { playCheck(); }, 5000); } } else { console.log("异常:找不到视频元素了"); } } function nextCheck() { const status = GM_getValue("play_end"); const lessions = GM_getValue("lessions"); if (status && lessions && lessions.length) { let currentText = GM_getValue("current"); const lastCurrent = GM_getValue("last_current"); let step = GM_getValue("step"); if (!lastCurrent || (currentText && lastCurrent !== currentText)) { GM_setValue("last_current", currentText); step = 1; } else { currentText = lastCurrent; step += 1; } GM_setValue("step", step); let index = GM_getValue("last_pos") ?? 0; if (status === "not found" && !currentText) { step = 0; } else if (isInNoNeedAutoPlay()) { return; } const newIndex = lessions.findIndex((e) => e.title === currentText); if (newIndex !== -1) { index = newIndex; } GM_setValue("last_pos", index); if (index + step < lessions.length) { document.querySelector("." + lessions[index + step].className).click(); GM_deleteValue("play_end"); GM_deleteValue("video"); } else { alert("课程播放结束"); return; } } setTimeout(() => { nextCheck(); }, 5000); } function getResource() { getCurrentLession(); getLessionsInfo(); } function init() { GM_deleteValue("play_end"); GM_deleteValue("video"); GM_deleteValue("current"); GM_deleteValue("last_current"); GM_deleteValue("lessions"); GM_setValue("step", 1); GM_setValue("last_pos", 0); } function popupClose() { const tips = document.querySelector(".win-content"); if (tips && tips.innerText.indexOf("继续学习") > 0) { const btn = document.querySelector(".win-content .close-win-bt"); btn && btn.click(); } const pop = document.querySelector("#pop"); pop && pop.querySelector(".pop_close").click(); } function work() { init(); setTimeout(() => { urlIn(lessionRules) && nextCheck(); }, 5000); setInterval(() => { urlIn(videoRules) && getVideo(); }, 10000); setInterval(() => { getResource(); popupClose(); }, 3000); } (function () { "use strict"; work(); })();