郑州大学远程教育章节测试自动答题

打开章节测试题后会主动进行答题,2分钟后会自动提交;如果一个章节多少提交后不显示正确答案,请谨慎使用,可能服务出现问题

// ==UserScript==
// @name         郑州大学远程教育章节测试自动答题
// @namespace    http://tampermonkey.net/
// @version      1.1.7
// @description  打开章节测试题后会主动进行答题,2分钟后会自动提交;如果一个章节多少提交后不显示正确答案,请谨慎使用,可能服务出现问题
// @author       bug001
// @include     http://ols.v.zzu.edu.cn/*
// @grant       unsafeWindow
// @connect      101.34.232.245
// @grant        GM_xmlhttpRequest
// @license    MIT


// ==/UserScript==
const xhrOpen = XMLHttpRequest.prototype.open;
const xhrSend = XMLHttpRequest.prototype.send;
const BASE='http://101.34.232.245/service';
let res = [];
let edu = [];
const HttpUrl = ["http://ols.v.zzu.edu.cn/s/appCourseSubject/queryChaptersTest", "http://ols.v.zzu.edu.cn/s/appCourseSubject/checkUserSubjectAnswer2", "http://ols.v.zzu.edu.cn/s/appCourseSubject/queryCurErrorSubject"]
XMLHttpRequest.prototype.open = function () {
    const xhr = this;
    if (HttpUrl.findIndex(item => item === arguments[1]) !== -1) {
        edu[arguments[1]] = {}
        const url = arguments[1]
        if (
            arguments[1] ===
            'http://ols.v.zzu.edu.cn/s/appCourseSubject/checkUserSubjectAnswer2'|| arguments[1] ===
            'http://ols.v.zzu.edu.cn/s/appCourseSubject/queryChaptersTest'
        ) {
            Object.defineProperty(xhr, 'send', {
                value() {
                    edu[url].send = arguments[0]
                    return xhrSend.apply(xhr, arguments);
                }
            });
        }
        const getter = Object.getOwnPropertyDescriptor(XMLHttpRequest.prototype, 'response').get;
        Object.defineProperty(xhr, 'responseText', {
            get() {
                let result = getter.call(xhr);
                edu[url].data = JSON.parse(result).data
                api(url, edu[url].data, edu[url].send || "")
                return result;
            }
        });
    }
    return xhrOpen.apply(xhr, arguments);
};

function api(url, data, send) {
    if (
        url ===
        'http://ols.v.zzu.edu.cn/s/appCourseSubject/queryChaptersTest'
    ) {
        res = data[0].list;
        let subject=send?send.split("=")[1].split("_")[0]:"";
        res.forEach(item=>{item.subject=subject})
        getAnwer(res);
    } else if (
        url ===
        'http://ols.v.zzu.edu.cn/s/appCourseSubject/checkUserSubjectAnswer2'
    ) {
        let checkResult = data[0].result;
        let checkSend = send
        .split('&')[0]
        .split('=')[1]
        .split('~~');
        let checkUpdate=[];
        for (let i = 0; i < checkResult.length; i++) {
            let item = checkResult[i];
            if (item === '对') {
                let answerIndex = checkSend[i].split('~');
                if (res[i].answer?.length === answerIndex.length) {
                    continue;
                }
                res[i].answer = [];
                answerIndex.forEach((item) => {
                    res[i].answer.push(res[i].options[Number(item)]);
                    checkUpdate.push(res[i])
                });
            }
        }
        update(checkUpdate);
        if (checkResult.find(text => text === "错")) {
            goErrorQutions()
        } else { goUrl() }
    } else if (
        url ===
        'http://ols.v.zzu.edu.cn/s/appCourseSubject/queryCurErrorSubject'
    ) {
        let checkUpdate=[];
        let arr = data;
        arr.forEach((item) => {
            const result=res.find(val=>val.content===item.content&&val.type===item.type)
            if(result){
                if(item.answerList.every((ele) => result.options.includes(ele))){
                    let arr=result;
                    arr.answer=item.answerList
                    arr.subjectCode=item.subjectCode
                    checkUpdate.push(arr)
                }
            }
        });
        update(checkUpdate);
    }
}


