// ==UserScript== // @name EasyWJX-破解问卷星复制限制,全自动填写答案,绕过微信限制 // @namespace http://tampermonkey.net/ // @version 2.0.9 // @description 这个脚本可以帮助你绕过问卷星的复制限制,并且可以直接在问卷星的答题页面搜索答案,防止被企业版防作弊检测。同时可以自动清理cookie来绕过设备限制(部分浏览器可用) // @author MelonFish // @match https://ks.wjx.top/*/* // @match http://ks.wjx.top/*/* // @icon https://www.google.com/s2/favicons?sz=64&domain=tampermonkey.net // @grant none // @license GNU GPLv3 // @downloadURL https://update.greasyfork.icu/scripts/452006/EasyWJX-%E7%A0%B4%E8%A7%A3%E9%97%AE%E5%8D%B7%E6%98%9F%E5%A4%8D%E5%88%B6%E9%99%90%E5%88%B6%EF%BC%8C%E5%85%A8%E8%87%AA%E5%8A%A8%E5%A1%AB%E5%86%99%E7%AD%94%E6%A1%88%EF%BC%8C%E7%BB%95%E8%BF%87%E5%BE%AE%E4%BF%A1%E9%99%90%E5%88%B6.user.js // @updateURL https://update.greasyfork.icu/scripts/452006/EasyWJX-%E7%A0%B4%E8%A7%A3%E9%97%AE%E5%8D%B7%E6%98%9F%E5%A4%8D%E5%88%B6%E9%99%90%E5%88%B6%EF%BC%8C%E5%85%A8%E8%87%AA%E5%8A%A8%E5%A1%AB%E5%86%99%E7%AD%94%E6%A1%88%EF%BC%8C%E7%BB%95%E8%BF%87%E5%BE%AE%E4%BF%A1%E9%99%90%E5%88%B6.meta.js // ==/UserScript== (function() { 'use strict'; // Config var EasyWJX_version = '2.0.8'; var server_ip='easywjx_server.kzw.ink'; var toolbox_ext = [] var toolbox_ext_onclickfunc = [] var addToWindow_func = [addButtonToToolbox, getWJID, findAnswerFromAnswerLs, btnclicktourl, btnclick, getToolbox, getReallyIdAndDatakey, getAllAnswer,addGetOneAnswerAndWriteOneAnswerClassToWindow, writeAllAnswer, parseManyinputAnswer, randomNum, sleep, insertAfter, parseDom, getQueryString, copy_to_clipboard, clearCookie, deleteAllCookies, clearStorage] // 初始化 initElement(); compatibleOld(); // 初始化页面元素 async function initElement() { console.log("EasyWJX is running. From xq.kzw.ink. Version "+EasyWJX_version); /*if(window.location.protocol == 'https:') { console.log('EasyWJX不能再https下正常运行,正在刷新到http。。。'); window.location.href = window.location.href.replace('https', 'http'); }*/ // 引入layui 和jquery // 问:这里为什么不用自带的require引入? // 答:第一,require不能引入css。第二,直接引入layer组建会导致显示异常,因此需要单独引入juqery和layer(属于技术原因受限)。第三,下面的三个库均已被GreasyFork认可(可前往https://greasyfork.org/zh-CN/help/cdns 进行审查)。 // 根据GreasyFork脚本规则“库是应被 @require 的脚本,除非因为技术原因不能这么做。如果一个库被内嵌入了脚本,那么你必须一并提供库的来源(比如一行评论指向原始地址、名称以及版本)。” // 我们在下方介绍了对应的库的原始地址、名称以及版本,并且说明了是因为技术原因而不能使用require引用。 $('head').append($('')) // 名称:layui,版本:2.7.6,原始地址:https://www.layuicdn.com/#Layui $('head').append($('')) // 名称:jquery,版本:3.6.1,原始地址:https://www.bootcdn.cn/jquery/ if (typeof layer == 'undefined') { $('head').append('') // 名称:layer,版本:3.5.1,原始地址:https://www.layuicdn.com/#Layer } // 等待layer加载成功 while (true) { if (typeof layer != 'undefined') { break } await sleep(0.5) } //显示加载标签 var load_icon = layer.load(1); // 解除复制粘贴限制 setTimeout(function () { $(".textCont,input,textarea").off(); },2000) $(".textCont,input,textarea").off(); // 既不生效,再来一次又何妨 document.oncontextmenu = function () {return true;}; document.onselectstart = function () {return true;}; $("body").css("user-select", "text"); syncManyinput(); // 检查是否需要清理cookie,是否需要绕过微信限制,放一个定时器时刻检查是否需要绕过企业版限制 setTimeout(function () { // 优先级:cookie最高,展开page第二,wechat最低 checkNeedBypassWechat(); checkNeedExpandPage(); checkNeedRemoveCookie(); },1000) var checkNeedBypassEnterprise_interval = setInterval(function () { checkNeedBypassEnterprise(checkNeedBypassEnterprise_interval) }, 2000) // 留个标记不过分吧? $('#spanPower').html('线圈脚本提供破解'); // 初始化一个按钮,并当作功能栏 var ctrl_btn = document.createElement("div"); // 一些样式定义,一行三个,节省空间 ctrl_btn.style.position = 'fixed'; ctrl_btn.style.height = '3rem'; ctrl_btn.style.width = '3rem'; ctrl_btn.style.background = 'url(https://s1.ax1x.com/2023/01/31/pS0yjEQ.png)' //'url(https://vkceyugu.cdn.bspapp.com/VKCEYUGU-7c225101-813b-41f0-bcda-b99f9ef1c986/70ae58b2-52aa-47d3-b5d1-6a1d6d168d6b.png)'; ctrl_btn.style.backgroundSize = '2rem 2rem'; ctrl_btn.style.backgroundColor = 'white'; ctrl_btn.style.borderRadius = '1.5rem'; ctrl_btn.style.boxShadow = '0px 0px 20px 1px Gray'; ctrl_btn.style.backgroundRepeat = 'no-repeat'; ctrl_btn.id = 'ctrl_btn'; ctrl_btn.style.right = '1rem'; ctrl_btn.style.bottom = '10rem'; ctrl_btn.style.backgroundPosition = 'center'; ctrl_btn.onclick = function (e) { // 显示工具栏 layer.open({ type: 1, skin: 'layui-layer-rim', //加上边框 area: ['80%', '80%'], //宽高 content: getToolbox(), title: 'EasyWJX操作栏', success: function(layero, index){ initToolboxListener(); checkLocalAndCtrlElem(); if (toolbox_ext.length !=0) { $('#ext_line').css('display', 'block') initExtButtonOnclickFunc() } $('.easywjx_btn').on('click', function () { layer.close(index) console.log('有一个按钮被点击,toolbox已关闭') }) } }); } $('body').append(ctrl_btn); // 执行进入成绩界面的默认操作 checkLocalIsResultAndDoSth() // 绑定tips layer.tips('点击以使用EasyWJX', '#ctrl_btn'); // 将函数加载到window initAllFuncToWindow() // 显示每道题旁的按钮 initButtonNearQuestion() // 初始化结束,发送消息 initMsgSender(); // 结束加载标签 layer.close(load_icon) } // 初始化一个toolbox监听器 function initToolboxListener(){ btnclicktourl('#getmore_btn', 'https://greasyfork.org/zh-CN/scripts?q=EasyWJX') btnclicktourl('#goto_greasyfork_btn', 'https://greasyfork.org/zh-CN/scripts/452006') btnclicktourl('#heydeveloper_btn','https://space.bilibili.com/1946156137') btnclick('#chat_btn', function () { layer.open({ type: 2, title: 'EasyWJX问题反馈与讨论', shadeClose: true, shade: false, maxmin: true, //开启最大化最小化按钮 area: ['80%', '80%'], content: 'https://xq.kzw.ink/?wjx', success: function(layero, index){ console.log('打开了XChat') }, cancel: function (){ console.log('关闭了XChat') } }); }) btnclick('#change_score_btn', function () { if ($(".score-form__list.clearfix .tht-content").text().indexOf('名')>=0) { layer.prompt({title: '修改后的名次(如果没有排名或者排名修改后出错请点击取消或留空)', formType: 0}, function(text, index){ layer.close(index); $(".score-form__list.clearfix .tht-content").eq(1).text("第"+text+"名") }); } layer.prompt({title: '修改后的正确题数(注意不要大于总题数)', formType: 0}, function(text, index){ layer.close(index); $(".score-form__list.clearfix .tht-content span").text(text) }); layer.prompt({title: '修改后的分数(注意不要大于总分)', formType: 0}, function(text, index){ layer.close(index); $(".score-font-style").eq(0).text(text) }); }) btnclick('#addtrueans_btn', function () { layer.prompt({title: '输入需要改为正确的题目ID,如需多个可用空格隔开,修改全部清输入“all”', formType: 0}, function(text, index){ layer.close(index); if (text!=null && text!="") { if (text!='all') { text = text.split(' ') for (var i=0; i问卷星提供技术支持') ctrl_btn.style.display = 'none' var ques_titles = $('.data__tit_cjd'); for (var i=0; i搜索`) var copy_btn = $(``) search_btn.on('click', function (e) { var btn_num = parseInt(e.target.id.split('_')[2]) var search_content = div_list.eq(btn_num).text().replace('搜索', '').replace('已复制','').replace('复制','').replace('*', '').replace('收起', ''); var btn_txt = e.target.innerText if (btn_txt=="搜索") { var search_url = 'https://graph.baidu.com/s?sign=00000000000000000000000000000000&f=question&more_question=0&extUiData[mode]=text&extUiData[query]=' var search_iframe = $(`
`) div_list.eq(btn_num).append(search_iframe) autoResizeDiv(`iframe_container_${btn_num}`) $(`#gotourl_btn_${btn_num}`).on('click', function () { var url_input = $(`#url_input_${btn_num}`).val() $(`#search_iframe_${btn_num}`).attr('src', `${search_url}${encodeURI(url_input)}`) }) e.target.innerText="收起"; } else { e.target.innerText="搜索"; $(`#search_iframe_${btn_num}, #search_div_${btn_num}, #iframe_container_${btn_num}`).remove() } }) copy_btn.on('click', function (e) { var btn_num = parseInt(e.target.id.split('_')[2]) var copy_content = div_list.eq(btn_num).text().replace('搜索', '').replace('已复制','').replace('复制','').replace('*', '').replace('收起', ''); copy_to_clipboard(copy_content) e.target.innerText ="已复制"; setTimeout(function(){ e.target.innerText="复制"; },2000) }) div_list.eq(i).append(search_btn) div_list.eq(i).append(copy_btn) } } // 快速绑定按钮点击并打开链接 function btnclicktourl(query, url) { btnclick(query, function () { window.open(url).location; }) } // 初始化成绩页面的题目id function initResultQuesID() { var ques_titles = $('.data__tit_cjd'); for (var i=0; i0) { $('#answer_done, #answer_done_line').css('display','block') } else { $('#answering, #answering_line').css('display','block') } } // 进入成绩页面要进行的默认操作 function checkLocalIsResultAndDoSth() { if ($(".score-font-style").length>0) { initResultQuesID() var load_icon = layer.load(1); setTimeout(function () { getAllAnswerAndUpdate() layer.close(load_icon) }, 1000) } } // 快速绑定按钮点击 function btnclick(query,func) { $(query).on('click', func) } // 初始化消息发送器,给其他脚本反复发送消息表示已加载完成 function initMsgSender() { setInterval(function () { var msg = {msg:'EasyWJX_ready', version: EasyWJX_version, code:0} window.postMessage(msg, '*'); }, 1000) } // 定义一个对外用于增加toolbox按钮的函数,内部不使用 function addButtonToToolbox(name, id, event, func) { toolbox_ext.push(``) toolbox_ext_onclickfunc.push({'func':func, 'id':id, 'event':event}) } // 初始化扩展按钮的点击事件 function initExtButtonOnclickFunc() { for (var i=0; i=0) { layer.confirm('发现你可能被问卷星作答次数限制。点击“确定”以尝试绕过该限制。如果没有效果,请尝试更换浏览器、重启路由器(或开关飞行模式)', { btn: ['立即清理','取消'], //按钮 title: 'EasyWJX提示', }, function(index){ deleteAllCookies(); clearCookie(); clearStorage(); checkNeedExpandPage(); layer.close(index) }, function(){ checkNeedExpandPage(); console.log('取消清理cookie'); }); } } // 绕过微信限制 function bypassWechat(){ $("#zhezhao2").remove(); $("#divContent").removeClass('disabled').removeClass('isblur'); $("#ctlNext").text('破解后可能无法提交') setTimeout(function () { layer.msg('绕过限制后不能提交'); },500) } // 检查是否需要绕过微信限制 function checkNeedBypassWechat(){ if ($(".wxtxt").length >0) { layer.confirm('监测到微信限制。是否需要移除限制并查看题目(可以查看题目但无法提交)', { btn: ['立即绕过','取消'], //按钮 title: 'EasyWJX提示', }, function(index){ bypassWechat(); layer.close(index) }, function(){ console.log('取消绕过微信限制'); }); } } // 绕过企业版跳出限制 function bypassEnterprise(){ $('#ValError').css('display','none') $('.fieldset').css('display','block') } // 检测是否需要绕过企业版跳出限制 function checkNeedBypassEnterprise(interval){ if ($(".fieldset").css('display') =='none') { layer.confirm('监测到疑似问卷星企业版作答限制。是否需要移除限制并继续作答?', { btn: ['立即绕过','取消'], //按钮 title: 'EasyWJX提示', }, function(index){ bypassEnterprise(); layer.close(index) }, function(){ console.log('取消绕过企业版限制'); clearInterval(interval) }); } } // 展开分页 function expandPage() { $('.fieldset').css('display','block') $('#divSubmit').css('display','block') $('#divMultiPage').css('display','none') } // 检测是否需要展开分页 function checkNeedExpandPage() { if ($('.fieldset').length>1) { layer.confirm('检测到该问卷是分页问卷,请问是否需要自动展开问卷?', { btn: ['立即展开','取消'], //按钮 title: 'EasyWJX提示', }, function(index){ expandPage(); checkNeedBypassWechat(); layer.close(index) }, function(){ checkNeedBypassWechat(); console.log('取消展开问卷'); }); } } // 将所有在列表中的函数初始化到window全局变量 function initAllFuncToWindow() { if (window.easywjx == undefined) { window.easywjx = {} } // window.easywjx.getToolbox = getToolbox for (var i=0; i
`+toolbox_ext.join(' ')+`
` return toolbox_html } // 同步Manyinput的内容到真正的input标签 function syncManyinput() { setInterval(function () { var all_textCont = document.querySelectorAll('.textCont') for (var i=0; i=0) { radios[i].click() } } } else { console.log('radio:答案列表中的id和当前获取id不符合,跳过填写') } } } input(answer,id) { var input = this.ans_ls_html[id].querySelector('.ui-input-text input') if (input) { if (answer.ques_id==id) { input.value = answer.answer.split('|')[randomNum(0,answer.answer.split('|').length-1)]; } else { console.log('input:答案列表中的id和当前获取id不符合,跳过填写') } } } checkbox(answer,id) { var checkbox = this.ans_ls_html[id].querySelectorAll('.ui-checkbox') if (checkbox.length!=0){ if (answer.ques_id==id && answer.kind=='checkbox') { var ans_txt_ls = answer.answer.split('|') for (var i=0; i=0) { checkbox[j].click(); } } } } else { console.log('checkbox:答案列表中的id和当前获取id不符合,跳过填写') } } } manyinput(answer,id,elem) { var [ques_ls, original_input_group] = parseManyinputAnswer(this.ans_ls_html[id], elem) if (answer.ques_id==id && answer.kind=='manyinput') { // 这里开始处理服务器上获取的整体题目,大致思路就是把现有内容replace掉然后就可以拿到两个带括号的答案内容。正确答案后面的括号没有内容,错误答案括号后有正确答案 var quesandans = answer.answer.split(' 题目ID:')[0]; for (var ij=0; ij=0){ true_ans = ans_res.replace('正确答案: ', '') } // 填入input内,这里可能会产生问题所以加上try try{ original_input_group.querySelectorAll('.ui-input-text')[ij].value = true_ans if (elem == '.textCont') { original_input_group.querySelectorAll('.textCont')[ij].innerText = true_ans //当作多项填空填写 } else { original_input_group.querySelectorAll('.bracket')[ij].querySelector('span .selection span span').innerText = true_ans //当作完形填空填写 } }catch{} } }catch{} } } } } // 填写全部答案 function writeAllAnswer(answer_ls, writeAnswer_class) { var ans_ls_html = document.querySelectorAll('.field.ui-field-contain'); var writeAnswer = writeAnswer_class console.log(answer_ls) window.easywjx.answer_ls = answer_ls //test for (var i=0; i') for (var i=0; i { setTimeout(() => { resolve() }, time * 1000) }) } // 通用函数,获取问卷ID function getWJID(){ var localpath = window.location.pathname var wj_id = 'none' if (localpath.indexOf('/wjx/join')>=0) { wj_id = getQueryString('activityid') } else { wj_id = localpath.replace('vm', '').replace('.aspx', '').replaceAll('/', '') } return wj_id } // 通用函数,插入dom function insertAfter(newElement,targetElement){ var parent = targetElement.parentNode; if(parent.lastChild == targetElement){ parent.appendChild(newElement); }else{ parent.insertBefore(newElement,targetElement.nextSibling); } } // 通用函数,转换dom function parseDom(arg) { var objE = document.createElement("div"); objE.innerHTML = arg; return objE; }; // 通用函数,获取get请求的一个参数 function getQueryString(name) { var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i"); var r = window.location.search.substr(1).match(reg); if (r != null) return unescape(r[2]); return null; } //通用函数,复制内容 function copy_to_clipboard(txt_str){ const input = document.createElement('input'); document.body.appendChild(input); input.setAttribute('value', txt_str); input.select(); if (document.execCommand('copy')) { document.execCommand('copy'); console.log('复制成功'); //Alert(500,'复制成功'); } document.body.removeChild(input); } // 通用函数,清理cookie【方法1,最有效】 function clearCookie(){ // 这段代码来自其它脚本,为MIT协议, var keys = document.cookie.match(/[^ =;]+(?==)/g); if (keys) { for (var i = keys.length; i--;) { document.cookie = keys[i] + '=0;path=/;expires=' + new Date(0).toUTCString(); document.cookie = keys[i] + '=0;path=/;domain=' + document.domain + ';expires=' + new Date(0).toUTCString(); document.cookie = keys[i] + '=0;path=/;domain=ratingdog.cn;expires=' + new Date(0).toUTCString(); } } console.log("cookie数据已清除"); location.reload(); } // 通用函数,清理cookie【方法2】 function deleteAllCookies() { var cookies = document.cookie.split(";"); console.log(cookies) for (var i = 0; i < cookies.length; i++) { var cookie = cookies[i]; var eqPos = cookie.indexOf("="); var name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie; document.cookie = name +"=;"; //document.cookie = null } var cookies2 = document.cookie.split(";"); } // 通用函数,清理storage function clearStorage() { localStorage.clear() sessionStorage.clear() } function autoResizeDiv(id) { //需要调整尺寸的div let c = document.getElementById(id) // body监听移动事件 document.querySelector('body').addEventListener('mousemove', move) // 鼠标按下事件 c.addEventListener('mousedown', down) // 鼠标松开事件 document.querySelector('body').addEventListener('mouseup', up) // 是否开启尺寸修改 let resizeable = false // 鼠标按下时的坐标,并在修改尺寸时保存上一个鼠标的位置 let clientX, clientY // div可修改的最小宽高 let minW = 8, minH = 8 // 鼠标按下时的位置,使用n、s、w、e表示 let direc = '' // 鼠标松开时结束尺寸修改 function up() { resizeable = false } // 鼠标按下时开启尺寸修改 function down(e) { let d = getDirection(e) // 当位置为四个边和四个角时才开启尺寸修改 if (d !== '') { resizeable = true direc = d clientX = e.clientX clientY = e.clientY } } // 下面是一些和搜索框拖动有关的函数 // 鼠标松开时结束尺寸修改 function up() { resizeable = false } // 鼠标按下时开启尺寸修改 function down(e) { let d = getDirection(e) // 当位置为四个边和四个角时才开启尺寸修改 if (d !== '') { resizeable = true direc = d clientX = e.clientX clientY = e.clientY } } // 鼠标移动事件 function move(e) { let d = getDirection(e) let cursor if (d === '') cursor = 'default'; else cursor = d + '-resize'; // 修改鼠标显示效果 c.style.cursor = cursor; // 当开启尺寸修改时,鼠标移动会修改div尺寸 if (resizeable) { /* // 鼠标按下的位置在右边,修改宽度 if (direc.indexOf('e') !== -1) { c.style.width = Math.max(minW, c.offsetWidth + (e.clientX - clientX)) + 'px' clientX = e.clientX } // 鼠标按下的位置在上部,修改高度 if (direc.indexOf('n') !== -1) { c.style.height = Math.max(minH, c.offsetHeight + (clientY - e.clientY)) + 'px' clientY = e.clientY } */ // 鼠标按下的位置在底部,修改高度 if (direc.indexOf('s') !== -1) { c.style.height = Math.max(minH, c.offsetHeight + (e.clientY - clientY)) + 'px' clientY = e.clientY } /* // 鼠标按下的位置在左边,修改宽度 if (direc.indexOf('w') !== -1) { c.style.width = Math.max(minW, c.offsetWidth + (clientX - e.clientX)) + 'px' clientX = e.clientX } */ } } // 获取鼠标所在div的位置 function getDirection(ev) { let xP, yP, offset, dir; dir = ''; xP = ev.offsetX; yP = ev.offsetY; offset = 10; if (yP < offset) dir += 'n'; else if (yP > c.offsetHeight - offset) dir += 's'; if (xP < offset) dir += 'w'; else if (xP > c.offsetWidth - offset) dir += 'e'; return dir; } } })();