Greasy Fork is available in English.
from ai build
// ==UserScript==
// @name 东营继续教育
// @namespace http://tampermonkey.net/
// @version 1.3
// @description from ai build
// @author xuefeng
// @match *://*.yxlearning.com/*
// @grant none
// @license
// ==/UserScript==
(function () {
'use strict';
// 确保页面完全加载后再执行脚本
window.onload = function () {
// 确保页面完全加载后再执行脚本,在这使用的是延时的办法
setTimeout(function () {
// 获取当前页所有章节的元素的ID
function getAllUnitID() {
// 声明一个存储当前课程的每章节id的数组
var allUnitID = [];
// 获取所有 class 为 "pt5" 的 ul 元素
var ulElements = document.querySelectorAll('ul.pt5');
// 遍历每个 ul 元素
ulElements.forEach(function (ul) {
// 获取 ul 元素下的所有 li 元素
var liElements = ul.querySelectorAll('li');
// 遍历每个 li 元素并获取其 id
liElements.forEach(function (li) {
allUnitID.push(li.id);
});
});
console.log("已经获取所有的章节ID", allUnitID);
return allUnitID;
}
// 找到当前章节的管视频播放的那个video标签,也即当前页面真实的视频标签
// nowUnitVideoElement 当前章节真实的视频元素标签
function nowUnitTrueVideo() {
var nowUnitTrueVideoElement = document.querySelectorAll("video");
for (var i = 0; i < nowUnitTrueVideoElement.length; i++) {
if (nowUnitTrueVideoElement[i].duration) { // 判断当前页面是否有视频标签 duration是看所拿到的视频标签是否有播放时长的属性,如果有那就是真实的视频元素
return nowUnitTrueVideoElement[i];//拿到真实的视频元素就返回给调用该函数的变量
}
}
}
// 点击这个视频所在的章节(即点击nowUnitID,即点击这个对应标题进入视频播放页),并确保完全进入该章节后改变promise状态
// inNowUnitID 进入当前的章节,以便于播放该小标题下的视频
// nowUnitID 当前小标题的ID(即当前章节的ID)
const inNowUnitID = (nowUnitID) => {
return new Promise((resolve) => { // promise 一旦建立就立即执行,但是状态的改变需要resolve()
document.querySelectorAll('li[id="' + nowUnitID + '"]')[0].click();
setTimeout(() => { resolve("等待时间到,应该已完全进入该章节") }, 40000) //往往是刚通过上句.click()点击该视频之后,改小标题下的视频还没有出来,如果此时接着点击播放视频,就会失败,所以添加了一个延时点击。
})
}
// 进入当前章节后找到真正的视频元素,并且保持持续播放,直到100%
// getNowUnitTrueVideoElement_AND_keepVideoPlay 获得当前小章节的真实视频元素 并 保证持续播放
// nowUnitID:当前小章节的ID
const getNowUnitTrueVideoElement_AND_keepVideoPlay = (nowUnitID) => { //传入nowUnitID,也就是传入当前的小章节ID,然后在本函数内嵌套有chekckVideoPlay函数,会用到
return new Promise((resolve) => {
const nowUnitTrueVideoElement = () => { //定义一个函数,用于获取当前小章节的视频元素
var nowUnitTrueVideoElement = document.querySelectorAll("video"); //获取当前页面的所有video标签
for (var i = 0; i < nowUnitTrueVideoElement.length; i++) { //遍历所有video标签
if (nowUnitTrueVideoElement[i].duration) { //判断当前video标签是否为真实视频(即有duration属性)
return nowUnitTrueVideoElement[i]; //返回真实视频
}
}
}
const checkVideo_IS_Done = setInterval(() => { // 检测视频是否播放完毕,只有播放完毕之后才允许该promise resolve()
console.log("当前章节视频完成了" + document.querySelector('[id="' + nowUnitID + '-badge"]').textContent);
if (document.querySelector('[id="' + nowUnitID + '-badge"]').textContent != '100%') { //当播放未达到100%
try {
if (nowUnitTrueVideoElement().paused) { // 如果视频暂停
nowUnitTrueVideoElement().muted = true; // 静音
nowUnitTrueVideoElement().play(); // 就点击播放
console.log("刚才检测到视频暂停,已自动点击本页视频播放");
} else {
// console.log("当前小节视频没有暂停,正在播放无需处理");
}
} catch (error) {
console.error("播放视频时发生错误:", error);
}
}else{ //当播放已经达到100%
clearInterval(checkVideo_IS_Done); //清除定时检查功能
resolve("本节播放完成")
}
}, 1000)
})
}
// 视频播放特殊处理,检测弹出的答题框
function autoClickSkipButton() {
// 选择需要观察变动的节点
var targetNode = document.body;
// 配置观察选项
var config = { childList: true, subtree: true };
const changecallback = function (mutations) {
mutations.forEach(function (mutation) {
if (document.querySelector('div.ccQuestion')) {
// 找到并点击 "跳过" 按钮
var skipButton = document.querySelector('input[value="跳过"]');
if (skipButton) {
skipButton.click();
// 重新启动观察者,以便处理后续的变化
observer.disconnect();
observer.observe(document.body, config);
}
}
});
};
// 创建一个观察者实例
var observer = new MutationObserver(changecallback);
// 开始观察
observer.observe(targetNode, config);
console.log("已开启自动跳过答题框");
}
//-------------------------事件顺序-------------------------------
// 获取本课程所有的章节ID(也即allUnitID)
const allUnitID = getAllUnitID();
// 开始播放课程所有章节
const start = async (allUnitID) => {
console.log("Type of allUnitID:", typeof allUnitID);
for (const nowUnitID of allUnitID) {
console.log("当前播放的是第" + (allUnitID.indexOf(nowUnitID) + 1) + "个小节");
const res1 = await inNowUnitID(nowUnitID) //进入当前章节
console.log(res1)
const res2 = await getNowUnitTrueVideoElement_AND_keepVideoPlay(nowUnitID) //获得当前小章节的视频元素并保持持续播放
console.log(res2)
}
}
// 开始
start(allUnitID);
// 调用观察者确保跳过答题框
autoClickSkipButton(); // 不需要传入参数
}, 20000); // 延迟10秒执行
};
})();