// ==UserScript==
// @name 🍀新版中国教育干部网络学院|脚本使用说明:http://doc.zhanyc.cn/pages/zgjygbwlxy/
// @namespace free
// @version 1.0
// @description 当前是免费版本,可免费使用视频自动播放、解除视频暂停限制、自动换课程功能数量受限。如需完整无人值守功能,含自动下一集、自动换课程、全自动无人值守高级功能需升级VIP版本解锁
// @author free
// @include *://*.enaea.edu.cn/*
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_addStyle
// @grant GM_deleteValue
// @grant GM_xmlhttpRequest
// @run-at document-end
// @require https://scriptcat.org/lib/8488/jquery-2.2.4.min.js/jquery-2.2.4.min.js.js?sha384-rY/jv8mMhqDabXSo+UCggqKtdmBfd3qC2/KvyTDNQ6PcUJXaxK1tMepoQda4g5vB
// @antifeature payment
// @license Creative Commons
// ==/UserScript==
(function () {
let docUrl = "http://doc.zhanyc.cn/pages/zgjygbwlxy/";
let _0x5a2c = ["\x76\x69\x64\x65\x6f\x43\x6f\x75\x6e\x74", "\x66\x72\x65\x65\x4f\x62\x6a", "\x67\x65\x74\x4d\x61\x78\x56\x69\x64\x65\x6f\x43\x6f\x75\x6e\x74"];
let _cfg = { v: "20261110", k: 0x1F3A, m: [3, 5, 7, 11, 13, 17, 19, 23] };
let freeObj = {
pageData: {
videoTimer: null,
checkTimer: null,
waitTime: 0,
lastTime: null,
checkTimes: 60,
running: false,
lastUrl: "",
},
async init() {
console.log("%c freeInit", "background:rgb(0,0,0);color:#fff");
freeObj.addGlobalStyle();
freeObj.showFloatingBox();
freeObj.begin();
},
begin() {
freeObj.pageData.lastUrl = location.href;
setInterval(() => {
if (freeObj.pageData.lastUrl !== location.href) {
freeObj.pageData.lastUrl = location.href;
freeObj.runByUrl(location.href);
}
}, 500);
freeObj.runByUrl(location.href);
},
runByUrl(url) {
clearInterval(freeObj.pageData.videoTimer);
freeObj.pageData.videoTimer = null;
clearTimeout(freeObj.pageData.checkTimer);
freeObj.pageData.checkTimer = null;
url = url.toLowerCase();
$(".zfk-float-tip-box").remove();
if (url.includes("/web/") && url.includes("/home")) {
freeObj.pageHome();
} else if (url.includes("/player/project")) {
freeObj.pageVideo();
} else if (url.includes("/requiredcourse") || url.includes("/electivecourses")) {
freeObj.pageCourseDetail();
}
},
addGlobalStyle() {
GM_addStyle(`
.free-btn{background-color:#0fbcf9;color:#fff;padding:4px 12px;border:none;font-size:14px;border-radius:4px;cursor:pointer;display:inline-block;text-align:center}
.free-btn:hover{opacity:.8}
.free-btn.success{background-color:#38b03f}
.free-btn.warning{background-color:#f1a325}
.free-btn.danger{background-color:#ea644a}
.free-btn.vip{background:linear-gradient(135deg,#ff6b6b,#ee5a6f);color:#fff;font-weight:bold}
@keyframes freeGlow{0%{box-shadow:0 0 10px #00ffcc}50%{box-shadow:0 0 20px #ff66cc}100%{box-shadow:0 0 10px #00ffcc}}
`);
},
pageHome() {
console.log("%c pageHome", "background:rgb(0,0,0);color:#fff");
freeObj.waitForElement(() => $('[class^="main-sub_"]').length > 0, () => {
freeObj.renderHomeButtons();
});
},
renderHomeButtons() {
if ($("#free-home-container").length > 0) return;
let videoCount = freeObj.getVideoCount();
let maxCount = freeObj.getMaxVideoCount();
let settingsHtml = `
免费版本学习设置
已学习 ${videoCount}/${maxCount}
(VIP版本专属功能)
(VIP版本可设置更多)
提示:免费版本仅支持解除视频暂停限制,如需自动学习、加速学习等功能请升级VIP版本
`;
let $target = $('[class^="main-sub_"]').first();
if ($target.length > 0) {
$target.before(settingsHtml);
} else {
$('body').prepend(settingsHtml);
}
$("#free-start-study-btn").on("click", function () {
freeObj.showVipUpgradeBox("VIP版本专属功能", "自动学习功能需要升级VIP版本后才能使用。VIP版本支持:自动下一集、自动换课程、秒过视频、加速学习等高级功能。");
});
$("#free-speed-select").on("change", function () {
freeObj.showVipUpgradeBox("VIP版本专属功能", "加速学习功能需要升级VIP版本后才能使用。当前免费版本仅支持1倍速播放。");
$(this).val("1");
});
},
pageVideo() {
console.log("%c pageVideo", "background:rgb(0,0,0);color:#fff");
freeObj.validateVideoAccess(() => {
freeObj.startVideoPlay();
});
},
validateVideoAccess(callback) {
let currentCount = freeObj.getVideoCount();
let limitCount = freeObj.getMaxVideoCount();
freeObj.checkVideoLimitStatus(currentCount, limitCount, callback);
},
checkVideoLimitStatus(current, limit, callback) {
let status = freeObj.calcLimitStatus(current, limit);
if (status.allowed) {
callback();
} else {
freeObj.handleLimitExceeded(status);
}
},
calcLimitStatus(current, limit) {
let diff = limit - current;
let allowed = diff > 0;
let remaining = Math.max(0, diff);
return { allowed: allowed, remaining: remaining, total: limit };
},
handleLimitExceeded(status) {
let msgData = freeObj.buildLimitMsg(status);
freeObj.displayLimitWarning(msgData);
},
buildLimitMsg(status) {
let title = freeObj.formatLimitTitle(status);
let content = freeObj.formatLimitContent(status);
return { title: title, content: content };
},
formatLimitTitle(status) {
let titles = ["免费额度已用完", "试用次数已耗尽", "体验次数已达上限"];
let idx = status.total % titles.length;
return titles[idx];
},
formatLimitContent(status) {
let templates = [
"免费脚本可全自动学习前{total}个视频,目前免费额度已经用完,请升级VIP版本后继续使用。",
"当前免费版本支持{total}个视频自动学习,您的额度已用完,升级VIP可解锁无限学习。",
"体验次数{total}次已用完,如需继续自动学习请升级VIP版本。"
];
let idx = (status.total + status.remaining) % templates.length;
return templates[idx].replace("{total}", status.total);
},
displayLimitWarning(msgData) {
freeObj.showVipUpgradeBox(msgData.title, msgData.content);
},
startVideoPlay() {
if (freeObj.pageData.videoTimer != null) return;
freeObj.pageData.running = true;
freeObj.pageData.checkTimes = 60;
freeObj.pageData.lastTime = null;
freeObj.showTips("视频自动播放已启动");
freeObj.pageData.videoTimer = setInterval(async () => {
try {
if (freeObj.pageData.waitTime > 0) {
freeObj.pageData.waitTime--;
return;
}
let video = freeObj.getVideoElement();
if (!video) {
console.log("%c no video", "background:rgb(0,0,0);color:#fff");
return;
}
let curTime = video.currentTime;
if (curTime == freeObj.pageData.lastTime) {
freeObj.pageData.checkTimes--;
if (freeObj.pageData.checkTimes <= 0) {
freeObj.pageData.checkTimes = 60;
freeObj.showTips("视频似乎卡住了,正在刷新页面...");
setTimeout(() => location.reload(), 3000);
return;
}
} else {
freeObj.pageData.lastTime = curTime;
freeObj.pageData.checkTimes = 60;
}
video.volume = 0;
let title = `进度:${curTime.toFixed(0)}/${video.duration.toFixed(0)}`;
$("title").text(title);
freeObj.updateFloatingBoxProgress(title);
let isFinish = video.duration > 0 && curTime + 5 >= video.duration;
if (isFinish) {
freeObj.pageData.waitTime = 15;
freeObj.showTips("视频即将结束");
freeObj.handleVideoFinish();
return;
}
if (video.paused && !isFinish) {
video.play().catch(() => { });
}
} catch (e) {
console.error("视频定时器出错", e);
}
}, 1000);
freeObj.pageData.checkTimer = setTimeout(async () => {
let video = freeObj.getVideoElement();
if (video) {
let time = video.currentTime;
await freeObj.wait(5000);
if (video.currentTime == time) {
freeObj.showTips("视频似乎卡住了,3秒后刷新页面");
setTimeout(() => location.reload(), 3000);
}
}
}, 60000);
},
handleVideoFinish() {
freeObj.processVideoCompletion();
},
processVideoCompletion() {
let countData = freeObj.incrementVideoCount();
freeObj.displayVideoProgress(countData);
freeObj.checkPostVideoAction(countData);
},
incrementVideoCount() {
let current = freeObj.getVideoCount();
current++;
freeObj.setVideoCount(current);
let max = freeObj.getMaxVideoCount();
return { current: current, max: max };
},
displayVideoProgress(countData) {
let msg = freeObj.buildProgressMsg(countData);
freeObj.showTips(msg);
},
buildProgressMsg(data) {
let formats = [
"当前已学习 {current}/{max} 个视频",
"已完成 {current}/{max} 个视频学习",
"学习进度 {current}/{max}"
];
let idx = (data.current + data.max) % formats.length;
return formats[idx].replace("{current}", data.current).replace("{max}", data.max);
},
checkPostVideoAction(countData) {
let action = freeObj.determineNextAction(countData);
freeObj.executeNextAction(action);
},
determineNextAction(countData) {
if (countData.current >= countData.max) {
return { type: "showVip", delay: 2000 };
}
return { type: "checkNext", delay: 10000 };
},
executeNextAction(action) {
setTimeout(() => {
if (action.type === "showVip") {
freeObj.triggerVipUpgradePrompt();
} else {
freeObj.checkAndNavigateNext();
}
}, action.delay);
},
triggerVipUpgradePrompt() {
let promptData = freeObj.buildVipPromptData();
freeObj.displayLimitWarning(promptData);
},
buildVipPromptData() {
let max = freeObj.getMaxVideoCount();
let titles = ["免费额度已用完", "试用次数已耗尽", "体验次数已达上限"];
let contents = [
"免费脚本可全自动学习前{max}个视频,目前免费额度已经用完,请升级VIP版本后继续使用。",
"当前免费版本支持{max}个视频自动学习,您的额度已用完,升级VIP可解锁无限学习。"
];
let titleIdx = max % titles.length;
let contentIdx = (max + 1) % contents.length;
return {
title: titles[titleIdx],
content: contents[contentIdx].replace("{max}", max)
};
},
checkAndNavigateNext() {
if ($(`#rightBox [class^='item-wrap_']:last`).find(`[class^='rate-span_']`).text().trim() == '完成') {
freeObj.showTips("准备前往详情页面");
setTimeout(() => {
$(`span[class^="return-icon"]`).click();
}, 3000);
}
},
pageCourseDetail() {
console.log("%c pageCourseDetail", "background:rgb(0,0,0);color:#fff");
freeObj.waitForElement(() => $(".grt-collapse-item").length > 0, async () => {
await freeObj.wait(2000);
let $elArr = [];
$(".grt-collapse-item").not('.grt-collapse-item-active').each((i, el) => {
$elArr.push($(el));
});
for (let i = 0; i < $elArr.length; i++) {
const $el = $elArr[i];
$el.find(`[class^='panel-header']`).click();
await freeObj.wait(200);
}
await freeObj.wait(500);
let $el = null;
$("[class^='section-box']").each((i, el) => {
if ($(el).find(`[class^='progress-label']`).length > 0) {
if ($(el).find(`[class^='progress-label']`).text() == '完成') {
return true;
}
}
$el = $(el);
return false;
});
if ($el == null) {
freeObj.showTips("学习完成");
return;
}
freeObj.showTips("3秒后开始播放视频");
await freeObj.wait(3000);
$el.find(`[class^='section-list']:first`).find(`[class^='list-title']`).click();
});
},
getVideoElement() {
try {
return $("video")[0];
} catch (e) {
return null;
}
},
getVideoCount() {
return GM_getValue("videoPlayCount", 0);
},
setVideoCount(count) {
GM_setValue("videoPlayCount", count);
},
waitForElement(condition, callback, interval = 1000, timeout = 30) {
let _timeOut = timeout * 1000;
if (condition()) {
callback();
return;
}
let index = setInterval(() => {
_timeOut -= interval;
if (_timeOut < 0) {
clearInterval(index);
return;
}
if (condition()) {
clearInterval(index);
callback();
}
}, interval);
},
wait(timeout) {
return new Promise(resolve => setTimeout(resolve, timeout));
},
showTips(msg, duration = 3000) {
console.log("%c " + msg, "background:rgb(0,255,0);color:#000");
freeObj.updateFloatingBoxTips(msg);
freeObj.showToast(msg, duration);
},
showToast(msg, duration = 3000) {
$("#freeToastOverlay").remove();
let autoClose = duration > 0;
let closeBtnHtml = autoClose
? `${duration / 1000}秒后自动关闭
`
: `点击关闭
`;
let $toast = $(`
`);
$("body").append($toast);
if ($("#freeToastStyle").length === 0) {
$("head").append(``);
}
if (!autoClose) {
$("#freeToastClose").on("click", function () {
let $overlay = $("#freeToastOverlay");
$overlay.find("div").first().css("animation", "freeToastFadeOut 0.3s ease-out");
setTimeout(() => $overlay.remove(), 300);
});
}
if (autoClose) {
setTimeout(() => {
let $overlay = $("#freeToastOverlay");
if ($overlay.length > 0) {
$overlay.find("div").first().css("animation", "freeToastFadeOut 0.3s ease-out");
setTimeout(() => $overlay.remove(), 300);
}
}, duration);
}
},
showVipUpgradeBox(title, content) {
$("#freeVipBox").remove();
let $box = $(`
🔔 ${title}
×
${content}
VIP特权:永久使用 | 免费维护 | 不限制电脑 | 秒过视频 | 自动换课
`);
$("body").append($box);
$box.find(".free-vip-close").on("click", function () {
$box.remove();
});
},
showFloatingBox() {
if ($("#freeFloatingBox").length > 0) return;
let videoCount = freeObj.getVideoCount();
let maxCount = freeObj.getMaxVideoCount();
let $box = $(`
当前状态:
等待启动
播放进度:
0/0
已学习:
${videoCount}/${maxCount}
提示信息:
就绪
💡 免费版本功能
✓ 解除视频暂停限制
✓ 自动播放视频
✓ 受限的视频自动换课功能
✗ 加速学习(VIP专属)
✗ 自动换课程(VIP专属)
✗ 秒过视频(VIP专属)
`);
$("body").append($box);
$("#freeCloseBtn").on("click", function () {
$("#freeFloatingBox").remove();
});
freeObj.initDrag("#freeFloatingHeader", "#freeFloatingBox");
},
initDrag(handleSelector, boxSelector) {
let $handle = $(handleSelector);
let $box = $(boxSelector);
let isDragging = false;
let startX, startY, initialLeft, initialTop;
$handle.on("mousedown", function (e) {
if ($(e.target).is("#freeCloseBtn")) return;
isDragging = true;
startX = e.clientX;
startY = e.clientY;
let rect = $box[0].getBoundingClientRect();
$box.css({
top: rect.top + "px",
bottom: "auto"
});
initialLeft = rect.left;
initialTop = rect.top;
$box.css("transition", "none");
e.preventDefault();
});
$(document).on("mousemove", function (e) {
if (!isDragging) return;
let deltaX = e.clientX - startX;
let deltaY = e.clientY - startY;
$box.css({
left: (initialLeft + deltaX) + "px",
top: (initialTop + deltaY) + "px"
});
});
$(document).on("mouseup", function () {
isDragging = false;
});
},
updateFloatingBoxTips(msg) {
$("#freeTipsText").text(msg);
},
updateFloatingBoxProgress(progress) {
$("#freeProgressText").text(progress);
},
updateFloatingBoxStatus(status) {
$("#freeStatusText").text(status);
},
updateFloatingBoxCount() {
let videoCount = freeObj.getVideoCount();
let maxCount = freeObj.getMaxVideoCount();
$("#freeCountText").text(`${videoCount}/${maxCount} `);
},
syncCourseData() {
console.log("%c syncCourseData", "background:rgb(0,0,0);color:#fff");
},
checkExamStatus() {
console.log("%c checkExamStatus", "background:rgb(0,0,0);color:#fff");
},
updateVideoProgress() {
console.log("%c updateVideoProgress", "background:rgb(0,0,0);color:#fff");
},
recordUserAction() {
console.log("%c recordUserAction", "background:rgb(0,0,0);color:#fff");
},
initAutoPlayConfig() {
console.log("%c initAutoPlayConfig", "background:rgb(0,0,0);color:#fff");
},
getMaxVideoCount() {
let _t = Date.now();
let _v = parseInt(_cfg.v) || 20261110;
let _k = _cfg.k ^ 0x1F32;
let _s1 = _cfg.m.reduce((a, b) => a + b, 0);
let _s2 = _cfg.m.filter(x => x > 10).length;
let _h = 0;
let _str = _cfg.v + "_" + _cfg.k;
for (let i = 0; i < _str.length; i++) {
_h = ((_h << 5) - _h) + _str.charCodeAt(i);
_h = _h & _h;
}
let _r1 = Math.abs(_h) % 16;
let _r2 = (_s1 + _s2) % 32;
let _r3 = (_k >> 2) & 0xF;
let _r4 = Math.floor(Math.sqrt(_v % 100));
let _base = (_r1 + _r2 + _r3 + _r4) % 16;
let _lookup = [8, 6, 7, 9, 10, 6, 8, 8, 9, 8, 6, 7, 8, 9, 10, 6];
let _final = _lookup[_base];
let _verify = (_k & 0xF) === 8 ? 0 : 1;
return _final + _verify;
}
};
setTimeout(() => {
if (typeof (zfk) == 'undefined') {
freeObj.init();
} else {
console.log('skip init');
}
}, 3000);
})();