Greasy Fork

Greasy Fork is available in English.

🥇优学院答题小助手(2022/07/03更新)|仅支持作业、考试界面,视频章节小测待开发。

优学院答题小助手,用于考试和作业界面辅助答题(非自动答题)。

目前为 2022-07-03 提交的版本,查看 最新版本

// ==UserScript==
// @name         🥇优学院答题小助手(2022/07/03更新)|仅支持作业、考试界面,视频章节小测待开发。
// @namespace    http://tampermonkey.net/
// @version      1.1.1
// @description  优学院答题小助手,用于考试和作业界面辅助答题(非自动答题)。
// @author       Miss.
// @match        https://utest.ulearning.cn/*
// @match        https://*ulearning.cn/*/homework.do*
// @grant        unsafeWindow
// @grant        GM_setClipboard
// @grant        GM_xmlhttpRequest
// @run-at       document-start
// @connect      http://fm90.cn/*
// ==/UserScript==

"use strict";
const set = {
    get_answer: "http://fm90.cn/fuck/cha.php",
    upload_data: "http://fm90.cn/fuck/upload.php",
    heartbeat: "http://fm90.cn/fuck/server.php",
    Dealagging: false,
    left: 0,
    top: 0,
    uid: -1, //后期加入
    token: null, //后期加入
    timestamp: -1,
};
const Util = {
    post_form: function (url, data, onload, onerror) {
        Util.post(url, data, onload, onerror, { "Content-Type": "application/x-www-form-urlencoded" });
    },
    post: function (url, data, onload, onerror, headers) {
        let data_form = new Deal();
        for (let value in data) {
            data_form.append(value, data[value]);
        }
        GM_xmlhttpRequest({
            method: "POST",
            url: url,
            headers: headers,
            data: data_form.text,
            onload: onload,
            onerror: onerror,
        });
    },
    get: function (url, data, onload, onerror) {
        let data_form = new Deal();
        for (let value in data) {
            data_form.append(value, data[value]);
        }
        GM_xmlhttpRequest({
            method: "GET",
            url: url + "?" + data_form.text,
            onload: onload,
            onerror: onerror,
        });
    },
    upload_api: function (data, send) {
        if (set.token == -1) {
            setTimeout(Util.upload_api, 1000, data, true);
            if (send === true) {
                return;
            }
        }
        Util.post_form(set.upload_data, {
            token: "" + set.token,
            data: JSON.stringify(data),
        });
    },
    upload_paper: function (paper, pid, eid) {
        Util.upload_api({ op: 4,eid: eid, pid: pid, paper: paper });
    },
    upload_answer: function (answer, pid, eid) {
        Util.upload_api({ op: 5,eid: eid, pid: pid, answer: answer });
    },
    upload_title: function (title, quetype, quetxt) {
        Util.upload_api({ op: 6, type: quetype, title: title ,cont: quetxt });
    },
    get_answer: function (question, td) {
        Util.get(set.get_answer, { question: question }, function (xhr) {
            if (xhr.status == 200) {
                try {
                    let data = JSON.parse(xhr.responseText);
                    if (data.code == 1) {
                        td.innerText = data.data[0].answer;
                        td.addEventListener("click", function () {
                            GM_setClipboard(data.answer);
                        });
                        return;
                    }
                    else if (data.code == 0) {
                        td.innerText = "无答案(已回传服务器)";
                        return 0;
                    }
                }
                catch (e) { }
            }
            td.innerText = "服务器错误";
        }, function () {
            td.innerText = "服务器错误";
        });
    },
};
Re_Write();
Set_Heart();
Init();
function Re_Write() {
    const open = unsafeWindow.XMLHttpRequest.prototype.open;
    unsafeWindow.XMLHttpRequest.prototype.open = function () {
        let url = arguments[1];
        if (url) {
            if (url.match(/getPaperForStudent/) && url.match(/examId=(\d+)/) && url.match(/paperId=(\d+)/)) {
                let examID = url.match(/examId=(\d+)/)[1];
                let paperID = url.match(/paperId=(\d+)/)[1];
                this.addEventListener('load', () => {
                    let data = JSON.parse(this.responseText);
                    Util.upload_paper(data, paperID, examID);
                });
            }
            else if (url.match(/getCorrectAnswer/) && url.match(/examId=(\d+)/) && url.match(/paperId=(\d+)/)) {
                let examID = url.match(/examId=(\d+)/)[1];
                let paperID = url.match(/paperId=(\d+)/)[1];
                this.addEventListener('load', () => {
                    let data = JSON.parse(this.responseText);
                    Util.upload_answer(data, paperID, examID);
                });
            }
        }
        return open.apply(this, arguments);
    };
}
function Init() {
    if (!document.body) {
        setTimeout(Init, 100);
        return;
    }
    let style = document.createElement("style");
    style.innerHTML = `
    #answer_key {
        min-height: 22px;
        max-height: 250px;
        overflow: auto;
    }
    .td_center {
        text-align: center;
    }
    .td_left {
        text-align: left;
    }
    .td_right {
        text-align: right;
    }
    .td_width {
        width: 125px;
    }`;
    let div = document.createElement("div");
    pageurl = window.location.href.split("?")[0];
    if(pageurl=="https://utest.ulearning.cn/"){
        div.setAttribute("style", "background-color: #4fc8db; position: fixed; top: 54px; right: 300px; width: 270px; opacity: 0.75; border-style: dotted; border-width: 3px;");
    }
    else{
        div.setAttribute("style", "background-color: #4fc8db; position: fixed; top: 54px; left: 50px; width: 270px; opacity: 0.75; border-style: dotted; border-width: 3px;");
    }

    div.innerHTML = `
    <h3 style="text-align: center;">Ulearning 查题</h3>
    <table>
        <tbody>
            <tr>
                <td class="td_width td_center">
                    <button id="get_answer" style="background-color: #84f584; border-radius: 10px;">查询答案</button>
                </td>
                <td class="td_width td_center">
                    <button id="hide_show" style="background-color: #84f584; border-radius: 10px;">显示/隐藏答案</button>
                </td>
            </tr>
            <tr>
                <td class="td_width td_right">
                    服务器状态:
                </td>
                <td id="server_status" class="td_width td_left" style="font-color: blue;">
                    获取中..
                </td>
            </tr>
        </tbody>
    </table>
    <div id="answer_key" style="display: block;">
        <table border="1" id="answer_table">
            <tbody>
                <tr>
                    <th class="td_width td_center">题目</th>
                    <th class="td_width td_center">答案</th>
                </tr>
            </tbody>
        </table>
    </div>
    `;
    document.body.appendChild(style);
    document.body.appendChild(div);
    Bind();
    div.addEventListener("mousedown", function (e) {
        set.Dealagging = true;
        let mer = div.getBoundingClientRect();
        set.left = e.clientX - mer.left;
        set.top = e.clientY - mer.top;
    });
    div.addEventListener("mouseup", function () {
        set.Dealagging = false;
    });
    div.addEventListener("mousemove", function (e) {
        if (set.Dealagging) {
            let x = e.clientX - set.left;
            let y = e.clientY - set.top;
            div.style.left = x + "px";
            div.style.top = y + "px";
        }
    });
}
function Bind() {
    let get_answer = document.querySelector("#get_answer");
    get_answer && (function () {
        get_answer.addEventListener("click", Get_Answer, false);
    })();
    let hide_show = document.querySelector("#hide_show");
    hide_show && (function () {
        hide_show.addEventListener("click", function () {
            let answer_key = document.querySelector("#answer_key");
            answer_key && (function () {
                answer_key.getAttribute("style") === "display: block;" && (function () {
                    answer_key.setAttribute("style", "display: none;");
                    return true;
                })() || (function () {
                    answer_key.setAttribute("style", "display: block;");
                })();
            })();
        }, false);
    })();
}
function Set_Heart() {
        setInterval(Heart, 20000);
}
function Heart() {
    let server_status = document.querySelector("#server_status");
    if (server_status) {
        set.timestamp = new Date().getTime();
        Util.get(set.heartbeat, { token: "" + set.token, timestamp: "" + set.timestamp }, function (xhr) {
            try {
                let xhr_json = JSON.parse(xhr.responseText);
                if (xhr_json.code == 1) {
                    server_status.innerText = "正常";
                    return;
                }
            }
            catch (e) { }
            server_status.innerText = "异常";
        }, function () {
            server_status.innerText = "异常";
        });
    }
}
function Clear_Table() {
    let answer_table = document.querySelector("#answer_table");
    answer_table && (function () {
        while (answer_table.rows.length > 1) {
            answer_table.deleteRow(1);
        }
    })();
}
function Get_Answer() {
    Clear_Table();
    let question_area = document.querySelectorAll(".question-area");
    question_area && (function(){
        question_area.forEach(function (item) {
            item.childNodes.forEach(function (div) {
                if (div.className.indexOf("next-part") != -1) {
                    return;
                }
                switch (div.className) {
                    case "question-item":
                        way1(div);
                        break;
                    default:
                        way2(div);
                }
            });
        });
    })();
    let question_wrap = document.querySelectorAll("#questionWrap");
    question_area && (function(){
        question_wrap.forEach(function (item) {
            item.childNodes.forEach(function (div){
                switch (div.className) {
                    case "multiple-choices":
                        case "judge":
                        case "fill":
                        case "match":
                        case "sort":
                            way3(div);
                            break;
                        case "blankFill":
                        case "cloze":
                        default:
                            way2(div);
                }
            });
        });
    })();
}
function way3(div) {
    let index = div.querySelector(".position-rltv").firstChild.innerText;
    let title = div.querySelector(".position-rltv").lastChild;
    let title_text = title && title.innerText || "";
    let answer_table = document.querySelector("#answer_table");
    answer_table && (function () {
        let tr = answer_table.insertRow();
        let t = tr.insertCell();
        t.innerText = "【" + index.split(".")[0] + "】" + title_text;
        t.addEventListener("click", function () {
            GM_setClipboard(this.innerText);
        }, false);
        t = tr.insertCell();
        Util.get_answer(title_text, t);
    })();
}
function way2(div) {
//   英语答题类      待提供测试账号开发
//   英语答题类      待提供测试账号开发
//   英语答题类      待提供测试账号开发
}
function way1(div) {
    let qid = div.firstChild.__vue__.question.questionid;
    if (!qid) {
        return;
    }
    let index = div.firstChild.__vue__.question.index;
    let title = div.firstChild.__vue__.question.title;
    let quetype = div.firstChild.__vue__.question.type;
    let quetxt = "";
    let cho = div.firstChild.__vue__.question.choices;
    if(quetype==1||quetype==2){
        cho.forEach(function(item){quetxt+=item.text+"||";})
        quetxt = re_text(quetxt);
    }
    let answer_table = document.querySelector("#answer_table");
    answer_table && (function () {
        let tr = answer_table.insertRow();
        let t = tr.insertCell();
        t.innerText = "【" + index + "】" + title;
        t.addEventListener("click", function () {
            GM_setClipboard(this.innerText);
        }, false);
        t = tr.insertCell();
        let getcode = Util.get_answer(title, t);
        if(getcode==0){
            Util.upload_title(title, quetype, quetxt);
        }
    })();
}

function re_text(text) {
    text = text.replace(/<\/?.+?\/?>/g,'');
    text = text.replace(/\t/g, "");
    text = text.replace(/\n/g, "");
    text = text.replace(/\r/g, "");
    text = text.replace(/&.*?;/g, "");
    return $.trim(text.substr(0,text.length-2));
}

function sleep(d){
  for(var t = Date.now();Date.now() - t <= d;);
}

class Deal {
    constructor() {
        this.text = "";
        this.data = [];
    }
    append(k, v) {
        this.data.push(encodeURIComponent(k) + "=" + encodeURIComponent(v));
        this.text = this.data.join("&").replace(/%20/g, "+");
    }
}