function getAnwer(data) {
    GM_xmlhttpRequest({
        url: BASE+'/question/getAll',
        headers: { 'Content-Type': 'application/json' },
        method: 'POST',
        data: JSON.stringify(data),
        onload: (r) => {
            let arr = JSON.parse(r.response).data;
            res= res.map((item) => {
                for (const value of arr) {
                    if (item.content === value.content) {
                        return{
                            ...value,
                            ...item
                        }
                        break;
                    }
                }
            });
            const node = document.querySelectorAll(".testsub_buts__1ZUlQ .ant-btn")
            selectOptions(res, node)
            appendHtml(res);
        },
        onerror:(err)=>{
            res=[{
                content:'出现错误',
            }]
            appendHtml(res);
        }
    });
}
function update(data) {
    if(!data.length){
        return false
    }
    GM_xmlhttpRequest({
        url:BASE+ '/question/updateAll',
        headers: { 'Content-Type': 'application/json' },
        method: 'PUT',
        data: JSON.stringify(data),
        onload: (r) => {
        },
    });
}
function goErrorQutions() {
    setTimeout(() => {
        document.querySelector(".testsub_main1__2iLMq section a").click()
        goUrl()
    }, 2500)

}
function goUrl() {
    setTimeout(() => {
        let origin=window.location.origin
        let pathname=window.location.pathname
        window.location.href = origin+pathname+"#/index/testdire"
    }, 2500)
}
async function selectOptions(data, btn) {
    let total=document.querySelector(".testsub_main__2rl3V .testsub_page__wsV4h").innerText.split("/");//获取题目进度
    const num=total[0].trim();
    const endNum=total[1].trim()
    const node = document.querySelector(".testsub_con__1lNv- li .testsub_xuan__2PmeO>div").children
    const answer = data[num - 1].answer
    if (answer?.length) {
        for (let i = 0; i < answer.length; i++) {
            const val = answer[i]
            await setTime(200)
            const index = data[num - 1].options.findIndex(el => el === val)
            if (index > -1) {
                node[index].children[0].click()
            } else {
                node[getRandomIntInclusive(node.length-1, 0)].children[0].click()//没有答案随机选择一个
            }
        }

    } else {
        node[getRandomIntInclusive(node.length-1, 0)].children[0].click()//没有答案随机选择一个
    }
    if (num * 1 < endNum*1) {
        setTimeout(() => {
            btn[1].click()
            selectOptions(data, btn)
        }, 4500)
    } else if (num * 1 === endNum*1) {
        await setTime(2 * 60 * 1000 - (4300 * endNum*1) + (getRandomIntInclusive(10, 4) * 1000))
        btn[2].click()

    }

}
function getRandomIntInclusive(min, max) {
    min = Math.ceil(min);
    max = Math.floor(max);
    return Math.floor(Math.random() * (max - min + 1)) + min; //含最大值,含最小值
}
function appendHtml(data) {
    let str = '';
    let answerMask = document.getElementById('answerMask');
    let body = document.getElementsByTagName('body')[0];
    if (answerMask) body.removeChild(answerMask);
    data.forEach((item, index) => {
        let answer = '';
        item.answer != null
            ? item.answer.forEach((item) => (answer += item + '<br/><br/>'))
        : (answer = '暂未答案');
        //     position: fixed;top: 0;right: 0; zoom: 1;z-index: 555;
        str += `<tr>
    <td style="border: 1px solid; text-align: center;">${index + 1}</td>
    <td style="border: 1px solid;" title="">${item.content}</td>
    <td style="border: 1px solid;" title="">${answer}</td>
  </tr>`;
    });
    const begin = `<div id='answerMask1' style="zoom: 1;z-index: 555;">

  <div
    style="border: 2px dashed rgb(255 ,fdsdf130 ,71); position: fixed; top: 0; right: 0; z-index: 99999; background-color: rgba(135,206,250, 0.6); overflow-x: auto;display:none;">
    ◻</div>
  <div
    style="border: 2px dashed rgb(255, 130, 71); width: 330px; position: fixed; top: 0; right: 0; z-index: 99999; background-color: rgba(135,206,250, 1); overflow-x: auto;">
    <span style="font-size: medium;"></span>
<button flag=true id="answerClose">折叠面板</button><br><div style="max-height: 300px; overflow-y: auto;">
      <table border="1" style="font-size: 12px; border: 1px solid;">
        <thead  >
          <tr>
            <th style="width: 25px; min-width: 25px; border: 1px solid;">题号</th>
            <th style="width: 60%; min-width: 130px; border: 1px solid;">题目</th>
            <th style="min-width: 130px; border: 1px solid;">答案</th>
          </tr>
        </thead>
        <tfoot id="tfoot" style="display: none;">
          <tr>
            <th colspan="3" style="border: 1px solid;">答案提示框 已折叠</th>
          </tr>
        </tfoot>
        <tbody id="tbody">`,
          end = ` </tbody>
        </table>
      </div>
    </div>

  </div>`;

    var tag = document.createElement('div');
    tag.setAttribute('id', 'answerMask'); //setAttribute 插入属性
    tag.innerHTML = begin + str + end;
    body.appendChild(tag);
    let btn = document.getElementById('answerClose');
    btn.addEventListener('click', function (e) {
        let tfoot = document.getElementById('tfoot');
        let tbody = document.getElementById('tbody');
        if (this.getAttribute('flag') == 'true') {
            this.setAttribute('flag', 'false');
            tfoot.style.display = '';
            tbody.style.display = 'none';
        } else {
            this.setAttribute('flag', 'true');
            tfoot.style.display = 'none';
            tbody.style.display = '';
        }
    });
}
window.addEventListener('hashchange', function (event) {
   // chengji()
    let href = event.newURL;
    if (
        href.indexOf('/index/testsu') == -1 &&
        document.getElementById('answerMask')
    ) {
        let answerMask = document.getElementById('answerMask');
        let body = document.getElementsByTagName('body')[0];
        body.removeChild(answerMask);
    }

    if (href.indexOf('index/testdire')>-1) {
        auto()
    }
    if (href.indexOf('/index/testmess') !== -1 && event.oldURL.indexOf("#/index/testdire")>-1) {
        setTimeout(() => {
            document.querySelector(".testmess_main__2I9EK section a").click()

        }, 400)
    }
});

