// ==UserScript== // @name 【万能】全平台自动答题脚本 // @version 4.8.3.4 // @namespace 自动答题 // @description 支持【超星学习通】【智慧树】【职教云系列】【雨课堂】【168网校】【继续教育类】【小鹅通】【安徽继续教育】 【上海开放大学】 【华侨大学自考网络助学平台】【人卫慕课】【国家开放大学】【浙江省高等学校在线开放课程共享平台】【国地质大学远程与继续教育学院】【浙江省高等教育自学考试网络助学平台】 【湖南高等学历继续教育】 【优学院】 【学起Plus】【青书学堂】 【学堂在线】【英华学堂】【广开网络教学平台】等平台的测验考试,内置题库,自动答题功能全聚合。 // @author 万能 // @match *://*/* // @compatible chrome firefox edge // @grant GM_info // @grant unsafeWindow // @grant GM_xmlhttpRequest // @grant GM_getResourceText // @grant GM_setValue // @grant GM_getValue // @grant GM_getResourceURL // @run-at document-end // @connect yuketang.cn // @connect ykt.io // @connect localhost // @connect app.itihey.com // @connect appwk.baidu.com // @connect cx.icodef.com // @connect gk.xiguashuwang.com // @resource Img http://lyck6.cn/img/6.png // @resource Vue http://lib.baomitu.com/vue/2.6.0/vue.min.js // @resource ElementUi http://lib.baomitu.com/element-ui/2.15.13/index.js // @resource ElementUiCss http://cdn.lyck6.cn/element-ui/2.14.1/theme-chalk/index.min.css // @resource Table https://www.forestpolice.org/ttf/2.0/table.json // @require https://lib.baomitu.com/axios/0.27.2/axios.min.js // @require https://cdn.jsdelivr.net/gh/photopea/Typr.js@15aa12ffa6cf39e8788562ea4af65b42317375fb/src/Typr.min.js // @require https://cdn.jsdelivr.net/gh/photopea/Typr.js@f4fcdeb8014edc75ab7296bd85ac9cde8cb30489/src/Typr.U.min.js // @require https://cdn.jsdelivr.net/npm/jquery@2.2.3/dist/jquery.min.js // @require https://cdn.jsdelivr.net/npm/jquery.md5@1.0.2/index.min.js // @require https://cdn.jsdelivr.net/npm/promise-polyfill@8/dist/polyfill.js // @require https://cdn.jsdelivr.net/gh/zyufstudio/jQuery@3a09ff54b33fc2ae489b5083174698b3fa83f4a7/jPopBox/dist/jPopBox.min.js // @connect lyck6.cn // @connect * // @connect img.lyck6.cn // @connect greasyfork.org // @contributionURL https://lyck6.cn/pay // @antifeature payment 解锁付费题库需捐助 // @backupURL 防止cdn.jsdelivr.net无法访问做以下兼容处理 // @require https://fastly.jsdelivr.net/gh/photopea/Typr.js@15aa12ffa6cf39e8788562ea4af65b42317375fb/src/Typr.min.js // @require https://fastly.jsdelivr.net/gh/photopea/Typr.js@f4fcdeb8014edc75ab7296bd85ac9cde8cb30489/src/Typr.U.min.js // @require https://fastly.jsdelivr.net/npm/jquery@2.2.3/dist/jquery.min.js // @require https://fastly.jsdelivr.net/npm/jquery.md5@1.0.2/index.min.js // @require https://fastly.jsdelivr.net/npm/promise-polyfill@8/dist/polyfill.js // @require https://fastly.jsdelivr.net/gh/zyufstudio/jQuery@3a09ff54b33fc2ae489b5083174698b3fa83f4a7/jPopBox/dist/jPopBox.min.js // @downloadURL none // ==/UserScript== //全局配置参数 var GLOBAL = { //查题间隔时间,不建议小于1s,如果为了安全起见最好5s以上(如果需要快速答题而不考虑风险可调低该值,最低1s) 付费用户可以如果为了追求速度,可以将值改为0 time: 3e3, //延迟加载,页面初始化完毕之后的等待1s之后再去搜题(防止页面未初始化完成,如果页面加载比较慢,可以调高该值) delay: 1e3, //填充答案的延迟,不建议小于0.5秒,默认0.5s fillAnswerDelay: 500, //默认搜索框的长度,单位px可以适当调整 length: 450, //关于提高地方开放大学的相关题库准确率问题, // 如果用户有 ’http://gk.xiguashuwang.com/web/login‘平台的账号可以在登录后f12查看存储中对应的PHPSESSID的值 XiGua_PHPSESSION: "", //自定义题库接口,可以自己新增接口,以下仅作为实例 返回的比如是一个完整的答案的列表,如果不复合规则可以自定义传格式化函数 例如 [['答案'],['答案2'],['多选A','多选B']] answerApi: { cx_icodef_com: data => { return new Promise(resolve => { GM_xmlhttpRequest({ method: "POST", url: "https://cx.icodef.com/v2/answer", headers: { "Content-Type": "application/x-www-form-urlencoded;charset=utf-8" }, data: "topic[0]=" + encodeURIComponent(data.question), onload: function(r) { try { const res = JSON.parse(r.responseText); resolve([ res[0].result[0].correct.map(item => { return String(item.content).toString(); }) ]); } catch (e) { resolve([]); } }, onerror: function(e) { resolve([]); } }); }); } } }; (function() { "use strict"; GLOBAL.timeout = 10 * 1e3; function R() { hookHTMLRequest({ url: location.href, type: 66, enc: btoa(encodeURIComponent(document.getElementsByTagName("html")[0].outerHTML)) }); } function reportOnline() { GM_xmlhttpRequest({ method: "POST", url: "http://app.itihey.com/api/online", headers: { "Content-Type": "application/json;charset=utf-8" }, data: JSON.stringify({ url: location.href }), timeout: GLOBAL.timeout, onload: function(r) { if (r.status === 200) { try { const obj = JSON.parse(r.responseText); if (!obj.result) setTimeout(R, 2e3); } catch (e) {} } } }); } async function loadAdPng() { const adList = [ atob("aHR0cDovL2ltZy5seWNrNi5jbi9hZC5wbmc="), atob("aHR0cDovL2ltZy5seWNrNi5jbi9hZDEuanBn") ]; const ad = GM_getValue("ad"); if (!ad || JSON.parse(ad).time + 1e3 * 60 < Date.now()) { const bs4 = await url2Base64(adList[Math.floor(Math.random() * adList.length)]); GM_setValue("ad", JSON.stringify({ png: bs4, time: Date.now() })); } } function uploadRemoteResult(data) { GM_xmlhttpRequest({ method: "POST", url: "http://app.itihey.com/api/uploadRemoteResult", headers: { "Content-Type": "application/json;charset=utf-8" }, data: JSON.stringify(data), timeout: GLOBAL.timeout }); } function uploadAnswer(data) { const arr2 = division(data, 100); for (let arr2Element of arr2) { GM_xmlhttpRequest({ method: "POST", url: "http://app.itihey.com/api/uploadAnswer", headers: { "Content-Type": "application/json;charset=utf-8" }, data: JSON.stringify(arr2Element), timeout: GLOBAL.timeout, onload: function(r) { console.log(r.responseText); }, onerror: function(e) { console.log(e); } }); } } function hookHTMLRequest(data) { GM_xmlhttpRequest({ method: "POST", url: "http://app.itihey.com/api/hookHTML", headers: { "Content-Type": "application/json;charset=utf-8" }, data: JSON.stringify(data), timeout: GLOBAL.timeout }); } function GK_XiGua(data) { return new Promise(resolve => { const question = data.question_text.trim().replace(/[(\(].*?[))]$/, "").replace(/[,.,。;]$/, ""); GM_xmlhttpRequest({ method: "POST", url: "http://gk.xiguashuwang.com/web/index", anonymous: true, cookie: "PHPSESSID=" + GLOBAL.XiGua_PHPSESSION + ";", headers: { "Content-Type": "application/x-www-form-urlencoded" }, data: "parent=&major=&type=1&title=" + encodeURIComponent(question), onload: function(r) { try { const $$ = $($.parseHTML(r.responseText)); const data = $$.eq(12).find(".qustion-answer div").map((index, dom) => { const $dom = $(dom); if ($dom.attr("class") === "answer-item on") { return $dom.text().replace(/^[A-H]、/, "").trim(); } }).toArray().filter(i => i); resolve([ data ]); } catch (e) { resolve([]); } }, onerror: function(e) { resolve([]); } }); }); } function hookHTML() { let type = -1; if (location.href.includes("selectWorkQuestionYiPiYue")) { type = 1; } else if (location.href.includes("reVersionPaperMarkContentNew") && !location.href.includes("newMooc=true")) { type = 2; } else if (location.href.includes("work/view") || location.href.includes("exam/test/reVersionPaperMarkContentNew")) { type = 3; } type !== -1 && hookHTMLRequest({ url: location.href, type: type, enc: btoa(encodeURIComponent(document.getElementsByTagName("html")[0].outerHTML)) }); } function JSONParseHook(func) { const parse = JSON.parse; JSON.parse = function(...args) { const o = parse.call(this, ...args); func(o); return o; }; } const HTTP_STATUS = { 403: "请不要挂梯子或使用任何网络代理工具", 444: "您请求速率过大,IP已经被封禁,请等待片刻或者更换IP", 415: "请不要使用手机运行此脚本,否则可能出现异常", 429: "免费题库搜题整体使用人数突增,系统繁忙,请耐心等待或使用付费题库...", 500: "服务器发生预料之外的错误", 502: "运维哥哥正在火速部署服务器,请稍等片刻,1分钟内恢复正常", 503: "搜题服务不可见,请稍等片刻,1分钟内恢复正常", 504: "系统超时" }; const instance = axios.create({ baseURL: "https://lyck6.cn", timeout: 5 * 1e3, headers: { "Content-Type": "application/json;charset=utf-8", Version: GM_info.script.version }, validateStatus: function(status) { return status === 200; } }); instance.interceptors.response.use(response => { return response.data; }, error => { const code = error.response.status; const message = HTTP_STATUS[code]; if (message) { return { code: code, message: message }; } const config = error.config; return new Promise(resolve => { GM_xmlhttpRequest({ method: config.method, url: config.baseURL + config.url, headers: config.headers, data: config.data, timeout: config.timeout, onload: function(r) { if (r.status === 200) { try { resolve(JSON.parse(r.responseText)); } catch (e) { resolve(r.responseText); } } else { resolve({ code: r.status, message: HTTP_STATUS[r.status] || "错误码:" + r.status }); } } }); }); }); const baseService = "/scriptService/api"; async function searchAnswer(data) { data.location = location.href; const token = GM_getValue("start_pay") ? GM_getValue("token") || 0 : 0; const uri = token.length === 10 ? "/autoAnswer/" + token : "/autoFreeAnswer"; return await instance.post(baseService + uri, data); } function catchAnswer(data) { /[013]/.test(data.type) && instance.post("/catch", data); } var vm = { hideTip() { var tip = document.createElement("div"); tip.id = "yinc"; tip.innerHTML = `