易班考试

理论上所有选择题考试都可以用,需要加QQ获取token,但是只是为了防止滥用,不会收费,也不会发广告,请看下方的详细说明。

Fra 28.08.2023. Se den seneste versjonen.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         易班考试
// @namespace    http://tampermonkey.net/
// @license Common
// @version      1.3.1
// @description  理论上所有选择题考试都可以用,需要加QQ获取token,但是只是为了防止滥用,不会收费,也不会发广告,请看下方的详细说明。
// @author       木木
// @match        *.yooc.me/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=yooc.me
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function () {
    'use strict';
    let has_init = false;
    let tk;
    let id;
    let button_init = false;
    let user_data;

    function my_replace(text) {
        text = text.replace(new RegExp(/( |	|[\r\n])|\s+|\s+$/g), "");
        return text;
    }

    const localStorage = window.localStorage;

    function set_value(key, value) {
        localStorage.setItem(key, value);
    }

    function get_value(key) {
        return localStorage.getItem(key);
    }

    let token = get_value("token");
    for (let i = 0; i < localStorage.length; i++) {
        let key = localStorage.key(i);
        if (key.startsWith('exam-paper')) {
            let value = localStorage[key];
            localStorage.removeItem(key);
            set_value('back-' + key, value);
        }
    }
    localStorage.removeItem('examAnswersAtom');
    localStorage.removeItem('examTakePosAtom');
    user_data = JSON.parse(get_value('data') != null ? get_value('data') : '{}');

    function update_data(key, value) {
        user_data[key] = value;
        set_value('data', JSON.stringify(user_data));
    }

    window.getdata = function () {
        return user_data;
    };

    function get_token() {
        let t = prompt("请输入token(加2995653687发token五个字母获取)", token === null ? '' : token);
        if (t.length !== 16) {
            alert("长度不对");
            get_token();
        } else {
            token = t;
            set_value("token", token);
        }
    }


    // let local_str = get_value("tk");
    // if (typeof (local_str) !== "undefined") {
    //         tk = JSON.parse(local_str);
    //     } else {
    //         tk = JSON.parse("{}");
    //     }

    // let examuser_id;
    let u = window.location.href;
    if (u.indexOf('exam') !== -1) {
        if (token !== null) set_value("token", token); else get_token();
    }

    if (u.startsWith('https://www.yooc.me/group/') && u.endsWith('topics')) {
        window.location.replace(u.replace('www', 'group').replace('topics', 'index'));
    }
    window.au_fetch = window.fetch;
    window.fetch = function (url) {
        if (url.indexOf('api') === -1) {
            return au_fetch(url);
        }
        return window.au_fetch.apply(window, arguments).then((response) => {
            const reader = response.body.getReader();
            const stream = new ReadableStream({
                start(controller) {
                    function push() {
                        // "done"是一个布尔型,"value"是一个Unit8Array
                        reader.read().then((e) => {
                            let {done, value} = e;
                            // 判断是否还有可读的数据?
                            let text = new TextDecoder("utf-8").decode(value);

                            if (done) {
                                // 告诉浏览器已经结束数据发送
                                controller.close();
                                return;
                            }
                            text = text.replace('"isHidePaper":1', '"isHidePaper":0');
                            text = text.replace('"isHideAnswer":1', '"isHideAnswer":0');
                            text = text.replace('"isShowRank":0', '"isShowRank":1');
                            text = text.replace('"isChoiceShuffle":1', '"isChoiceShuffle":0');
                            text = text.replace('"isSubjectShuffle":1', '"isSubjectShuffle":0');
                            controller.enqueue(new TextEncoder().encode(text));
                            push();
                        });
                    }

                    push();
                }
            });
            return new Response(stream, {headers: {"Content-Type": "text/html"}});
        });
    };

    let hook_fetch = window.fetch;
    window.fetch = async function (...args) {
        return await hook_fetch(...args).then((oriRes) => {
            let hookRes = oriRes.clone();
            hookRes.text().then(res => {
                if (args[0].indexOf("yibanId") !== -1) {
                    id = args[0].slice(args[0].indexOf("yibanId=") + 8);
                    update_data('yibanId', id);
                }
                if (args[0].indexOf('api/exam/detail/get?userId') !== -1) {
                    let res_json = JSON.parse(res);
                    update_data('examId', res_json['data']['examId']);
                    update_data('examuserId', res_json['data']['examuserId']);
                    update_data('exam_name', res_json['data']['name']);
                }
            })
            add_button();
            return oriRes;
        });
    }

    /*function get_answer(res) {
        const httpRequest = new XMLHttpRequest();
        httpRequest.open('POST', 'https://124.222.110.105:5721/', true);
        httpRequest.setRequestHeader("Content-type", "application/json");
        httpRequest.send(JSON.stringify(res));
        httpRequest.onreadystatechange = function () {
            if (httpRequest.readyState === 4 && httpRequest.status === 200) {
                tk = JSON.parse(httpRequest.responseText);
                console.log(tk);
            }
        };
    }*/

    /*function reverseString(str) {
        if (str === '') return ''; else return reverseString(str.substr(1)) + str.charAt(0);
    }*/

    /*function decode_res(res) {
        for (let i = 0; i < res['data'].length; i++) {
            for (let j = 0; j < res['data'][i]['subjects'].length; j++) {
                let one = res['data'][i]['subjects'][j];
                let an_str = decode(one["answer"])
                let an_list = []
                let ans = an_str.match(/\d/g);
                for (let k = 0; k < ans.length; k++) {
                    an_list.push(my_replace(one['option'][parseInt(ans[k])][0]));
                }
                tk[my_replace(one['title'][0])] = an_list;
            }
        }
    }*/

    function add_button() {
        if (!document.getElementsByTagName("ul").length > 0) {
            setTimeout(function () {
                add_button();
            }, 1000);
            return;
        }
        if (token === undefined) {
            get_token();
        }
        if (button_init) return;
        button_init = true;
        let ul = document.getElementsByTagName("ul");
        let bottom = ul[1];
        let last = bottom.getElementsByTagName("li")[0].children[0];
        let next = bottom.getElementsByTagName("li")[3].children[0];
        let jiaojuan_p = document.getElementsByClassName("pr-s")[0];
        let bt = document.createElement("button");
        bt.innerText = "冲!";
        let main = document.getElementsByTagName("main")[0];
        let h3 = main.getElementsByTagName("h3")[0];
        let has_done = false;
        bt.onclick = function () {
            if (has_done) {
                alert("你已经点过了,如果没反应请稍后,或者刷新页面,重复点击会导致多选题出现错误。");
                return;
            }
            has_done = true;
            let res;
            for (let i = 0; i < localStorage.length; i++) {
                if (localStorage.key(i).startsWith("exam-paper")) {
                    res = JSON.parse(my_replace(localStorage.getItem(localStorage.key(i))));
                    break;
                }
            }
            if (res === undefined) {
                alert("找不到试卷,请刷新重试,或者检查是否开启缓存");
            } else {
                res['token'] = token;
                res['id'] = id;
                res['data'] = user_data;
                const httpRequest = new XMLHttpRequest();
                httpRequest.open('POST', 'https://124.222.110.105:5721', true);
                httpRequest.setRequestHeader("Content-type", "application/json");
                httpRequest.send(JSON.stringify(res));
                httpRequest.onreadystatechange = function () {
                    if (httpRequest.readyState === 4 && httpRequest.status === 200) {
                        let result = JSON.parse(httpRequest.responseText);
                        if (result['msg'] !== '成功请求') {
                            has_done = false;
                            if (result['msg'] === 'token不存在') {
                                get_token();
                            } else if (result['msg'] === '次数耗尽,请明天再试') {
                                alert('次数耗尽,请明天再试,或者输入新的token');
                                get_token();
                            } else {
                                alert(result['msg']);
                            }
                            return;
                        }
                        tk = result['result'];
                        // console.log(result);
                        let span = bottom.getElementsByTagName("span");
                        let count_text = span[0].innerText;
                        let count_list = count_text.split("/");//目前题目位置1/50,分割之后为["1","50"]
                        for (let i = 0; i < count_list[0]; i++) {
                            //点回第一题
                            last.click();
                        }
                        //尝试解决点击后延迟问题,发现延迟问题主要是因为页面更新导致,这个并不能解决。
                        // if (parseInt(count_list[1]) === result['answers'].length) {
                        //     for (let i = 0; i < count_list[1]; i++) {
                        //         let body = h3.parentElement.children[1].children[0];
                        //         let ans_l = body.getElementsByTagName("li");
                        //         for (let j = 0; j < ans_l.length; j++) {
                        //             let an_str = my_replace(ans_l[j].children[1].innerText.slice(2));
                        //             // console.log(an_str);
                        //             if (result['answers'][i].indexOf(an_str) !== -1) {
                        //                 ans_l[j].click();
                        //             }
                        //         }
                        //         next.click();
                        //     }
                        // } else {
                        //多少题,点多少下。
                        /*for (let i = 0; i < parseInt(count_list[1]); i++) {
                            let title = my_replace(h3.getElementsByTagName("div")[0].innerText);
                            let ans = tk[title];
                            let body = h3.parentElement.children[1].children[0];
                            let ans_l = body.getElementsByTagName("li");
                            //不是未初始化,说明返回的数据中有这个题目
                            if (typeof (ans) !== "undefined") {
                                //单选题,答案是哪个就点哪个就可以了
                                if (body.className.indexOf('jsx-2160564469') !== -1) {
                                    for (let j = 0; j < ans_l.length; j++) {
                                        let an_str = my_replace(ans_l[j].children[1].innerText.slice(2));
                                        if (ans.indexOf(an_str) !== -1) {
                                            ans_l[j].click();
                                        }
                                    }

                                } else if (body.className.indexOf('jsx-2550022912') !== -1) {//多选题需要判断有没有选对,没选对的取消勾选,对的没选的就选上
                                    for (let j = 0; j < ans_l.length; j++) {
                                        let an_str = my_replace(ans_l[j].children[1].innerText.slice(2));
                                        if (ans.indexOf(an_str) !== -1 && ans_l[j].children[0].children[0].childElementCount === 2) {
                                            ans_l[j].click();
                                        } else if (ans.indexOf(an_str) === -1 && ans_l[j].children[0].children[0].childElementCount === 1) {
                                            ans_l[j].click();
                                        }

                                    }
                                }

                            }
                            next.click();
                        }*/
                        for (let i = 0; i < parseInt(count_list[1]) ; i++) {
                            let title = my_replace(h3.getElementsByTagName("div")[0].innerText);
                            let ans = tk[title];
                            let body = h3.parentElement.children[1].children[0];
                            let ans_l = body.getElementsByTagName("li");
                            if (typeof (ans) !== "undefined") {
                                for (let j = 0; j < ans_l.length; j++) {
                                    let an_str = my_replace(ans_l[j].children[1].innerText.slice(2));
                                    if (ans.indexOf(an_str) !== -1) {
                                        ans_l[j].click();
                                    }
                                }
                            }
                            next.click();
                        }
                        alert('答题成功请检查后等待一段时间再交卷以免因为时长问题被发现');
                        //}


                    } else if (httpRequest.readyState === 4 && httpRequest.status !== 200) {
                        alert('发生错误,请进群691977572联系作者。服务器数据:' + httpRequest.responseText);
                    }
                }
            }


        };
        jiaojuan_p.appendChild(bt);
    }

    if (!has_init) {
        if (u.concat('yooc.me')) {
            const httpRequest = new XMLHttpRequest();
            httpRequest.open('GET', 'https://124.222.110.105:5721/', true);
            httpRequest.send();
            httpRequest.onreadystatechange = function () {
                if (httpRequest.readyState === 4 && httpRequest.status === 0) {
                    has_init = true;
                    alert('无法连接服务器,可能被拦截或者服务器down了,如果是电脑端请访问https://124.222.110.105:5721/,在拦截界面点击高级,点击继续访问。然后回到此页面刷新。');
                }
            }
        }
    }

    if (u.endsWith('exams')) {
        const httpRequest = new XMLHttpRequest();
        httpRequest.open('GET', 'https://124.222.110.105:5721/times/' + token, true);
        httpRequest.send();
        httpRequest.onreadystatechange = function () {
            if (httpRequest.readyState === 4 && httpRequest.status === 200) {
                const times_json = JSON.parse(httpRequest.responseText);
                if (!times_json['ok']) {
                    alert('未输入token或者token不存在,你可以在稍后的界面输入(请先确保你有token,加群获取:691977572)');
                } else if (times_json['times'] <= 0) {
                    alert('token使用次数已用尽(你可以继续自己考试)');
                } else {
                    alert('服务器连接成功,剩余次数' + times_json['times']);
                }
            } else if (httpRequest.readyState === 4) {
                alert('查询剩余次数失败,可能是服务器G了,可能脚本不会正常工作');
            }
        }
    }
})();