// ==UserScript==
// @name 江西智慧教育平台-互联网+教师专业发展全员培训-课程助手
// @namespace http://tampermonkey.net/zzzzzzys_江西智慧教育平台-互联网+教师专业发展全员培训-课程助手
// @version 1.0.3
// @copyright zzzzzzys.All Rights Reserved.
// @description 江西智慧教育平台-互联网+教师专业发展全员培训-课程助手(https://www.jx.smartedu.cn/),可自动静音播放视频,防暂停。更全自动方法,请查看文档介绍!
// @author zzzzzzys
// @match https://www.jx.smartedu.cn/*
// @require https://fastly.jsdelivr.net/npm/crypto-js@4.2.0/crypto-js.min.js
// @resource https://cdn.staticfile.org/limonte-sweetalert2/11.7.1/sweetalert2.min.css
// @require https://fastly.jsdelivr.net/npm/sweetalert2@11.12.2/dist/sweetalert2.all.min.js
// @require https://scriptcat.org/lib/637/1.4.5/ajaxHooker.js#sha256=EGhGTDeet8zLCPnx8+72H15QYRfpTX4MbhyJ4lJZmyg=
// @connect fc-mp-8ba0e2a3-d9c9-45a0-a902-d3bde09f5afd.next.bspapp.com
// @connect mp-8ba0e2a3-d9c9-45a0-a902-d3bde09f5afd.cdn.bspapp.com
// @grant unsafeWindow
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_deleteValue
// @grant GM_xmlhttpRequest
// @grant GM_info
// @grant GM_addStyle
// @run-at document-start
// @antifeature ads 有弹窗广告,介绍完全自动化软件
// @antifeature payment 脚本基础功能使用免费,但需要使用完全自动化软件时,可能收费
// ==/UserScript==
(function() {
'use strict';
// 工具函数封装
const delay = ms => new Promise(r => setTimeout(r, ms));
class MainController {
constructor() {
this.hookInitialized = false;
this.domReady = false;
this.courseInstance = null;
this._setupInterceptor();
this._waitForDocument();
}
_setupInterceptor() {
const self = this;
ajaxHooker.hook(function(req) {
const url = req.url;
if (url.indexOf('vedioValidQuestions/getQuestions') !== -1) {
req.response = function(res) {
try {
const parsed = JSON.parse(res.responseText);
unsafeWindow.QuestionInfo = parsed.data;
console.log("QuestionInfo:", unsafeWindow.QuestionInfo);
} catch(e) {
console.error("解析问题信息失败", e);
}
};
}
else if (url.includes('p/play/config')) {
req.response = res => {
try {
const json = JSON.parse(res.responseText);
console.log("play/config:");
console.log(json);
unsafeWindow.playConfig = json.data;
} catch(err) {
console.error("配置解析错误", err);
}
};
}
else if (url.includes('learning/learnVerify/checkCode')) {
req.abort = true;
req.response = res => {
res.responseText = '{"code":0,"msg":null,"data":{"data":"请勿频繁请求","status":9999}}';
};
}
else if (url.includes('learning/learnVerify')) {
req.abort = true;
}
});
console.log("hooker:", ajaxHooker);
}
_waitForDocument() {
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => this._bootstrap());
} else {
this._bootstrap();
}
}
_bootstrap() {
this.courseInstance = new CourseManager("channel-hunau");
}
}
class CourseManager {
constructor(channelId) {
this.channelName = channelId;
this.broadcastCh = new BroadcastChannel(channelId);
this.isPremium = false;
this.isProcessing = false;
this.premiumUrl = null;
this.pauseHandler = null;
this.uiPanel = new ControlPanel({
VIPBtnText: "高级功能-已弃用,请前往软件学习"
});
this._initialize();
}
async _initialize() {
this._setupCallbacks();
this._checkPremiumStatus();
try {
const msg = {
title: "提示",
text: Utils.swFireText,
icon: 'info',
timer: 5000,
confirmButtonText: '确定',
timerProgressBar: true,
willClose: () => {
this.uiPanel.triggerAutomation();
}
};
Swal.fire(msg);
} catch (err) {
console.error(err);
this.uiPanel.triggerAutomation();
}
}
_setupCallbacks() {
this.uiPanel.onVerify = async (data) => {
const validatedUrl = await Utils.validateCode(data);
if (validatedUrl) {
this.premiumUrl = validatedUrl;
this.isPremium = true;
this.uiPanel.updateStatus(Utils.vipText);
return true;
}
return false;
};
this.uiPanel.onStart = () => {
if (this.isProcessing) return;
this.isProcessing = true;
this._execute().finally(() => {
this.isProcessing = false;
});
};
this.uiPanel.onPremium = async () => {
if (!this.premiumUrl) {
await this.uiPanel.promptVerify();
}
await this._runPremium();
};
}
_checkPremiumStatus() {
if (Utils.loadStatus()) {
this.isPremium = true;
this.uiPanel.updateStatus(Utils.vipText);
} else {
this.isPremium = false;
this.uiPanel.updateStatus(Utils.baseText);
}
console.log("VIP:", this.isPremium);
}
async _execute() {
try {
await this._handleVideoPlayback();
} catch (error) {
console.error(error);
Swal.fire({
title: "失败!",
text: `视频基础播放失败!`,
icon: 'error',
confirmButtonColor: "#FF4DAFFF",
confirmButtonText: "确定",
timer: 5000,
timerProgressBar: true
});
}
}
async _handleVideoPlayback() {
const media = document.querySelector('video');
if (!media) return;
media.volume = 0;
media.muted = true;
if (this.pauseHandler) {
media.removeEventListener('pause', this.pauseHandler);
}
let debounceTimer = null;
this.pauseHandler = async () => {
if (media.ended) return;
if (debounceTimer) clearTimeout(debounceTimer);
debounceTimer = setTimeout(async () => {
console.log("检测到视频暂停,自动恢复播放...");
media.volume = 0;
media.muted = true;
try {
await media.play();
} catch (e) {
console.error("恢复播放失败:", e);
}
}, 500);
};
media.addEventListener('pause', this.pauseHandler);
media.addEventListener('ended', () => {
this._switchToNext();
}, { once: true });
await media.play();
}
_switchToNext() {
const listItems = Array.from(document.querySelectorAll('ul.lis-content li.lis-inside-content'));
if (!listItems.length) {
console.log("未找到目录列表");
return;
}
const currentIdx = listItems.findIndex(li => li.querySelector('#top_play'));
console.log("当前目录索引:", currentIdx);
const startSearch = currentIdx === -1 ? 0 : currentIdx + 1;
for (let idx = startSearch; idx < listItems.length; idx++) {
const item = listItems[idx];
const btn = item.querySelector('button');
const titleEl = item.querySelector('h2');
if (!titleEl) continue;
const btnText = btn ? btn.textContent.trim() : '';
console.log(`目录[${idx}] 状态: ${btnText}`);
const clickAttr = titleEl.getAttribute('onclick') || '';
const match = clickAttr.match(/window\.location\.href='([^']+)'/);
if (match) {
const nextUrl = match[1];
const nextTitle = titleEl.textContent.trim().replace(/\s+/g, ' ');
console.log("跳转下一节:", nextUrl);
Swal.fire({
title: "视频已播放完毕",
html: `即将跳转到下一节:
${nextTitle}`,
icon: 'success',
timer: 5000,
timerProgressBar: true,
confirmButtonText: '立即跳转',
showCancelButton: true,
cancelButtonText: '取消',
}).then((result) => {
if (result.isConfirmed || result.dismiss === Swal.DismissReason.timer) {
window.location.href = nextUrl;
}
});
return;
}
}
console.log("已是最后一节,无下一个目录");
this._complete();
}
async _runPremium() {
try {
Utils.showUpgradeAlert();
} catch (error) {
console.error(error);
Swal.fire({
title: "高级功能执行失败!",
text: "若一直失败,请联系进行售后处理!",
icon: 'error',
confirmButtonText: '确定',
allowOutsideClick: false
});
}
}
_complete() {
if (!this.isPremium) {
Swal.fire({
title: "请升级高级版!",
text: `脚本已停止!基础版只能连播几个视频!`,
icon: 'info',
confirmButtonColor: "#FF4DAFFF",
confirmButtonText: "确定",
timer: 0
});
return;
}
this.broadcastCh.postMessage('finish');
Swal.fire({
title: "学习完成!",
text: `学习完成,5s后页面自动关闭!`,
icon: 'success',
confirmButtonColor: "#FF4DAFFF",
confirmButtonText: "确定",
timer: 5000,
willClose: () => {
history.back();
setTimeout(() => location.reload(), 1000);
}
});
}
async _waitVideoEnd(media, container) {
return new Promise((resolve) => {
const checker = setInterval(async () => {
try {
const currentVid = document.querySelector('video');
if (!currentVid) {
clearInterval(checker);
resolve();
return;
}
media.volume = 0;
media.muted = true;
if (media.paused) {
console.log("视频暂停了,重新开始播放...");
media.volume = 0;
media.muted = true;
await media.play();
}
if (!media.src) {
console.error("视频源未设置,即将重新加载");
setTimeout(() => location.reload(), 5000);
}
try {
const quizDialog = document.querySelector('div.el-dialog[aria-label="随机练习"]');
if (quizDialog && unsafeWindow.QuestionInfo) {
const answer = unsafeWindow.QuestionInfo.correctAnswer;
console.log("答题弹窗:答案:", answer);
const options = Array.from(quizDialog.querySelectorAll('input'));
const correctOpt = options.find(opt => opt.value.includes(answer));
if (correctOpt) correctOpt.click();
await delay(100);
const submitBtn = quizDialog.querySelector('.submit');
if (submitBtn) submitBtn.click();
await delay(500);
const msgBoxBtn = document.querySelector('.el-message-box button');
if (msgBoxBtn) msgBoxBtn.click();
}
} catch (e) {}
try {
const tipDialog = document.querySelector('div.el-dialog[aria-label="温馨提示"]');
if (tipDialog) {
const btn = tipDialog.querySelector('button');
if (btn) btn.click();
}
} catch (e) {}
} catch (err) {
console.error("checkInterval error:", err);
clearInterval(checker);
}
}, 5000);
media.addEventListener('ended', () => {
clearInterval(checker);
resolve();
}, { once: true });
});
}
_selectElement(selector, mode = 'single', context, timeout = 10000) {
return new Promise((resolve, reject) => {
const validModes = ['single', 'multiple'];
if (!validModes.includes(mode)) {
reject('Invalid mode');
return;
}
const getNodes = () => {
try {
if (mode === 'single') {
return context ? context.querySelector(selector) : document.querySelector(selector);
} else {
const nodes = context ? context.querySelectorAll(selector) : document.querySelectorAll(selector);
return nodes.length > 0 ? nodes : null;
}
} catch (e) {
console.error('节点检查错误:', e);
return null;
}
};
const timer = setTimeout(() => {
clearInterval(interval);
resolve(null);
}, timeout);
const interval = setInterval(() => {
const result = getNodes();
if (result) {
clearTimeout(timer);
clearInterval(interval);
console.log(`${selector} ready!`);
resolve(result);
} else {
console.log(`等待节点: ${selector}...`);
}
}, 1000);
});
}
_checkProgress(node) {
return node.querySelector('.el-progress__text').innerText.includes("100");
}
_checkPostFinish(node) {
return node.querySelector('.xxzt_icon3');
}
_detectType(node) {
if (node.querySelector('.font-syllabus-online-video')) return 0;
if (node.querySelector('.font-syllabus-page')) return 1;
if (node.querySelector('.font-syllabus-material')) return 2;
return -1;
}
startCaptchaMonitor() {
const dialogSel = ".layui-layer1";
const self = this;
const monitor = setInterval(async () => {
const dialog = document.querySelector(dialogSel);
if (dialog) {
console.log("检查到验证码窗口");
clearInterval(monitor);
const inputSel = "#captchaInput";
const btnSel = ".layui-layer-btn0";
for (let i = 0; i < 20; i++) {
try {
const input = dialog.querySelector(inputSel);
const btn = dialog.querySelector(btnSel);
if (!input || !btn) break;
input.value = i;
await delay(100);
btn.click();
await delay(100);
} catch (err) {
console.error(err);
break;
}
}
self.startCaptchaMonitor();
}
}, 5000);
}
}
class Utils {
static flag = 'hnedu123_VIP'
static js_Flag = 'hnedu123_jsCode'
static vipSign = 'hnedu123_vipSign'
static webId = '69329ec07ae7089a6285fb1b'
static swFireText = "请在视频播放页面使用脚本,脚本检测到视频会自动开始,脚本功能有限,也可能页面有所更新,导致脚本不能正常使用,建议下载软件使用!全自动学习所有未完成视频"
static baseText = '建议下载软件使用!全自动学习所有未完成视频'
static vipText = '全自动建议下载客户端使用!江西智慧教育平台-互联网+教师专业发展全员培训-课程助手'
static vipBtnText = "前往软件使用课程助手,全自动学习所有未完成视频!"
static scriptFeatures = [
"辅助当前页面视频播放",
"防暂停",
"自动静音播放",
"视频播放完成自动切换",
"仅限单页面使用",
]
static softwareFeatures = [
"输入账号密码即可全自动",
"支持批量多账号同时学习",
]
static aliLink = "https://www.alipan.com/s/wViqbLvgSF8"
static directLink = 'http://112.124.58.51/static/课程助手.exe'
static link = [
"https://68n.cn/IJ8QB",
"https://68n.cn/RM9ob",
]
static web_list = [
{ name: "备用地址0", url: "https://www.zzzzzzys.com/" },
{ name: "备用地址1", url: "https://zzzzzzys.lovestoblog.com/" },
{ name: "备用地址2", url: "https://zzzzzzys.us.kg/" },
{ name: "备用地址3", url: "https://zzysdocs.dpdns.org/" },
{ name: "备用地址4", url: "https://zzzzzzys.dpdns.org/" },
{ name: "备用地址5", url: "https://zzzzzzys.kesug.com/" },
{ name: "备用地址6", url: "https://zzysdocs.great-site.net/" },
]
static docLink = `${Utils.web_list[0].url}?webId=` + Utils.webId
static loadStatus() {
return false
}
static async validateCode(data) {
try {
Utils.showUpgradeAlert();
return;
} catch (e) {
console.error(e);
Swal.fire({
title: "验证失败!",
text: e.toString(),
icon: 'error',
confirmButtonText: '确定',
});
}
}
static async fetchRemoteJs(url) {
try {
let cached = GM_getValue(Utils.js_Flag);
if (cached) return cached;
const response = await new Promise((resolve, reject) => {
GM_xmlhttpRequest({
url: url,
method: 'GET',
onload: res => res.status === 200 ? resolve(res.responseText) : reject('Server error'),
onerror: err => reject(err)
});
});
const processed = response
.replace(/\\/g, '\\\\')
.replace(/'/g, '\'')
.replace(/"/g, '\"');
GM_setValue(Utils.js_Flag, processed);
return processed;
} catch (error) {
console.error('远程加载失败:', error);
throw new Error("远程加载失败");
}
}
static showLinkSwal() {
const links = Utils.link;
Swal.fire({
title: ' 高级功能解锁',
html: `
⚠️ 网页脚本有局限性
浏览器脚本运行在沙盒中,无法跨页面、无法自动登录、无法批量管理账号。
若需要 输入账号密码后全自动完成所有视频,推荐使用本地客户端。
📄 当前脚本