// ==UserScript== // @name 成都文理学院刷课助手|自动刷课|考试自动答题 // @version 2.1.3 // @description 成都文理学院刷课助手,(虽不止成文理,但仅在成文理做了测试)🚀目前已支持平台:【数字化实习实训平台、公益课程、在线学堂、英华学堂】。😀目前已具有功能包括:视频自动播放、自动识别填充验证码、考试自动答题等功能。如有bug请留言。🐧QQ交流群:878643471 // @author iFulling // @match *://zxshixun.cdcas.com/* // @match *://*.zjxkeji.com/* // @match *://mooc.cdcas.com/* // @match *://*.rurenkj.com/* // @match *://*/* // @icon data:image/png;base64,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 // @grant GM_xmlhttpRequest // @grant GM_setValue // @grant GM_getValue // @grant GM_listValues // @license MIT // @namespace https://github.com/iFulling/cdcasSK // @connect 119.8.102.43 // @connect 119.8.102.43:5000 // @connect ark.cn-beijing.volces.com // @downloadURL https://update.greasyfork.icu/scripts/512596/%E6%88%90%E9%83%BD%E6%96%87%E7%90%86%E5%AD%A6%E9%99%A2%E5%88%B7%E8%AF%BE%E5%8A%A9%E6%89%8B%7C%E8%87%AA%E5%8A%A8%E5%88%B7%E8%AF%BE%7C%E8%80%83%E8%AF%95%E8%87%AA%E5%8A%A8%E7%AD%94%E9%A2%98.user.js // @updateURL https://update.greasyfork.icu/scripts/512596/%E6%88%90%E9%83%BD%E6%96%87%E7%90%86%E5%AD%A6%E9%99%A2%E5%88%B7%E8%AF%BE%E5%8A%A9%E6%89%8B%7C%E8%87%AA%E5%8A%A8%E5%88%B7%E8%AF%BE%7C%E8%80%83%E8%AF%95%E8%87%AA%E5%8A%A8%E7%AD%94%E9%A2%98.meta.js // ==/UserScript== let videoElement = null; let checkCaptchaTimer = null; let containerTextElement = null; let examTextElement = null; let sponsorElement = null; let statementElement = null; let layuiLayerContent = null; let links = null; let current = 0; let timerCnt = 0; let version = "2.1.3" let endpoint_id = ""; let apikey = ""; let examCurrent = 0; let startFlag = false; // 获取当前课程 function getCurrent() { links = $('a[target="_self"]'); links.each((index, item) => { if ($(item).hasClass("on")) { return current = index } }); } // 下一个视频 async function playNext() { clearInterval(checkCaptchaTimer); if (current === links.length - 1) { addText("最后一个已看完!") } else { addText("准备播放下一个视频...") await pause(3) links[current + 1].click(); } } // 输入验证码 async function inputCaptcha() { if (layuiLayerContent.length && layuiLayerContent.is(':visible')) { addText("验证码弹窗出现,准备填写验证码..."); await pause(2, 5) // 获取图片 let imgs = layuiLayerContent.find("img") let img = imgs[0].style.opacity === '0' ? imgs[1] : imgs[0] // 图片转base64 let canvas = document.createElement("canvas"); let ctx = canvas.getContext("2d"); canvas.width = img.width; canvas.height = img.height; ctx.drawImage(img, 0, 0, img.width, img.height); let code = canvas.toDataURL("image/png").split("base64,")[1]; // 调用接口,识别验证码 let ans = await getCode(code) // 获取input,填入验证码 let inputs = layuiLayerContent.find("input") let input = inputs[0].style.display === 'none' ? inputs[1] : inputs[0] $(input).mousedown() input.value = ans // 点击开始播放按钮 await pause(2, 5) const playButton = $('.layui-layer-btn0'); if (playButton.length) { playButton.click(); checkCaptchaTimer = setInterval(playVideo, 1000); addText("已自动点击开始播放按钮!"); } else { addText("未找到开始播放按钮,尝试刷新页面...."); location.reload(); // 刷新当前页面 } } } async function test(){ let img = $("#codeImg")[0] // 图片转base64 let canvas = document.createElement("canvas"); let ctx = canvas.getContext("2d"); canvas.width = img.width; canvas.height = img.height; ctx.drawImage(img, 0, 0, img.width, img.height); let code = canvas.toDataURL("image/png").split("base64,")[1]; // 调用接口,识别验证码 let ans = await getCode(code) console.log(ans) } function getCode(code) { return new Promise((resolve, reject) => { const datas = { "ImageBase64": String(code), } GM_xmlhttpRequest({ method: "POST", url: "http://119.8.102.43:5000/get_captcha", data: JSON.stringify(datas), headers: { "Content-Type": "application/json", }, responseType: "json", timeout: 10000, ontimeout: async function (e) { addText("验证码获取超时,刷新页面..."); await pause(3) location.reload(); // 刷新当前页面 }, onload: function (response) { if (response.status == 200) { let result = response.response["message"]; addText("识别结果:" + result); return resolve(result); } else { let result = JSON.parse(response.response)["message"]; addText(result); addText("识别失败,请勿开启代理,或联系管理员。🐧群:878643471"); } }, onerror: function (error) { addText(`${error.statusText} ${error.status} - 出错了`) }, }); }); } // 播放视频,同时检测验证码 async function playVideo() { timerCnt++; if (timerCnt % 5 === 0) { addText("等待加载,已加载:" + timerCnt + "秒") } if (timerCnt > 20) { addText("刷新页面") location.reload(); return } if (!videoElement) { if (links[current].title && current === links.length - 1) { addText("课程已看完,自动停止!") clearInterval(checkCaptchaTimer) }else if (links[current].title && /考试|章节作业|自学教材/.test(links[current].title)){ addText("没有视频,准备跳过...") clearInterval(checkCaptchaTimer) await playNext(); }else { getVideoElement(); } return } // 验证码弹窗 layuiLayerContent = $('.layui-layer-content'); if (layuiLayerContent.length > 0) { clearInterval(checkCaptchaTimer); await inputCaptcha() return; } // 检测视频是否加载成功且暂停 // if (!videoElement) return; if (videoElement.paused) { videoElement.play(); if (videoElement.readyState === 4) { const message = containerTextElement.text().includes("视频加载完成") ? "请将浏览器置于前台运行。(若学时会增加可忽略)" : "视频加载完成,准备播放"; addText(message); } } else { timerCnt = 0; } } // 获取视频元素 const getVideoElement = () => { videoElement = document.querySelector("video"); videoElement.muted = true; videoElement.playbackRate = 1.0; videoElement.volume = 0; videoElement.onended = async function () { await playNext(); }; } // 添加交互显示 const addContainer = () => { const mini = $("
刷课
助手
") const container = $('') container.addClass('popup'); const header = $("
") header.addClass('container-header') header.text("成都文理学院刷课助手 " + version) container.append(header) const btnGroup = $("
") const classTab = $("") const examTab = $("") const statementTab = $("") const sponsorTab = $("") const minimize = $("") btnGroup.append(classTab) btnGroup.append(examTab) btnGroup.append(statementTab) btnGroup.append(sponsorTab) btnGroup.append(minimize) header.append(btnGroup) classTab.on("click", () => { containerTextElement.show() examTextElement.hide() statementElement.hide() sponsorElement.hide() }) examTab.on("click", ()=>{ containerTextElement.hide() examTextElement.show() statementElement.hide() sponsorElement.hide() }) statementTab.on("click", () => { containerTextElement.hide() examTextElement.hide() statementElement.show() sponsorElement.hide() }) sponsorTab.on("click", () => { containerTextElement.hide() examTextElement.hide() statementElement.hide() sponsorElement.show() }) classTab.on("mousedown", e=>{ e.stopPropagation() }) examTab.on("mousedown", e=>{ e.stopPropagation() }) statementTab.on("mousedown", e=>{ e.stopPropagation() }) sponsorTab.on("mousedown", e=>{ e.stopPropagation() }) minimize.on("click", ()=>{ container.hide() mini.css("display", "flex") }) let moveFlag = false; mini.on("mouseup", ()=>{ if (moveFlag) return; container.show() mini.hide() }) // 添加移动事件 header.on("mousedown", function (event) { event.stopPropagation(); event.preventDefault() document.body.style.userSelect = 'none'; // 获取鼠标相对盒子的偏移量 let shiftX = event.clientX - header.offset().left; let shiftY = event.clientY - header.offset().top; // 当鼠标移动时 function onMouseMove(event) { event.stopPropagation(); event.preventDefault() container.css({ left: event.pageX - shiftX + 'px', top: event.pageY - shiftY + 'px' }) } // 鼠标提起来 function onMouseUp() { document.body.style.userSelect = 'auto'; $(document).off('mousemove', onMouseMove); $(document).off('mouseup', onMouseUp); } $(document).on('mousemove', onMouseMove); $(document).on('mouseup', onMouseUp); }) mini.on("mousedown", function (event) { event.stopPropagation(); event.preventDefault() document.body.style.userSelect = 'none'; // 获取鼠标相对盒子的偏移量 let shiftX = event.clientX - mini.offset().left; let shiftY = event.clientY - mini.offset().top; // 当鼠标移动时 function onMouseMove(event) { event.stopPropagation(); event.preventDefault() moveFlag = true; mini.css({ left: event.pageX - shiftX + 'px', top: event.pageY - shiftY + 'px' }) } // 鼠标提起来 function onMouseUp() { document.body.style.userSelect = 'auto'; moveFlag = false; $(document).off('mousemove', onMouseMove); $(document).off('mouseup', onMouseUp); } $(document).on('mousemove', onMouseMove); $(document).on('mouseup', onMouseUp); }) const hr = $("
") container.append(hr) $("body").append(container) $("body").append(mini) } const showSponsor = () => { sponsorElement = $("
") sponsorElement.addClass('container-sponsor') $(".popup").append(sponsorElement) sponsorElement.append("
二维码是自愿捐赠!插件完全免费,但是依然需要一台服务器来处理数据。
") sponsorElement.append("如果您觉得它对您有所帮助,您可以选择自愿捐赠支持它。

