// ==UserScript==
// @name 东航易学助手
// @namespace http://tampermonkey.net/
// @version 2.2.1
// @description 检测超时弹窗,稳定多开加速,并处理所有弹出按钮
// @author 买不起泡面的Hanley
// @match *://dhyx.ceair.com/*
// @require http://code.jquery.com/jquery-1.9.1.min.js
// @grant unsafeWindow
// @grant GM_addStyle
// @grant GM_getResourceText
// @license MIT
// ==/UserScript==
var Status = 0; // 初始化状态标识
var lastClickTime = Date.now(); // 最后一次点击的时间
var refreshInterval; // 用于存储定时器ID
var isDragging = false; // 用于标识是否正在拖动
var dragStartX, dragStartY; // 记录拖动开始时的鼠标位置
function getAutoNavigateEnabled() {
return localStorage.getItem('autoNavigateEnabled') === 'true';
}
function setAutoNavigateEnabled(value) {
localStorage.setItem('autoNavigateEnabled', value);
manageAutoRefresh();
}
function manageAutoRefresh() {
clearInterval(refreshInterval); // 清除之前的定时器
if (Status == 0 && !getAutoNavigateEnabled()) {
refreshInterval = setInterval(function() {
window.top.location.reload(true);
}, 300000); // 5分钟刷新一次
}
}
function updateToggleButton(toggleButton) {
const autoNavigateEnabled = getAutoNavigateEnabled();
toggleButton.innerText = autoNavigateEnabled ? "自动导航:开" : "自动导航:关";
toggleButton.style.background = autoNavigateEnabled ? 'rgba(255, 255, 0, 0.5)' : 'rgba(128, 128, 128, 0.5)';
}
function detectAndClickAlertButton() {
// 查找弹窗的wrapper
const alertWrapper = document.querySelector('.alert-shadow.new-alert-shadow');
if (!alertWrapper) {
return;
}
// 查找确定按钮
const alertButton = document.getElementById('D253btn-ok');
if (alertButton) {
alertButton.click(); // 自动点击确定按钮
}
}
function detectString() {
function checkString(node) {
if (node.nodeType === Node.TEXT_NODE) {
if (node.nodeValue.includes('可继续学习')) {
var confirmBtns3 = document.getElementsByClassName("btn");
if (confirmBtns3 != null && confirmBtns3.length > 0) {
confirmBtns3[0].click();
lastClickTime = Date.now();
}
} else if (node.nodeValue.includes('恭喜')) {
var cancelBtns = document.querySelectorAll('button[data-bb-handler="cancel"]');
if (cancelBtns.length > 0) {
cancelBtns[0].click();
}
if (getAutoNavigateEnabled()) {
setTimeout(function() {
window.top.location.reload(true);
}, 5000);
}
} else if (node.nodeValue.includes('进度已保存')) {
if (getAutoNavigateEnabled()) {
// 5秒后刷新页面
setTimeout(function() {
window.top.location.reload(true);
}, 5000);
}
} else if (node.nodeValue.includes('小测试')) {
// 执行一次遍历
}
} else if (node.nodeType === Node.ELEMENT_NODE) {
// 检查元素节点中的文本内容
if (node.textContent.includes('进度已保存')) {
if (getAutoNavigateEnabled()) {
// 5秒后刷新页面
setTimeout(function() {
window.top.location.reload(true);
}, 5000);
}
}
// 遍历子节点
for (let child of node.childNodes) {
checkString(child);
}
}
}
const observer = new MutationObserver(function(mutations) {
for (let mutation of mutations) {
for (let addedNode of mutation.addedNodes) {
checkString(addedNode);
}
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
}
function updateFlagStatus() {
const flag1 = document.getElementById('flag');
if (Status == 1) {
flag1.innerText = "检测到考试!代码停止运行!\nby:买不起泡面的Hanley";
} else if (Status == 2) {
flag1.innerText = "运行阅卷脚本\nby:买不起泡面的Hanley";
} else {
flag1.innerText = "脚本正在运行\nby:买不起泡面的Hanley";
}
}
function makeElementDraggable(element) {
let offsetX, offsetY;
element.addEventListener('mousedown', function(event) {
isDragging = false;
dragStartX = event.clientX;
dragStartY = event.clientY;
offsetX = event.clientX - element.getBoundingClientRect().left;
offsetY = event.clientY - element.getBoundingClientRect().top;
element.style.cursor = 'move';
function onMouseMove(event) {
const deltaX = event.clientX - dragStartX;
const deltaY = event.clientY - dragStartY;
if (!isDragging && (Math.abs(deltaX) > 5 || Math.abs(deltaY) > 5)) {
isDragging = true;
}
if (isDragging) {
element.style.left = event.clientX - offsetX + 'px';
element.style.top = event.clientY - offsetY + 'px';
event.preventDefault(); // 防止选择文本
}
}
function onMouseUp() {
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', onMouseUp);
element.style.cursor = 'pointer';
}
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
});
}
if (window.self === window.top) { // 仅在顶层窗口显示悬浮窗
setTimeout(function() {
const flag = document.createElement("div");
flag.id = 'flag';
flag.style.cssText = 'left: 10px;bottom: 10px;background: rgba(26, 89, 183, 0.5);color:#ffffff;overflow: hidden;z-index: 9999;position: fixed;padding:3px;text-align:center;width: 175px;height: 45px;line-height: 20px;border-radius: 4px;cursor: pointer;';
document.getElementById("content").appendChild(flag);
updateFlagStatus();
makeElementDraggable(flag);
flag.addEventListener('click', function() {
if (!isDragging && flag.innerText.includes("脚本正在运行")) {
flag.style.background = 'rgba(255, 0, 0, 0.5)';
flag.innerText = "正在尝试爆破\nby:买不起泡面的Hanley";
markVideoAsCompleted();
setTimeout(function() {
flag.style.background = 'rgba(26, 89, 183, 0.5)';
updateFlagStatus();
}, 2000);
loadKnockoutJs(proceedWithModifications);
}
});
const toggleButton = document.createElement("div");
toggleButton.id = 'toggleButton';
toggleButton.style.cssText = 'right: 10px;bottom: 10px;color:#000000;overflow: hidden;z-index: 9999;position: fixed;padding:3px;text-align:center;width: 100px;height: 30px;line-height: 25px;border-radius: 4px;cursor: pointer;';
document.body.appendChild(toggleButton);
updateToggleButton(toggleButton); // 确保页面加载时立即更新按钮背景颜色
makeElementDraggable(toggleButton);
toggleButton.addEventListener('click', function() {
if (!isDragging) {
const newState = !getAutoNavigateEnabled();
setAutoNavigateEnabled(newState);
updateToggleButton(toggleButton);
setTimeout(function() {
window.top.location.reload(true);
}, 1000);//一秒刷新
}
});
// 初始化时检查并设置自动刷新
manageAutoRefresh();
}, 4000); // 4秒后显示状态牌
}
var AutoClick = setInterval(function() { Clicker() }, 1000); // 每秒运行一次
function Clicker() {
console.error = function() {};
if (window.location.href.indexOf("exam") > -1) {
if (window.location.href.indexOf("mark-paper") > -1) { // 检测到是在阅卷,停止运行但不跳弹窗
clearInterval(AutoClick); // 阅卷了就不乱点了
clearInterval(refreshInterval);
Status = 2; // 阅卷了阅卷了
} else {
clearInterval(AutoClick); // 别是在考试,考试就直接摆烂
clearInterval(refreshInterval);
Status = 1; // 考试了还玩球,状态标异常
alert('检测到考试!代码停止运行!');
}
}
detectString(); // 叫外援
checkLoginStatus();
handleClicks();
detectAndClickAlertButton();
if (getAutoNavigateEnabled()) {
clickNextButtonInIframe();
autoNavigateNextChapter();
}
if (getAutoNavigateEnabled()) {
const nextPage = document.querySelector(".navBtn.glyphicon.glyphicon-chevron-right");
if (nextPage && !nextPage.disabled) {
nextPage.click();
lastClickTime = Date.now();
}
}
}
function handleClicks() {
if (!getAutoNavigateEnabled()) return;
const confirmBtns = document.querySelectorAll(".bootbox-close-button.close");
if (confirmBtns.length > 0) {
confirmBtns[0].click(); // 自动点击
lastClickTime = Date.now();
}
const confirmBtns2 = document.querySelectorAll(".alertify-button.alertify-button-ok");
if (confirmBtns2.length > 0) {
confirmBtns2[0].click();
lastClickTime = Date.now();
}
}
// 自动导航到下一个章节
function autoNavigateNextChapter() {
if (!getAutoNavigateEnabled()) return;
const currentChapter = findCurrentChapter();
if (currentChapter && isChapterCompleted(currentChapter)) {
clickNextChapter(currentChapter);
}
}
// 查找当前正在学习的章节
function findCurrentChapter() {
return $(".chapter-list-box.focus");
}
// 判断章节是否完成
function isChapterCompleted(chapter) {
return !chapter.find('.item.pointer.item22').length;
}
function clickNextChapter(currentChapter) {
if (!getAutoNavigateEnabled()) {
return;
}
// 从当前章节开始,查找下一个未完成的章节
let chapters = Array.from(document.querySelectorAll('.chapter-list-box'));
let currentChapterIndex = chapters.indexOf(currentChapter[0]); // 获取当前章节的索引
for (let i = currentChapterIndex + 1; i < chapters.length; i++) {
let nextChapterToStudy = chapters[i];
if (nextChapterToStudy.querySelector('.item.pointer.item22')) {
let clickableElement = nextChapterToStudy.querySelector('.chapter-item');
if (clickableElement) {
clickableElement.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true }));
lastClickTime = Date.now();
break;
}
}
}
}
// 在 iframe 内部执行点击操作
function clickNextButtonInIframe() {
if (!getAutoNavigateEnabled()) return;
const iframe = document.getElementById('scormIframe');
if (iframe) {
const iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
const nextPageButton = iframeDocument.querySelector('.navBtn.glyphicon.glyphicon-chevron-right.nextCompleted');
if (nextPageButton) {
nextPageButton.click();
lastClickTime = Date.now();
}
const popupBtns = iframeDocument.querySelectorAll('.btn[data-bb-handler="ok"], .btn[data-bb-handler="next"], .btn[data-bb-handler="confirm"]');
popupBtns.forEach(function(btn) {
simulateClick(btn, iframe.contentWindow);
if (getAutoNavigateEnabled()) {
btn.click();
lastClickTime = Date.now();
}
});
const navigationLabel = iframeDocument.querySelector('.navigation-controls__label');
if (navigationLabel && getAutoNavigateEnabled()) {
const pageNumbers = navigationLabel.innerText.split('/');
if (pageNumbers.length === 2 && pageNumbers[0].trim() === pageNumbers[1].trim()) {
if (getAutoNavigateEnabled()) {
setTimeout(function() {
window.top.location.reload(true);
}, 10000); // 等待 10 秒后强制导航到下一个章节
}
}
}
const buttons = iframeDocument.querySelectorAll('.uikit-primary-button.uikit-primary-button_size_medium.play-controls-container__play-pause-button');
buttons.forEach(function(button) {
const svg = button.querySelector('svg');
if (svg) {
const path = svg.querySelector('path');
if (path && getAutoNavigateEnabled() && path.getAttribute('d') === 'M5 16.3087V3.54659L5 3.54659L16.8484 8.87836C17.2245 9.04759 17.2455 9.57369 16.8842 9.77243L5 16.3087Z') {
simulateClick(button, iframe.contentWindow);
}
}
});
const popupBtns2 = iframeDocument.querySelectorAll('.message-box-buttons__window-button');
popupBtns2.forEach(function(btn) {
simulateClick(btn, iframe.contentWindow);
});
}
}
function simulateClick(element, win) {
if (!getAutoNavigateEnabled()) return;
const mouseDownEvent = new MouseEvent('mousedown', {
bubbles: true,
cancelable: true,
view: win
});
const mouseUpEvent = new MouseEvent('mouseup', {
bubbles: true,
cancelable: true,
view: win
});
const clickEvent = new MouseEvent('click', {
bubbles: true,
cancelable: true,
view: win
});
element.dispatchEvent(mouseDownEvent);
element.dispatchEvent(mouseUpEvent);
element.dispatchEvent(clickEvent);
}
function loadKnockoutJs(callback) {
var resources = performance.getEntriesByType('resource');
var regex = /file-cloud\/01\/[0-9A-Za-z]+\/[0-9A-Za-z]+\/[0-9A-Za-z]+/;
var knockoutJsUrl = '';
for (var i = 0; i < resources.length; i++) {
var resource = resources[i];
if (resource.name.includes('scorm_api.jsp?')) {
var match = resource.name.match(regex);
if (match) {
var dynamicPath = match[0];
if (dynamicPath.includes('/player')) {
dynamicPath = dynamicPath.replace('/player', '');
}
knockoutJsUrl = 'https://dhyx.ceair.com/' + dynamicPath + '/lib/knockout/knockout.min.js';
break;
}
}
}
if (knockoutJsUrl) {
var script = document.createElement('script');
script.src = knockoutJsUrl;
document.head.appendChild(script);
script.onload = function() {
callback();
};
} else {
callback();
}
}
function proceedWithModifications() {
function findViewModel(root) {
var queue = [{ obj: root, path: '' }];
var visited = new Set();
while (queue.length > 0) {
var current = queue.shift();
var obj = current.obj;
var path = current.path;
if (visited.has(obj)) {
continue;
}
visited.add(obj);
for (var prop in obj) {
if (obj.hasOwnProperty(prop) && typeof obj[prop] === 'object' && obj[prop] !== null) {
try {
if (obj[prop].constructor && obj[prop].constructor.name === 'CBTPlayer') {
return obj[prop];
}
} catch (e) {
continue;
}
queue.push({ obj: obj[prop], path: path + prop + '.' });
}
}
}
return null;
}
var cbtPlayer = findViewModel(window);
if (cbtPlayer) {
var currentOrg = cbtPlayer.currentOrg();
if (currentOrg && currentOrg.items) {
currentOrg.items().forEach(function(item) {
item.completed(true);
item.visited(true);
item.playbackFinished(true);
if (item.type === 'topic' || item.type === 'mergedpages') {
item.items().forEach(function(subItem) {
subItem.completed(true);
subItem.visited(true);
subItem.playbackFinished(true);
});
}
});
currentOrg.items.valueHasMutated();
if (typeof cbtPlayer.SavePlayer === 'function') {
cbtPlayer.SavePlayer();
}
}
}
}
function checkLoginStatus() {
if (window.location.href.indexOf("oauth/#login") > -1) {
setTimeout(function() {
document.querySelector(".step-item.pointer:nth-child(2)").click();
}, 5000);
lastClickTime = Date.now();
}
}
// 添加视频爆破功能
function markVideoAsCompleted() {
var videoElements = document.querySelectorAll('video[id$="player_html5_api"]');
if (videoElements.length > 0) {
var videoElement = videoElements[0];
videojs(videoElement).ready(function() {
var player = this;
player.currentTime(player.duration());
player.trigger('ended');
});
}
}