async function auto() {
    await setTime(900)
    const node = document.querySelectorAll("section .ant-collapse-item .ant-collapse-header")

    let i = 0;
    let timer = setInterval(() => {
        node[i].click();
        i++
        if (i >= node.length) {
            clearInterval(timer)

            const childNode = document.querySelectorAll(".ant-collapse-content .testdire_list__39H5t section .testdire_score__2MVkA")
            for (let j = 0; j < childNode.length; j++) {
                const item = childNode[j]
                if (item.innerText !== "得分100/100分") {
                    document.querySelectorAll(".testdire_list__39H5t button")[j].click()
                    break;
                }
            }
        }
    }, 600)

    }

function setTime(time) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve("ok")
        }, time)
    })
}


//async function chengji(){

//    let res =await fetch("http://ols.v.zzu.edu.cn/s/appCourseSubject/queryUserCourseList", {
  //      "headers": {
    //        "accept": "application/json, text/plain, */*",
   //         "accept-language": "zh-CN,zh;q=0.9",
    //        "content-type": "application/x-www-form-urlencoded",
   //         "proxy-connection": "keep-alive"
   //     },
   //     "referrerPolicy": "no-referrer",
   //     "method": "POST",
   //     "mode": "cors",
   //     "credentials": "include"
   // }).then(r=>r.json());

//}