// ==UserScript==
// @name 寒假教师研修秒过
// @namespace http://tampermonkey.net/zzzzzzys_国家中小学
// @version 1.0.2
// @description 寒假研修秒过|寒假教师研修|国家智慧教育公共服务平台|国家中小学智慧教育平台秒过
// @author kkkk
// @match https://basic.smartedu.cn/*
// @icon https://basic.smartedu.cn/favicon.ico
// @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
// @connect basic.smartedu.cn
// @connect x-study-record-api.ykt.eduyun.cn
// @grant unsafeWindow
// @grant GM_xmlhttpRequest
// @license GPL-3.0-or-later
// @downloadURL https://update.greasyfork.icu/scripts/524900/%E5%AF%92%E5%81%87%E6%95%99%E5%B8%88%E7%A0%94%E4%BF%AE%E7%A7%92%E8%BF%87.user.js
// @updateURL https://update.greasyfork.icu/scripts/524900/%E5%AF%92%E5%81%87%E6%95%99%E5%B8%88%E7%A0%94%E4%BF%AE%E7%A7%92%E8%BF%87.meta.js
// ==/UserScript==
(function () {
"use strict";
let qqUrl = "https://qm.qq.com/q/rDCbvTiV9K";
let qqNum = "570337037";
let qqNum2 = "618010974";
let qqUrl2 = "https://qm.qq.com/q/h854sxDvKa";
let biliUrl = "https://b23.tv/x5pFcB0";
let requestObj = {
fullsData: {
url: "https://s-file-2.ykt.cbern.com.cn/teach/s_course/v2/activity_sets/3efdb592-138e-4854-8964-5e10f6011f33/fulls.json",
method: "GET",
},
resourceLearningPositions: {
url: "https://x-study-record-api.ykt.eduyun.cn/v1/resource_learning_positions/",
method: "PUT",
},
};
//样式
let style = `.button-3 {
position: fixed;
appearance: none;
background-color: #e52b13;
border: 1px solid rgba(27, 31, 35, .15);
border-radius: 6px;
box-shadow: rgba(27, 31, 35, .1) 0 1px 0;
box-sizing: border-box;
color: #ffffff;
cursor: pointer;
display: inline-block;
font-family: -apple-system,system-ui,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";
font-size: 14px;
font-weight: 600;
line-height: 20px;
padding: 6px 16px;
left: 20px;
top: 300px;
text-align: center;
text-decoration: none;
user-select: none;
-webkit-user-select: none;
touch-action: manipulation;
vertical-align: middle;
white-space: nowrap;
z-index: 2147483647;
}
.button-3:focus:not(:focus-visible):not(.focus-visible) {
box-shadow: none;
outline: none;
}
.button-3:hover {
background-color: #2c974b;
}
.button-3:focus {
box-shadow: rgba(46, 164, 79, .4) 0 0 0 3px;
outline: none;
}
.button-3:disabled {
background-color: #94d3a2;
border-color: rgba(27, 31, 35, .1);
color: rgba(255, 255, 255, .8);
cursor: default;
}
.button-3:active {
background-color: #298e46;
box-shadow: rgba(20, 70, 32, .2) 0 1px 0 inset;
}`;
const createFloatingButton = () => {
// 如果按钮已存在则先移除旧实例
const existingBtn = document.getElementById("zs-helper-btn");
if (existingBtn) existingBtn.remove();
// 直接创建按钮元素(去掉外层div嵌套)
const btn = document.createElement("div");
btn.id = "zs-helper-btn"; // 确保唯一ID直接设置在元素上
btn.style.cssText = `
position: fixed;
left: 0px;
top: 250px;
transform: translateY(-50%);
background: #FF4DAF;
color: white;
padding: 12px 24px;
border-radius: 30px;
cursor: pointer;
box-shadow: 0 4px 12px rgba(255,77,175,0.3);
z-index: 2147483647; /* 使用最大z-index值 */
transition: 0.3s;
font-family: 'Microsoft Yahei', sans-serif;
white-space: nowrap;
display: flex;
align-items: center;
gap: 8px;
`;
// 添加内部HTML内容
btn.innerHTML = `
使用指南
`;
// 使用更可靠的事件监听方式
const handleHover = () => {
btn.style.transform = "translateY(-50%) scale(1.05)";
btn.style.boxShadow = "0 6px 16px rgba(255,77,175,0.4)";
};
const handleLeave = () => {
btn.style.transform = "translateY(-50%) scale(1)";
btn.style.boxShadow = "0 4px 12px rgba(255,77,175,0.3)";
};
btn.addEventListener("mouseenter", handleHover);
btn.addEventListener("mouseleave", handleLeave);
btn.addEventListener("click", showGuideDialog);
document.body.appendChild(btn);
return btn;
};
// 显示操作指南弹窗
const showGuideDialog = () => {
if (Swal) {
Swal.fire({
title:
'📚 智能刷课指南 v1.0.2
',
html: `
播放页面未正常生效请刷新页面!
🚀 极速操作流程
1
进入2025研修课程播放页面
2
等待视频加载完成(未自动播放时)
3
点击左侧「即刻开刷」按钮
⚠️ 重要提醒
- 视频最后剩下5秒需要看完
- 请勿主动点击播放
- 建议刷完全部视频再刷新,观看最后的几秒
💡 高效技巧
- 先刷一个视频
- 点击另外一个视频
- 再点击回刚刷的视频,播放完最后5s
`,
confirmButtonText: "已了解,开始减负之旅 →",
confirmButtonColor: "#FF4DAF",
showCancelButton: true,
cancelButtonText: "不在显示此窗口",
cancelButtonColor: "#95a5a6",
width: 760,
customClass: {
popup: "animated pulse",
title: "swal-title-custom",
},
footer:
'请合理使用本工具
',
}).then((result) => {
// console.log(result);
// console.log(Swal.DismissReason.cancel);
if (result.dismiss === Swal.DismissReason.cancel) {
// 跳转到课程列表页或其他操作
localStorage.setItem("noMoreDialog", "ture");
}
});
}
};
// 初始化逻辑
// 初始化逻辑优化
const init = () => {
// 创建悬浮按钮
const floatBtn = createFloatingButton();
// 添加防DOM清理监听(优化版)
const observer = new MutationObserver((mutations) => {
if (!document.body.contains(floatBtn)) {
createFloatingButton();
}
});
observer.observe(document.body, { childList: true });
// 添加CSS保护
const style = document.createElement("style");
style.textContent = `
#zs-helper-btn {
pointer-events: auto !important;
opacity: 1 !important;
visibility: visible !important;
}
#zs-helper-btn:hover {
transform: translateY(-50%) scale(1.05) !important;
}
`;
document.head.appendChild(style);
};
window.onload = function () {
init();
if (
!location.href.includes("courseDetail") &&
!localStorage.getItem("noMoreDialog")
) {
showGuideDialog();
return;
}
if (
!location.href.includes("courseDetail") &&
!location.href.includes("courseIndex")
) {
return;
}
let myStyle = document.createElement("style");
myStyle.innerHTML = style;
document.head.appendChild(myStyle);
/*let intercept=GM_GetValue*/
let div = document.createElement("div");
div.innerHTML = `即刻开刷
2222
`;
document.body.appendChild(div);
document.getElementById("my1").addEventListener("click", async () => {
try {
await setProgress(
requestObj.resourceLearningPositions.url +
getResourceId() +
"/" +
getDynamicToken().token["user_id"],
getVideoTime()
);
if (Swal) {
Swal.fire({
title: "刷课成功!",
html: `
`,
icon: "success",
confirmButtonColor: "#FF4DAFFF",
// cancelButtonText: "取消,等会刷新",
// 作者:zzzzzzys
// https://greasyfork.org/zh-CN/users/1176747-zzzzzzys
// 搬运可耻
confirmButtonText: "确定",
}).then((result) => {
if (result.isConfirmed) {
}
});
}
} catch (e) {
console.error(e);
if (Swal) {
Swal.fire({
title: "失败!",
text: e,
icon: "error",
// showCancelButton: true,
confirmButtonColor: "#FF4DAFFF",
// cancelButtonText: "取消,等会刷新",
confirmButtonText: "点击去反馈",
}).then((result) => {
if (result.isConfirmed) {
window.open(
"https://greasyfork.org/zh-CN/scripts/525037/feedback"
);
}
});
}
}
});
document.getElementById("my2").addEventListener("click", function () {
Swal.fire({
title:
'欢迎加入交流群',
html: `
📚 减负工具
🛡️ 使用规范
- 仅限中小学课程使用
- 禁止商业倒卖行为
- 请勿批量自动化操作大量刷课
`,
icon: "info",
confirmButtonColor: "#FF4DAF",
confirmButtonText: "2222",
showCloseButton: true,
width: 680,
showDenyButton: true,
denyButtonText:
'
前往好评', // 带图标的按钮
denyButtonColor: "#FFC107",
focusDeny: false,
showCancelButton: false,
// 新增按钮回调
preDeny: () => {
window.open(
"https://greasyfork.org/zh-CN/scripts/525037/feedback",
"_blank"
);
return false; // 阻止弹窗关闭
},
customClass: {
denyButton: "swal-custom-deny",
popup: "swal-custom-popup",
title: "swal-custom-title",
},
footer:
'请合理使用。
',
});
});
};
function getVideoTime() {
return Math.round(document.querySelector("video").duration);
}
function getResourceId() {
// 获取目标元素
const divElement = document.querySelector("div.vjs-poster");
if (divElement) {
const bgImage = divElement.style.backgroundImage;
const uuidPattern =
/assets\/([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/;
const match = bgImage.match(uuidPattern);
if (match) {
const resId = match[1];
console.log(resId);
return resId;
}
}
throw Error("can not get ResourceId!");
}
function getDynamicToken() {
try {
const pattern =
/^ND_UC_AUTH-([0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12})&ncet-xedu&token$/;
for (let key of Object.keys(localStorage)) {
if (pattern.test(key)) {
return {
key: key,
appId: key.match(pattern)[1],
token: JSON.parse(JSON.parse(localStorage.getItem(key)).value),
};
}
}
throw Error("Invalid token! can not get loginInfo!");
} catch (err) {
throw Error("At:getDynamicToken>>" + err);
}
}
// const tokenData = getDynamicToken();
// if (tokenData) {
// console.log("完整键名:", tokenData.key);
// console.log("用户UUID:", tokenData.uuid);
// console.log("Token值:", tokenData.token);
// }
// 作者:zzzzzzys
// https://greasyfork.org/zh-CN/users/1176747-zzzzzzys
// 搬运可耻
const getMACAuthorizationHeaders = function (url, method) {
let n = getDynamicToken().token;
return He(url, method, {
accessToken: n.access_token,
macKey: n.mac_key,
diff: n.diff,
});
};
function Ze(e) {
for (
var t = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""), n = "", r = 0;
r < e;
r++
)
n += t[Math.ceil(35 * Math.random())];
return n;
}
function Fe(e) {
return new Date().getTime() + parseInt(e, 10) + ":" + Ze(8);
}
function ze(e, t, n, r) {
let o = {
relative: new URL(e).pathname,
authority: new URL(e).hostname,
};
let i =
t +
"\n" +
n.toUpperCase() +
"\n" +
o.relative +
"\n" +
o.authority +
"\n";
return CryptoJS.HmacSHA256(i, r).toString(CryptoJS.enc.Base64);
}
function He(e) {
// 作者:zzzzzzys
// https://greasyfork.org/zh-CN/users/1176747-zzzzzzys
// 搬运可耻
let t =
arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : "GET",
n = arguments.length > 2 ? arguments[2] : void 0,
r = n.accessToken,
o = n.macKey,
i = n.diff,
s = Fe(i),
a = ze(e, s, t, o);
return 'MAC id="'
.concat(r, '",nonce="')
.concat(s, '",mac="')
.concat(a, '"');
}
const setProgress = function (url, duration) {
const info = getDynamicToken();
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
url: url,
method: "PUT",
headers: {
accept: "application/json, text/plain, */*",
"accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
authorization: getMACAuthorizationHeaders(url, "PUT"),
"cache-control": "no-cache",
pragma: "no-cache",
"content-type": "application/json",
"sdp-app-id": info.appId,
"sec-ch-ua":
'"Not A(Brand";v="8", "Chromium";v="132", "Microsoft Edge";v="132"',
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": '"Windows"',
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "cross-site",
host: "x-study-record-api.ykt.eduyun.cn",
origin: "https://basic.smartedu.cn",
referer: "https://basic.smartedu.cn/",
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36 Edg/121.0.0.0",
},
data: JSON.stringify({ position: duration - 3 }),
// fetch:true,
onload: function (res) {
console.log("请求成功");
console.log(res);
if (res.status === 200) {
console.log("刷课成功!");
resolve(res);
}
},
onerror: function (err) {
reject("请求错误!" + err.toString());
},
});
});
};
})();