") sponsorElement.append("PS: 所有捐赠将用于维护免费插件运行
") sponsorElement.append("zfb ") sponsorElement.append("wx") sponsorElement.scrollTop(sponsorElement[0].scrollHeight) } const showStatement = () => { statementElement = $("
") statementElement.addClass('container-text') $(".popup").append(statementElement) statementElement.append("

成都文理学院刷课助手 使用说明



") statementElement.append("1. 您使用本插件,即表示您同意本使用条款;如果您不同意,请勿使用本插件。
") statementElement.append("2. 此脚本仅用于学习研究,您必须在下载后24小时内将所有内容从您的计算机或手机或任何存储设备中完全删除,若违反规定引起任何事件本人对此均不负责。
") statementElement.append("3. 请勿将此脚本用于任何商业或非法目的,若违反规定请自行对此负责。
") statementElement.append("4. 本人对此脚本引发的问题概不负责,包括但不限于由脚本错误引起的任何损失和损害(如封禁、限制等)。
") statementElement.append("5. 若有信息功能侵犯到您的权益,请及时联系作者。
") statementElement.append("6. 任何以任何方式查看此脚本的人或直接或间接使用此脚本的使用者都应仔细阅读此条款。
") statementElement.append("7. 本人保留随时更改或补充此条款的权利,一旦您使用或复制或修改了此脚本,即视为您已接受此免责条款。
") statementElement.scrollTop(statementElement[0].scrollHeight) } const showClassOption = () => { containerTextElement = $("
") containerTextElement.addClass('container-text') $(".popup").append(containerTextElement) addText("

