// ==UserScript==
// @name [ECUST] 华东理工 旧版学习通 全自动刷课
// @namespace ddin
// @version 1.0.5
// @author gpt-4-turbo
// @description 华东理工旧版超星学习通专刷(高数线代大物) mooc.s.ecust.edu.cn
// @license Unlicense
// @icon https://s.ecust.edu.cn/favicon.ico
// @match *://mooc.s.ecust.edu.cn/*
// @match *://mooc1.chaoxing.com/*
// @grant none
// ==/UserScript==
(() => {
let timer1;
let timer2;
let initialJobCount = null;
let clickInterval;
// 初始化本地存储项
if (localStorage.getItem("scriptRunCounter") === null) {
localStorage.setItem("scriptRunCounter", 0);
}
if (localStorage.getItem("chapterToCheck") === null) {
localStorage.setItem("chapterToCheck", "不自动停止");
}
if (localStorage.getItem("autoReturnDelay") === null) {
localStorage.setItem("autoReturnDelay", 60000);
}
if (localStorage.getItem("autoManageMode") === null) {
localStorage.setItem("autoManageMode", "0");
}
if (localStorage.getItem("courseSelectionMode") === null) {
localStorage.setItem("courseSelectionMode", "0");
}
function checkStop() {
let currents = document.querySelectorAll(".currents");
let chapterToCheck = localStorage.getItem("chapterToCheck");
for (let i = 0; i < currents.length; i++) {
let hideChapterNumber = currents[i].querySelector(".hideChapterNumber");
if (hideChapterNumber && hideChapterNumber.textContent.trim() === chapterToCheck) {
console.log(`Chapter number ${chapterToCheck} found, exiting.`);
clearInterval(timer1);
clearInterval(timer2);
setChapterToCheck("不自动停止"); // 假设这是正确设置下一章节的方式
localStorage.setItem("autoManageMode", "0");
window.location.href = "about:blank";
return; // 防止继续执行后续代码
}
}
}
// 检查课程的函数
function checkLessons() {
let videoPlayed = false; // 标志,表示是否已经播放过视频
let isScriptPause = false; // 标志,表示是否由脚本触发的暂停
// 等待 iframe 元素加载完成后查找并自动播放
function waitForIframeAndPlay() {
checkStop();
if (videoPlayed) {
console.log("已播放视频,停止脚本。");
return; // 如果已经播放过视频,停止执行
}
// 查找页面中的第一个 iframe
const outerIframe = document.querySelector("iframe");
if (outerIframe) {
console.log("找到外层 iframe,正在加载...");
try {
// 获取外层 iframe 的内容窗口和文档
const outerIframeDocument = outerIframe.contentWindow.document;
// 替换所有class为ans-attach-ct ans-job-finished的div为占位元素
const divsToReplace = outerIframeDocument.querySelectorAll("div.ans-attach-ct.ans-job-finished");
if (divsToReplace.length > 0) {
divsToReplace.forEach((div) => {
// 创建占位元素
const placeholder = outerIframeDocument.createElement("div");
// 设置占位元素的样式
placeholder.style.width = "100%";
placeholder.style.height = "200px"; // 根据需要调整高度
placeholder.style.backgroundColor = "#f0fff0";
placeholder.style.display = "flex";
placeholder.style.alignItems = "center";
placeholder.style.justifyContent = "center";
placeholder.style.border = "2px solid #ccc";
placeholder.style.boxSizing = "border-box";
placeholder.style.fontSize = "24px";
placeholder.style.color = "#555";
placeholder.style.borderRadius = "20px"; // 添加圆角
// 设置占位文本
placeholder.textContent = "已播放完毕";
// 替换原有的div
div.parentNode.replaceChild(placeholder, div);
console.log("已替换一个ans-attach-ct ans-job-finished的div元素为占位元素");
});
} else {
console.log('未找到具有class "ans-attach-ct ans-job-finished" 的div元素');
}
// 查找外层 iframe 中的第一个内层 iframe
const innerIframe = outerIframeDocument.querySelector("iframe");
if (innerIframe) {
console.log("找到内层 iframe,正在加载...");
try {
// 获取内层 iframe 的内容窗口和文档
const innerIframeDocument = innerIframe.contentWindow.document;
// 查找内层 iframe 中的第一个视频元素
const video = innerIframeDocument.querySelector("video");
if (video) {
video.muted = true; // 静音视频
video
.play()
.then(() => {
console.log("视频已开始播放");
videoPlayed = true; // 设置标志,表示已播放
// 添加事件监听器以监测视频状态变化
const onVideoStateChange = ({ type }) => {
if (isScriptPause) {
// 忽略脚本自身触发的暂停
return;
}
console.log(`检测到视频事件: ${type}`);
// 在事件发生后延迟1秒
setTimeout(() => {
goback();
}, 1000);
// 移除事件监听器,防止多次弹窗
video.removeEventListener("pause", onVideoStateChange);
video.removeEventListener("ended", onVideoStateChange);
};
video.addEventListener("pause", onVideoStateChange);
video.addEventListener("ended", onVideoStateChange);
// 在播放后1秒暂停视频
setTimeout(() => {
isScriptPause = true; // 标记即将由脚本暂停
video.pause();
console.log("视频已暂停");
// 再过1秒继续播放视频
setTimeout(() => {
video
.play()
.then(() => {
console.log("视频已继续播放");
isScriptPause = false; // 解除标记
})
.catch((err) => {
console.log("继续播放视频时出错:", err);
isScriptPause = false; // 解除标记
});
}, 1000);
}, 1000);
})
.catch((error) => {
console.log("播放视频时出错:", error);
});
} else {
console.log("未找到视频元素");
// 替换包含内层 iframe 的 ans-attach-ct div 为“非视频内容”
const parentDiv = innerIframe.closest("div.ans-attach-ct");
if (parentDiv) {
const placeholder = outerIframeDocument.createElement("div"); // 使用外层 iframe 的文档
// 设置占位元素的样式(与“已播放完毕”一致)
placeholder.style.width = "100%";
placeholder.style.height = "200px"; // 根据需要调整高度
placeholder.style.backgroundColor = "#fff0f0";
placeholder.style.display = "flex";
placeholder.style.alignItems = "center";
placeholder.style.justifyContent = "center";
placeholder.style.border = "2px solid #ccc";
placeholder.style.boxSizing = "border-box";
placeholder.style.fontSize = "24px";
placeholder.style.color = "#555";
placeholder.style.borderRadius = "20px"; // 添加圆角
// 设置占位文本
placeholder.textContent = "非视频内容";
// 替换原有的div
parentDiv.parentNode.replaceChild(placeholder, parentDiv);
console.log("已替换包含内层 iframe 的ans-attach-ct div元素为“非视频内容”的占位元素");
// 重新运行整个查找
setTimeout(waitForIframeAndPlay, 1000); // 延迟1秒后重试
} else {
console.log("无法找到包含内层 iframe 的ans-attach-ct div元素");
}
}
} catch (error) {
console.log("无法访问内层 iframe 内容,可能是跨域限制:", error);
}
} else {
console.log("未找到内层 iframe");
}
} catch (error) {
console.log("无法访问外层 iframe 内容,可能是跨域限制:", error);
}
} else {
console.log("未找到外层 iframe,延迟重试...");
setTimeout(waitForIframeAndPlay, 1000); // 每隔1秒重试
}
}
// 页面加载完成后延迟3秒开始查找并播放
setTimeout(waitForIframeAndPlay, 2000);
}
// 判断是否已登录
function isLoggedIn() {
// 查找页面上是否有特定的“退出登录”链接
const logoutLink = document.querySelector('a[href="#"][onclick="logout()"]');
return logoutLink !== null;
}
// 点击目标元素的函数
function clickTargetElement() {
// 如果未登录,则显示提示并停止自动点击
if (!isLoggedIn()) {
alert("未登录,请先登录!");
clearInterval(clickInterval); // 停止setInterval循环
return;
}
// 寻找ID为"clazzApplyBtn"的a标签
const clazzApplyBtn = document.getElementById("clazzApplyBtn");
if (clazzApplyBtn && clazzApplyBtn.tagName.toUpperCase() === "A") {
clazzApplyBtn.click();
console.log("已点击: clazzApplyBtn");
}
// 寻找ID为"iboxAlertOk-confirm"的a标签
const iboxAlertOkConfirm = document.getElementById("iboxAlertOk-confirm");
if (iboxAlertOkConfirm && iboxAlertOkConfirm.tagName.toUpperCase() === "A") {
iboxAlertOkConfirm.click();
console.log("已点击: iboxAlertOk-confirm");
}
}
// 设置需要检查的章节号
function setChapterToCheck(value) {
localStorage.setItem("chapterToCheck", value);
console.log(`Chapter to check has been set to: ${value}`);
}
// 点击目标的h3元素
function clickTargetH3() {
const spans = document.querySelectorAll("span.articlename");
spans.forEach((span) => {
// 查找该span元素下的所有a元素
const links = span.querySelectorAll("a");
links.forEach((link) => {
const originalHref = link.href; // 获取原始href
if (!originalHref.includes("&mooc2=1")) {
// 检查是否已包含&mooc2=1
link.href = `${originalHref}&mooc2=1`; // 添加参数
}
});
});
let h3Elements = document.querySelectorAll("h3");
let targetElement = null;
for (let i = 0; i < h3Elements.length; i++) {
if (h3Elements[i].querySelector("em.orange")) {
targetElement = h3Elements[i];
break;
}
}
if (targetElement) {
let anchor = targetElement.querySelector("a");
if (anchor) anchor.click();
} else {
// 如果找不到 em.orange,检查是否存在 em.openlock
let openLockElements = document.querySelectorAll("em.openlock");
if (openLockElements.length > 0) {
// 找到 class 为 "content1 roundcorner" 的 div 元素
let contentDiv = document.querySelector("div.content1.roundcorner");
if (contentDiv) {
// 创建占位符元素
let placeholder = document.createElement("div");
// 设置占位符样式(根据需要调整样式)
placeholder.style.width = "100%";
placeholder.style.height = "200px"; // 根据需要调整大小
placeholder.style.display = "flex";
placeholder.style.justifyContent = "center";
placeholder.style.alignItems = "center";
placeholder.style.backgroundColor = "#f0f0f0";
placeholder.style.border = "2px solid #ccc";
placeholder.style.borderRadius = "8px";
placeholder.style.fontSize = "24px";
placeholder.style.color = "#555";
placeholder.textContent = "已全部播放完毕";
// 替换原有的 div 元素
contentDiv.parentNode.replaceChild(placeholder, contentDiv);
}
}
}
}
// 修改标签的函数
function modifyTags() {
// 选择所有h4和h5元素
const tags = document.querySelectorAll("h4, h5");
tags.forEach((tag) => {
// 查找第一个span和a元素
const firstSpan = tag.querySelector("span");
const firstA = tag.querySelector("a");
if (firstSpan && firstA) {
// 获取span的onclick属性
const onclickAttr = firstSpan.getAttribute("onclick");
if (onclickAttr) {
// 将onclick属性设置到a标签并移除href属性
firstA.setAttribute("onclick", onclickAttr);
firstA.removeAttribute("href");
}
}
});
}
const consoleScript = `window.addEventListener("mouseout",t=>{t.stopImmediatePropagation(),t.stopPropagation(),t.preventDefault()},!0);`;
// 运行控制台脚本
const runConsoleScript = () => {
const script = document.createElement("script");
script.textContent = consoleScript;
document.head.appendChild(script);
script.remove();
};
runConsoleScript();
if (window === window.top) {
setInterval(modifyTags, 1000);
let counter = parseInt(localStorage.getItem("scriptRunCounter"), 10) || 0;
counter++;
localStorage.setItem("scriptRunCounter", counter);
let titleElement = document.querySelector("h1");
if (titleElement) {
titleElement.innerText = `程序运行中 <${counter}> - ${titleElement.innerText}`;
}
// 创建一个容器div
let containerDiv = document.createElement("div");
containerDiv.style.padding = "10px";
containerDiv.style.backgroundColor = "#f0f0f0";
containerDiv.style.textAlign = "center";
// 创建章节检查输入框
let inputFieldChapter = document.createElement("input");
inputFieldChapter.setAttribute("type", "text");
inputFieldChapter.setAttribute("placeholder", "输入自动停止的章节号 如1.3");
inputFieldChapter.id = "chapterInput";
let storedChapter = localStorage.getItem("chapterToCheck");
if (storedChapter) {
inputFieldChapter.value = storedChapter;
}
// 创建确认按钮
let confirmButtonChapter = document.createElement("button");
confirmButtonChapter.textContent = "设置终止";
confirmButtonChapter.onclick = () => {
let inputValue = document.getElementById("chapterInput").value;
if (inputValue.trim() !== "") {
setChapterToCheck(inputValue);
console.log(`Chapter to check has been updated to: ${inputValue}`);
} else {
alert("输入错误");
}
};
// 创建自动托管模式开关
let autoManageSwitch = document.createElement("input");
autoManageSwitch.setAttribute("type", "checkbox");
autoManageSwitch.id = "autoManageSwitch";
let storedAutoManageMode = localStorage.getItem("autoManageMode");
autoManageSwitch.checked = storedAutoManageMode === "1"; // 如果存储值为1,则选中
// 创建自动托管模式标签
let autoManageLabel = document.createElement("label");
autoManageLabel.setAttribute("for", "autoManageSwitch");
autoManageLabel.textContent = "自动切集";
// 为开关添加事件监听器
autoManageSwitch.onchange = () => {
localStorage.setItem("autoManageMode", autoManageSwitch.checked ? "1" : "0");
//alert(`全自动托管模式已${autoManageSwitch.checked ? "启用" : "禁用"}`);
window.location.reload();
};
// 创建重置按钮
let resetButton = document.createElement("button");
resetButton.textContent = "重置程序";
resetButton.onclick = () => {
localStorage.removeItem("scriptRunCounter");
localStorage.removeItem("chapterToCheck");
localStorage.removeItem("autoReturnDelay");
localStorage.removeItem("autoManageMode");
//alert("所有设置已重置");
window.location.reload(); // 重载页面以反映重置后的状态
};
// 创建选课模式开关
let courseSelectionSwitch = document.createElement("input");
courseSelectionSwitch.setAttribute("type", "checkbox");
courseSelectionSwitch.id = "courseSelectionSwitch";
let storedCourseSelectionMode = localStorage.getItem("courseSelectionMode");
courseSelectionSwitch.checked = storedCourseSelectionMode === "1"; // 如果存储值为1,则选中
// 创建选课模式标签
let courseSelectionLabel = document.createElement("label");
courseSelectionLabel.setAttribute("for", "courseSelectionSwitch");
courseSelectionLabel.textContent = "选课模式";
// 为开关添加事件监听器
courseSelectionSwitch.onchange = () => {
localStorage.setItem("courseSelectionMode", courseSelectionSwitch.checked ? "1" : "0");
//alert(`选课模式已${courseSelectionSwitch.checked ? "启用" : "禁用"}`);
window.location.reload();
};
containerDiv.style.padding = "20px";
containerDiv.style.marginBottom = "20px";
containerDiv.style.backgroundColor = "#ffffff";
containerDiv.style.boxShadow = "0 4px 8px rgba(0,0,0,0.1)";
containerDiv.style.borderRadius = "8px";
containerDiv.style.textAlign = "center";
const baseInputStyle = "margin: 5px; padding: 10px; width: 80%; max-width: 300px; border-radius: 4px; border: 1px solid #ccc;";
const baseButtonStyle = "cursor: pointer; margin: 5px; padding: 10px 15px; border: none; border-radius: 4px; background-color: #007bff; color: white;";
inputFieldChapter.style = baseInputStyle;
confirmButtonChapter.style = baseButtonStyle;
confirmButtonChapter.onmouseover = () => (confirmButtonChapter.style.backgroundColor = "#0056b3"); // Hover效果
confirmButtonChapter.onmouseleave = () => (confirmButtonChapter.style.backgroundColor = "#007bff"); // 鼠标离开时恢复颜色
// 自动托管模式开关样式调整
autoManageSwitch.style = "margin: 10px; cursor: pointer;";
// 自动托管模式标签样式调整
autoManageLabel.style = "color: #333; font-size: 14px;";
// 选课模式开关样式调整
courseSelectionSwitch.style = "margin: 10px; cursor: pointer;";
// 选课模式标签样式调整
courseSelectionLabel.style = "color: #333; font-size: 14px;";
// 重置按钮样式调整
resetButton.style = "cursor: pointer; margin-top: 20px; padding: 10px 15px; border: none; border-radius: 4px; background-color: #dc3545; color: white;";
resetButton.onmouseover = () => (resetButton.style.backgroundColor = "#c82333"); // Hover效果
resetButton.onmouseleave = () => (resetButton.style.backgroundColor = "#dc3545"); // 鼠标离开时恢复颜色
// 将新创建的元素添加到容器div中
if (window.location.href.indexOf("https://mooc.s.ecust.edu.cn/course/") === 0) {
containerDiv.appendChild(document.createElement("br"));
containerDiv.appendChild(courseSelectionSwitch);
containerDiv.appendChild(courseSelectionLabel);
} else {
// 将元素添加到容器div中
containerDiv.appendChild(inputFieldChapter);
containerDiv.appendChild(confirmButtonChapter);
containerDiv.appendChild(document.createElement("br")); // 添加换行,美观分隔
// 将新创建的元素添加到容器div中
containerDiv.appendChild(document.createElement("br"));
containerDiv.appendChild(autoManageSwitch);
containerDiv.appendChild(autoManageLabel);
containerDiv.appendChild(document.createElement("br"));
containerDiv.appendChild(resetButton);
// 将容器div添加到body的最开始的位置
}
document.body.insertBefore(containerDiv, document.body.firstChild);
}
checkLessons();
if (localStorage.getItem("autoManageMode") === "1") {
timer2 = setInterval(clickTargetH3, 2000);
} else if (localStorage.getItem("courseSelectionMode") === "1") {
clickInterval = setInterval(clickTargetElement, 100);
}
})();