提示1

:如果开启了系统代理,要先关闭!") addText("

提示2

:本脚本仅支持PC端,如果不起作用,点油猴图标看是否有提示 \"Please enable developer mode...\",若有,点击查看 油猴插件不能使用") addText("

提示3

:安装过老版本的需要把老版本删除或者禁用。") addText("

提示4

:因不同浏览器的优化策略问题,如果发现学时没变,看视频时请将浏览器置于前台运行
") addText("启动成功...") } const showExamOption = () => { examTextElement = $("
") examTextElement.addClass('container-exam') $(".popup").append(examTextElement) examTextElement.append("

提示1

:如果开启了系统代理,要先关闭!
") examTextElement.append("

提示2

:本脚本仅支持PC端,如果不起作用,点油猴图标看是否有提示 \"Please enable developer mode...\",若有,点击查看 油猴插件不能使用
") examTextElement.append("

提示3

:安装过老版本的需要把老版本删除或者禁用。
") examTextElement.append("

提示4

:对接的是抖音豆包,因为是AI,所以不能保证完全正确,分数高低与作者无关,如果有所担心可在搜完后再自己手动搜一遍
") examTextElement.append("启动成功...

") endpoint_id = GM_getValue("endpoint_id", "") apikey = GM_getValue("apikey", "") let date = new Date(); date.setTime(date.getTime() + (365 * 24 * 60 * 60 * 1000)); examTextElement.append("搜题配置:点击链接 👉 视频教程 | 获取搜题接入点ID和API Key
") let endpointDiv = $("
") endpointDiv.append("接入点ID:") let endpointInput = $("") endpointInput.on("keyup", e=>{ endpoint_id = e.target.value GM_setValue("endpoint_id", endpoint_id) }) endpointDiv.append(endpointInput) let apikeyDiv = $("
") apikeyDiv.append("API Key: ") let apikeyInput = $("") apikeyInput.on("keyup", e=>{ apikey = e.target.value GM_setValue("apikey", apikey) }) apikeyDiv.append(apikeyInput) examTextElement.append(endpointDiv) examTextElement.append(apikeyDiv) let startBtn = $("") let stopBtn = $("") let saveBtn = $("") examTextElement.append(saveBtn) examTextElement.append(startBtn) examTextElement.append(stopBtn) examCurrent = parseInt($(".topic-head.on").text()) - 1 examTextElement.append("") setExamStatus("已停止。搜题将从当前题开始"); if ($("#startArea").length == 1){ setExamStatus("等待答题..."); } if ($(".courseexam-list").find(".time").text().includes("已交卷")) { setExamStatus("已交卷,不可继续答题"); } saveBtn.on("click", ()=>{ endpointInput[0].value = endpointInput[0].value.trim() apikeyInput[0].value = apikeyInput[0].value.trim() GM_setValue("endpoint_id", endpointInput[0].value) GM_setValue("apikey", apikeyInput[0].value) setExamStatus("保存成功!"); }) startBtn.on("click",async ()=>{ if (startFlag) return; startFlag = true; examCurrent = parseInt($(".topic-head.on").text()) - 1 let n = $(".courseexamcon-intro").find("ul").children("li").length; for (; examCurrent < n; examCurrent++) { if (!startFlag) break; let tab = $("#topic-tab-" + examCurrent) setExamStatus("进行中...正在搜索第 " + ( examCurrent + 1 ) + " 题") await pause(1) // 1 单选 2 多选 3 判断 let type = parseInt(tab.find(".courseexamcon-main").data("type")) if ([1, 2, 3].includes(type)){ let question = tab.find(".courseexamcon-main")[0].innerText.replaceAll("\n.\n", ".") let answer = await getAnswer(question) answer = answer.match(/[a-zA-Z]+/)[0]; setExamStatus("第 "+ (examCurrent + 1) +" 题答案:" + answer) switch (type) { case 1: case 3: tab.find("input[value='"+answer.toUpperCase()+"']").click() break; case 2: for (let item of answer) { tab.find("input[value='"+item.toUpperCase()+"']").click() } break; } }else{ setExamStatus("未添加该题型,跳过...") } await pause(3) let btn = tab.find("input[value='保存修改']") if (btn.css("display") == "none"){ tab.find("input[value='继续下一题']").click() }else{ btn.click() $(".courseexamcon-intro").find("ul").children("li")[examCurrent + 1].querySelector("a").click() } } startFlag = false setExamStatus("已停止。下次搜题将从当前题开始"); }) stopBtn.on("click", ()=>{ startFlag = false setExamStatus("已停止。下次搜题将从当前题开始") }) } const setExamStatus = text => { $("#examStatus").text("当前状态:"+text) } // 添加样式 const addStyle = () => { const style = $("") style.prop('type', 'text/css') style.html( ` .mini { position: fixed; top: 50px; left: 150px; width: 50px; height: 50px; display: none; z-index: 99999999999999999; background: #bb241d; color: white; border-radius: 50%; cursor: pointer; align-items: center; justify-content: center; box-shadow: rgba(0, 0, 0, 0.5) 0px 0px 8px 2px; } .popup { position: fixed; top: 50px; left: 150px; width: 540px; font: 14px Menlo, Monaco, Consolas, "Courier New", monospace; z-index: 9999999999999999999999; background-color: #fff; box-shadow: 0 0 5px 1px rgba(0, 0, 0, .3); padding: 10px; border-radius: 5px; } .popup h4{ display: inline-block; } .popup b{ color: red; } .popup a{ color: blue; } .container-header { height: 30px; cursor: move; line-height: 30px; display: flex; justify-content: space-between; } .container-header button{ margin-left: 10px; border: none; background: none; cursor: pointer; border-bottom: 1px solid; } .container-header button:hover{ color: red; } .container-text, .container-exam { margin-top: 10px; max-height: 250px; min-height: 30px; overflow: auto; } .container-exam { max-height: 300px; } .container-sponsor { max-height: 400px; } .container-exam div{ margin: 10px 0; } .container-exam input{ border: 1px solid #000000; width: 400px; padding: 3px; padding-left: 5px; border-radius: 3px; } .container-exam button{ color: red; padding: 3px 10px; background: #ba251e; color: white; border-radius: 3px; cursor: pointer; margin: 10px 10px 10px 0; border: none; } .container-exam button:hover{ background: pink; } ` ) $('body').append(style); } // 添加交互文本 const addText = text => { containerTextElement.append(text + "
") containerTextElement.scrollTop(containerTextElement[0].scrollHeight) } // 暂停函数 function pause(start, end = undefined) { let delay = start; if (end) { delay = Math.floor(Math.random() * (end - start)) + start; addText(`等待 ${delay} 秒后继续...`); } return new Promise(resolve => { setTimeout(() => { resolve(); }, delay * 1000); // 将秒转换为毫秒 }); } const getAnswer = (question) => { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "POST", url: "https://ark.cn-beijing.volces.com/api/v3/chat/completions", data: JSON.stringify({ "model": endpoint_id, "messages": [ { "role": "user", "content": "只说选项号,不要说理由。\n" + question } ] }), headers: { "Authorization": "Bearer " + apikey, "Content-Type": "application/json", }, responseType: "json", onload: function (response) { if (response.status == 401) { setExamStatus("接口错误!401"); } else if (response.status == 200) { try { var answer = response.response["choices"][0].message.content; return resolve(answer); } catch (e) { setExamStatus("异常捕获:接口错误!"); } } else { setExamStatus("接口错误!"); } } }); }) } // 初始化程序 const init = async () => { addContainer() addStyle() showClassOption() showExamOption() showStatement() showSponsor() } function FirstUse(){ var fisrtUse = GM_getValue("fisrtUse", true); if (fisrtUse) { var mzsm = prompt("成都文理学院刷课助手|自动刷课|考试自动答题\n若要使用,请阅读并同意以下免责条款。\n\n \ 1. 此脚本仅用于学习研究,您必须在下载后24小时内将所有内容从您的计算机或手机或任何存储设备中完全删除,若违反规定引起任何事件本人对此均不负责。\n \ 2. 请勿将此脚本用于任何商业或非法目的,若违反规定请自行对此负责。\n \ 3. 本人对此脚本引发的问题概不负责,包括但不限于由脚本错误引起的任何损失和损害(如封禁、限制等)。\n \ 4. 若有信息功能侵犯到您的权益,请及时联系作者。\n \ 5. 任何以任何方式查看此脚本的人或直接或间接使用此脚本的使用者都应仔细阅读此条款。\n \ 6. 本人保留随时更改或补充此条款的权利,一旦您使用或复制或修改了此脚本,即视为您已接受此免责条款。\n\n \ 若您同意以上内容,请输入“我已阅读并同意以上内容” 然后开始使用。", ""); if (mzsm == "我已阅读并同意以上内容") { GM_setValue("fisrtUse", false); return false; } else { alert("免责条款未同意,脚本停止运行。\n若不想使用,请自行禁用脚本,以免每个页面都弹出该提示。"); return true; } } } function matchIcon() { let iconLink = document.querySelector("link[rel='shortcut icon']"); return iconLink && /yinghua|canghui|gyxy|ruren|zjxkeji|yuncanjykeji/.test(iconLink.getAttribute("href")); } // 运行程序 (function () { 'use strict'; if (!matchIcon()) return; if (FirstUse()) return; window.addEventListener("load", async function (){ await init() // await test() if (window.location.href.includes("/node")) { $(".classTabBtn").click() getCurrent() addText("初始化完成,可以解放双手了;为了更像人为点击,将会延时一段时间再播放
") await pause(5, 10) checkCaptchaTimer = setInterval(playVideo, 1000); }else if (window.location.href.includes("/exam")){ $(".examTab1").click() $(".minimize").click() }else{ $(".classTabBtn").click() addText("请点进课程内容,进行学习...
") } }); })();