// ==UserScript== // @name QingJiaoHelper // @namespace http://tampermonkey.net/ // @version 0.3.0 // @description 青骄第二课堂小助手: 长期更新 | 2022 知识竞赛 | 跳过视频 | 自动完成所有课程 | 每日领取学分 | 课程自动填充答案 // @author WindLeaf233 // @match *://www.2-class.com/* // @match *://2-class.com/* // @grant GM_addStyle // @grant GM_getResourceText // @grant GM_registerMenuCommand // @grant GM_getValue // @grant GM_setValue // @license GPL-3.0 // @supportURL https://github.com/WindLeaf233/QingJiaoHelper // @require https://cdn.bootcdn.net/ajax/libs/toastify-js/1.12.0/toastify.min.js // @require https://greasyfork.org/scripts/453791-lib2class/code/lib2class.js?version=1258326 // @require https://cdn.bootcdn.net/ajax/libs/axios/1.3.6/axios.min.js // @resource toastifycss https://cdn.bootcdn.net/ajax/libs/toastify-js/1.12.0/toastify.min.css // @resource spectrecss https://cdn.jsdelivr.net/gh/WindLeaf233/QingJiaoHelper/spectre.css // @downloadURL none // ==/UserScript== var _this = this; var apiGetGradeLevels = { method: "GET", api: "/course/getHomepageGrade", }; var apiGetCoursesByGradeLevel = { method: "GET", api: "/course/getHomepageCourseList?grade=${grade}&pageSize=50&pageNo=1", }; var apiGetSelfCoursesByGradeLevel = { method: "GET", api: "/course/getHomepageCourseList?grade=自学&pageNo=1&pageSize=500&sort=&type=${grade}", }; var apiGetTestPaperList = { method: "GET", api: "/exam/getTestPaperList?courseId=${courseId}", }; var apiCommitExam = { method: "POST", api: "/exam/commit", }; var apiAddMedal = { method: "GET", api: "/medal/addMedal", }; var apiGetBeforeResourcesByCategoryName = { method: "POST", api: "/resource/getBeforeResourcesByCategoryName", }; var apiAddPCPlayPV = { method: "POST", api: "/resource/addPCPlayPV", }; var apiLikePC = { method: "POST", api: "/resource/likePC", }; function requestAPI(api, params, data) { return __awaiter(this, void 0, void 0, function () { var method, origin, url, key; return __generator(this, function (_a) { switch (_a.label) { case 0: method = api.method; origin = "https://www.2-class.com"; url = "".concat(origin, "/api").concat(api.api); for (key in params) { url = url.replaceAll("${" + key + "}", params[key]); } if (!(method === "GET")) return [3 /*break*/, 2]; return [4 /*yield*/, axios({ method: "GET", url: url }) .then(function (response) { var rdata = response.data; console.debug("[".concat(method, "] ").concat(url), data, rdata); if (rdata.success === false || rdata.data === null) { var errorMessage = rdata.errorMsg; var errorCode = rdata.errorCode; console.error("API 返回错误 [".concat(errorCode, "]:").concat(errorMessage, ",请刷新页面重试!")); return null; } else { return rdata; } }) .catch(function (reason) { showMessage("请求 API 失败(".concat(reason.code, "):").concat(reason.message, "\n请将控制台中的具体报错提交!"), "red"); console.error("请求失败(".concat(reason.status, "/").concat(reason.code, ")→").concat(reason.message, "→"), reason.toJSON(), reason.response, reason.stack); })]; case 1: return [2 /*return*/, _a.sent()]; case 2: return [4 /*yield*/, axios({ method: "POST", url: url, headers: { "Content-Type": "application/json;charset=UTF-8", }, data: data, }).then(function (response) { var rdata = response.data; console.debug("[".concat(method, "] ").concat(url), data, rdata); if (rdata.success === false || rdata.data === null) { var errorMessage = rdata.errorMsg; var errorCode = rdata.errorCode; console.error("API 返回错误 [".concat(errorCode, "]:").concat(errorMessage, ",请刷新页面重试!")); return null; } else { return rdata; } })]; case 3: return [2 /*return*/, _a.sent()]; } }); }); } function getAvailableGradeLevels() { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, requestAPI(apiGetGradeLevels).then(function (data) { return data ? data.data.map(function (it) { return it.value; }) : null; })]; case 1: return [2 /*return*/, _a.sent()]; } }); }); } function getCoursesByGradeLevel(gradeLevel) { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, requestAPI(apiGetCoursesByGradeLevel, { grade: gradeLevel, }).then(function (data) { return data ? data.data.list : null; })]; case 1: return [2 /*return*/, _a.sent()]; } }); }); } function getSelfCoursesByGradeLevel(gradeLevel) { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, requestAPI(apiGetSelfCoursesByGradeLevel, { grade: gradeLevel, }).then(function (data) { return data ? data.data.list : null; })]; case 1: return [2 /*return*/, _a.sent()]; } }); }); } function getTestPaperList(courseId) { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, requestAPI(apiGetTestPaperList, { courseId: courseId }).then(function (data) { return data ? data.data.testPaperList : null; })]; case 1: return [2 /*return*/, _a.sent()]; } }); }); } function getCourseAnswers(courseId) { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, getTestPaperList(courseId).then(function (testPaperList) { if (!isNone(testPaperList)) { var answers = testPaperList.map(function (column) { return column.answer; }); console.debug("成功获取课程 [".concat(courseId, "] 的答案"), answers); return answers.map(function (it) { return it.split("").join(","); }); } else { console.error("无法获取课程 [".concat(courseId, "] 答案!")); return null; } })]; case 1: return [2 /*return*/, _a.sent()]; } }); }); } function commitExam(data) { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, requestAPI(apiCommitExam, {}, data)]; case 1: return [2 /*return*/, _a.sent()]; } }); }); } function addMedal() { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, requestAPI(apiAddMedal).then(function (data) { if (isNone(data)) { return null; } else { var flag = data.flag; var num = data.medalNum; if (flag) { return num; } else { return undefined; } } })]; case 1: return [2 /*return*/, _a.sent()]; } }); }); } function getBeforeResourcesByCategoryName(data) { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, requestAPI(apiGetBeforeResourcesByCategoryName, {}, data).then(function (data) { return data ? data.data.list.map(function (it) { return { title: it.briefTitle, resourceId: it.resourceId, }; }) : null; })]; case 1: return [2 /*return*/, _a.sent()]; } }); }); } function addPCPlayPV(data) { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, requestAPI(apiAddPCPlayPV, {}, data).then(function (data) { return data ? data.data.result : null; })]; case 1: return [2 /*return*/, _a.sent()]; } }); }); } function likePC(data) { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, requestAPI(apiLikePC, {}, data).then(function (data) { if (isNone(data)) { return null; } else { var rdata = data.data; return !Number.isNaN(Number(rdata)) || rdata.errorCode === "ALREADY_like"; } })]; case 1: return [2 /*return*/, _a.sent()]; } }); }); } var scriptName = "QingJiaoHelper"; var scriptVersion = "v0.3.0"; var toastifyDuration = 3 * 1000; var toastifyGravity = "top"; var toastifyPosition = "left"; var __DATA__ = function () { return window["__DATA__"]; }; var reqtoken = function () { return __DATA__().reqtoken; }; var userInfo = function () { return __DATA__().userInfo; }; var isLogined = function () { return JSON.stringify(userInfo()) !== "{}"; }; var accountGradeLevel = function () { return isLogined() ? userInfo().department.gradeName : "未登录"; }; var coursesGradeLevels = function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, getAvailableGradeLevels()]; case 1: return [2 /*return*/, _a.sent()]; } }); }); }; var selfCoursesGradeLevels = function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { return [2 /*return*/, [ "小学", "初中", "高中", "中职", "通用", ]]; }); }); }; ("use strict"); var isTaskCoursesEnabled = function () { return getGMValue("qjh_isTaskCoursesEnabled", false); }; var isTaskSelfCourseEnabled = function () { return getGMValue("qjh_isTaskSelfCourseEnabled", false); }; var isTaskGetCreditEnabled = function () { return getGMValue("qjh_isTaskGetCreditEnabled", false); }; var isTaskSingleCourseEnabled = function () { return getGMValue("qjh_isTaskSingleCourseEnabled", true); }; var isTaskSkipEnabled = function () { return getGMValue("qjh_isTaskSkipEnabled", true); }; var isTaskFinalExaminationEnabled = function () { return getGMValue("qjh_isTaskFinalExaminationEnabled", false); }; var isFullAutomaticEmulationEnabled = function () { return getGMValue("qjh_isFullAutomaticEmulationEnabled", false); }; var autoComplete = function () { return featureNotAvailable("自动完成"); }; var autoCompleteCreditsDone = function () { return getGMValue("qjh_autoCompleteCreditsDone", false); }; var features = [ { key: "courses", title: "自动完成所有课程(不包括考试)", matcher: ["/courses", "/drugControlClassroom/courses"], task: function () { return taskCourses(false); }, enabled: isTaskCoursesEnabled, }, { key: "selfCourse", title: "自动完成所有自学课程(不包括考试)", matcher: ["/selfCourse", "/drugControlClassroom/selfCourse"], task: function () { return taskCourses(true); }, enabled: isTaskSelfCourseEnabled, }, { key: "credit", title: "自动获取每日学分(会花费一段时间,请耐心等待)", matcher: ["/admin/creditCenter"], task: taskGetCredit, enabled: isTaskGetCreditEnabled, }, { key: "singleCourse", title: "单个课程自动完成", matcher: /\/courses\/exams\/(\d+)/, task: taskSingleCourse, enabled: isTaskSingleCourseEnabled, }, { key: "finalExamination", title: "期末考试", matcher: ["/courses/exams/finalExam"], task: taskFinalExamination, enabled: isTaskFinalExaminationEnabled, }, { key: "skip", title: "显示课程视频跳过按钮", matcher: /\/courses\/(\d+)/, task: taskSkip, enabled: isTaskSkipEnabled, }, ]; function triggerFeatures() { if (location.pathname === "/") { showMessage("".concat(scriptName, "\n版本:").concat(scriptVersion), "green"); } features.forEach(function (feature) { var matcher = feature.matcher; var isMatched = matcher instanceof RegExp ? location.pathname.match(matcher) : matcher.indexOf(location.pathname) !== -1; if (isMatched && feature.enabled()) { showMessage("激活功能:".concat(feature.title), "green"); feature.task(); } }); } (function () { for (var _i = 0, _a = document.getElementsByTagName("script"); _i < _a.length; _i++) { var script = _a[_i]; if (script.innerText.indexOf("window.__DATA__") !== -1) { eval(script.innerText); } } GM_addStyle(GM_getResourceText("toastifycss")); GM_addStyle(GM_getResourceText("spectrecss")); GM_registerMenuCommand("菜单", showMenu); prepareMenu(); var pathname = location.pathname; setInterval(function () { var newPathName = location.pathname; if (newPathName !== pathname) { console.debug("地址改变", pathname, newPathName); pathname = newPathName; triggerFeatures(); } }); triggerFeatures(); })(); var customGradeLevels = function () { return getGMValue("qjh_customGradeLevels", []); }; var customSelfGradeLevels = function () { return getGMValue("qjh_customSelfGradeLevels", []); }; function prepareMenu() { return __awaiter(this, void 0, void 0, function () { var menuElement, coursesGradeLevelsList, selfCoursesGradeLevelsList, titleElement, _loop_1, _i, _a, _b, selector, gradeLevels, customGradeLevelsList, customGradeLevelsListChangeHandler, closeButton, toggleInputs, _loop_2, _c, toggleInputs_1, toggleInput, featButtons, _loop_3, _d, featButtons_1, featButton; return __generator(this, function (_e) { switch (_e.label) { case 0: return [4 /*yield*/, waitForElementLoaded("#qjh-menu")]; case 1: menuElement = _e.sent(); return [4 /*yield*/, coursesGradeLevels()]; case 2: coursesGradeLevelsList = _e.sent(); return [4 /*yield*/, selfCoursesGradeLevels()]; case 3: selfCoursesGradeLevelsList = _e.sent(); if (coursesGradeLevels === null || selfCoursesGradeLevelsList === null) { showMessage("课程年级列表或自学课程年级列表获取失败!", "red"); } return [4 /*yield*/, waitForElementLoaded("#qjh-menu-title")]; case 4: titleElement = _e.sent(); titleElement.append(scriptVersion); _loop_1 = function (selector, gradeLevels, customGradeLevelsList, customGradeLevelsListChangeHandler) { var element, _loop_4, _f, gradeLevels_1, gradeLevel; return __generator(this, function (_g) { switch (_g.label) { case 0: return [4 /*yield*/, waitForElementLoaded(selector)]; case 1: element = _g.sent(); if (gradeLevels === null) { return [2 /*return*/, "continue"]; } _loop_4 = function (gradeLevel) { var label = document.createElement("label"); label.className = "form-checkbox form-inline"; var input = document.createElement("input"); input.type = "checkbox"; input.checked = customGradeLevelsList().indexOf(gradeLevel) !== -1; input.onchange = function () { if (input.checked) { customGradeLevelsListChangeHandler(Array.of.apply(Array, __spreadArray(__spreadArray([], customGradeLevelsList(), false), [gradeLevel], false))); } else { customGradeLevelsListChangeHandler(customGradeLevelsList().filter(function (it) { return it !== gradeLevel; })); } }; var i = document.createElement("i"); i.className = "form-icon"; label.appendChild(input); label.appendChild(i); label.append(gradeLevel); element.appendChild(label); }; for (_f = 0, gradeLevels_1 = gradeLevels; _f < gradeLevels_1.length; _f++) { gradeLevel = gradeLevels_1[_f]; _loop_4(gradeLevel); } return [2 /*return*/]; } }); }; _i = 0, _a = [ { selector: "#qjh-menu-feat-courses", gradeLevels: coursesGradeLevelsList, customGradeLevelsList: customGradeLevels, customGradeLevelsListChangeHandler: function (value) { return GM_setValue("qjh_customGradeLevels", value); }, }, { selector: "#qjh-menu-feat-self-courses", gradeLevels: selfCoursesGradeLevelsList, customGradeLevelsList: customSelfGradeLevels, customGradeLevelsListChangeHandler: function (value) { return GM_setValue("qjh_customSelfGradeLevels", value); }, }, ]; _e.label = 5; case 5: if (!(_i < _a.length)) return [3 /*break*/, 8]; _b = _a[_i], selector = _b.selector, gradeLevels = _b.gradeLevels, customGradeLevelsList = _b.customGradeLevelsList, customGradeLevelsListChangeHandler = _b.customGradeLevelsListChangeHandler; return [5 /*yield**/, _loop_1(selector, gradeLevels, customGradeLevelsList, customGradeLevelsListChangeHandler)]; case 6: _e.sent(); _e.label = 7; case 7: _i++; return [3 /*break*/, 5]; case 8: return [4 /*yield*/, waitForElementLoaded("#qjh-menu-close-button")]; case 9: closeButton = _e.sent(); closeButton.onclick = function () { menuElement.style.display = "none"; }; toggleInputs = nodeListToArray(document.querySelectorAll("input")).filter(function (element) { return element.getAttribute("qjh-type") === "toggle"; }); _loop_2 = function (toggleInput) { var key = toggleInput.getAttribute("qjh-key"); toggleInput.checked = GM_getValue(key); toggleInput.onchange = function () { GM_setValue(key, toggleInput.checked); }; }; for (_c = 0, toggleInputs_1 = toggleInputs; _c < toggleInputs_1.length; _c++) { toggleInput = toggleInputs_1[_c]; _loop_2(toggleInput); } featButtons = nodeListToArray(document.querySelectorAll("button")).filter(function (element) { return element.getAttribute("qjh-feat-key") !== null; }); _loop_3 = function (featButton) { var key = featButton.getAttribute("qjh-feat-key"); var feature = features.find(function (feature) { return feature.key === key; }); featButton.onclick = function () { if (feature.enabled()) { showMessage("手动激活功能:".concat(feature.title), "green"); feature.task(); } else { showMessage("功能 ".concat(feature.title, " 未被启用!"), "red"); } }; }; for (_d = 0, featButtons_1 = featButtons; _d < featButtons_1.length; _d++) { featButton = featButtons_1[_d]; _loop_3(featButton); } return [2 /*return*/]; } }); }); } function startCourse(courseId) { return __awaiter(this, void 0, void 0, function () { var answers, data, response; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, getCourseAnswers(courseId)]; case 1: answers = _a.sent(); if (!(answers === null)) return [3 /*break*/, 2]; showMessage("[".concat(courseId, "] 无法获取当前课程的答案!"), "red"); return [2 /*return*/, false]; case 2: console.debug("正在提交课程 [".concat(courseId, "] 答案...")); data = { courseId: courseId, examCommitReqDataList: answers.map(function (answer, index) { return { examId: index + 1, answer: Number(answer) || answer, // 如果是单选,则必须要为数字 }; }), reqtoken: reqtoken(), }; return [4 /*yield*/, commitExam(data)]; case 3: response = _a.sent(); console.debug("提交课程 [".concat(data.courseId, "] 答案"), response); return [2 /*return*/, !isNone(response)]; } }); }); } function taskCourses(isSelfCourses) { return __awaiter(this, void 0, void 0, function () { var gradeLevels, _i, gradeLevels_2, gradeLevel, coursesList, _a, courseIds, committed, _b, courseIds_1, courseId, result; return __generator(this, function (_c) { switch (_c.label) { case 0: if (!isLogined()) { showMessage("你还没有登录!", "red"); return [2 /*return*/]; } return [4 /*yield*/, (isSelfCourses ? selfCoursesGradeLevels : coursesGradeLevels)()]; case 1: gradeLevels = _c.sent(); if (gradeLevels === null) { showMessage("获取年级名列表失败,功能已中止!", "red"); return [2 /*return*/]; } console.debug("获取总年级名列表", gradeLevels); gradeLevels = isSelfCourses ? customSelfGradeLevels() : customGradeLevels(); console.debug("已选择的年级列表", gradeLevels); _i = 0, gradeLevels_2 = gradeLevels; _c.label = 2; case 2: if (!(_i < gradeLevels_2.length)) return [3 /*break*/, 13]; gradeLevel = gradeLevels_2[_i]; if (!isSelfCourses) return [3 /*break*/, 4]; return [4 /*yield*/, getSelfCoursesByGradeLevel(gradeLevel)]; case 3: _a = _c.sent(); return [3 /*break*/, 6]; case 4: return [4 /*yield*/, getCoursesByGradeLevel(gradeLevel)]; case 5: _a = _c.sent(); _c.label = 6; case 6: coursesList = _a; if (coursesList === null) { showMessage("[".concat(gradeLevel, "] 获取当前年级的课程列表失败,已跳过当前年级!"), "red"); } courseIds = coursesList .filter(function (it) { return !it.isFinish && it.title !== "期末考试"; }) .map(function (it) { return it.courseId; }); if (courseIds.length === 0) { console.debug("[".concat(gradeLevel, "] 所有").concat(isSelfCourses ? "自学" : "", "课程都是完成状态,已跳过!")); return [2 /*return*/]; } console.debug("[".concat(gradeLevel, "] 未完成的").concat(isSelfCourses ? "自学" : "", "课程"), courseIds); committed = 0; _b = 0, courseIds_1 = courseIds; _c.label = 7; case 7: if (!(_b < courseIds_1.length)) return [3 /*break*/, 11]; courseId = courseIds_1[_b]; if (courseId === "finalExam") { return [2 /*return*/]; } if (!!isNone(courseId)) return [3 /*break*/, 9]; return [4 /*yield*/, startCourse(courseId)]; case 8: result = _c.sent(); if (result) { committed++; } else { console.error("[".concat(courseId, "] 无法提交当前课程,已跳过!")); } return [3 /*break*/, 10]; case 9: console.error("[".concat(gradeLevel, "] 无法找到 courseId,已跳过!")); _c.label = 10; case 10: _b++; return [3 /*break*/, 7]; case 11: showMessage("成功完成了 ".concat(committed, " 个").concat(isSelfCourses ? "自学" : "", "课程!"), "green"); _c.label = 12; case 12: _i++; return [3 /*break*/, 2]; case 13: return [2 /*return*/]; } }); }); } function taskSingleCourse() { return __awaiter(this, void 0, void 0, function () { var courseId, answers; return __generator(this, function (_a) { switch (_a.label) { case 0: if (!isLogined()) { showMessage("你还没有登录!", "red"); return [2 /*return*/]; } courseId = location.pathname.match(/(\d+)/g)[0]; return [4 /*yield*/, getCourseAnswers(courseId)]; case 1: answers = _a.sent(); return [4 /*yield*/, emulateExamination(answers, "#app > div > div.home-container > div > div > div > div > div > button", "#app > div > div.home-container > div > div > div > div > div > div.exam-content-btnbox > button", "#app > div > div.home-container > div > div > div > div > div > div.exam-content-btnbox > div > button.ant-btn-primary", function (answers, _) { var firstAnswer = answers.shift().toString(); return { answer: firstAnswer, matchedQuestion: null, }; }, "答题 [".concat(courseId, "]"), answers.length)]; case 2: _a.sent(); return [2 /*return*/]; } }); }); } function emulateExamination(answers, startButtonSelector, primaryNextButtonSelector, secondaryNextButtonSelector, answerHandler, examinationName, size) { if (size === void 0) { size = 100; } return __awaiter(this, void 0, void 0, function () { var isExaminationStarted, count, next, startButton; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: isExaminationStarted = false; count = 0; next = function (nextAnswers, nextButton) { if (nextButton === void 0) { nextButton = null; } return __awaiter(_this, void 0, void 0, function () { var questionElement, questionText, _firstNextButton, _a, answer, matchedQuestion, selections, displayAnswer, finalQuestion, _i, _b, answerIndex, selectionElement; return __generator(this, function (_c) { switch (_c.label) { case 0: return [4 /*yield*/, waitForElementLoaded(".exam-content-question")]; case 1: questionElement = _c.sent(); questionText = removeSpaces(questionElement.innerText.split("\n")[0] // 获取第一行(题目都是在第一行) ); if (!!isExaminationStarted) return [3 /*break*/, 4]; return [4 /*yield*/, waitForElementLoaded(primaryNextButtonSelector)]; case 2: _firstNextButton = _c.sent(); isExaminationStarted = true; return [4 /*yield*/, next(nextAnswers, _firstNextButton)]; case 3: _c.sent(); return [3 /*break*/, 5]; case 4: if (count > 0) { nextButton = document.querySelector(secondaryNextButtonSelector); } if (!isNone(size) && count < size) { nextButton.onclick = function () { setTimeout(function () { return next(nextAnswers, nextButton); }, 200); return; }; _a = answerHandler(answers, questionText), answer = _a.answer, matchedQuestion = _a.matchedQuestion; selections = document.getElementsByClassName("exam-single-content-box"); console.debug("选择", answer, selections); displayAnswer = toDisplayAnswer(answer); finalQuestion = matchedQuestion || questionText; if (!isFullAutomaticEmulationEnabled()) { showMessage("".concat(finalQuestion ? finalQuestion + "\n" : "", "第 ").concat(count + 1, " 题答案:").concat(displayAnswer), "green"); } for (_i = 0, _b = answer.split(",").map(function (it) { return Number(it); }); _i < _b.length; _i++) { answerIndex = _b[_i]; selectionElement = selections[answerIndex]; selectionElement.click(); } if (isFullAutomaticEmulationEnabled()) { nextButton.click(); } count++; } _c.label = 5; case 5: return [2 /*return*/]; } }); }); }; return [4 /*yield*/, waitForElementLoaded(startButtonSelector)]; case 1: startButton = _a.sent(); startButton.onclick = function () { showMessage("开始 ".concat(examinationName, "!"), "blue"); next(answers, null); }; return [2 /*return*/]; } }); }); } function taskSkip() { return __awaiter(this, void 0, void 0, function () { var courseId, span, skipButton, skipSpan; return __generator(this, function (_a) { switch (_a.label) { case 0: if (!isLogined()) { showMessage("你还没有登录!", "red"); return [2 /*return*/]; } courseId = location.pathname.match(/(\d+)/g)[0]; return [4 /*yield*/, waitForElementLoaded("#app > div > div.home-container > div > div > div.course-title-box > div > a > span")]; case 1: span = _a.sent(); span.style.display = "inline-flex"; skipButton = document.createElement("button"); skipButton.type = "button"; skipButton.className = "ant-btn ant-btn-danger ant-btn-lg"; skipSpan = document.createElement("span"); skipSpan.innerText = "跳过"; skipButton.appendChild(skipSpan); skipButton.onclick = function () { location.href = "/courses/exams/".concat(courseId); }; span.appendChild(skipButton); return [2 /*return*/]; } }); }); } function taskGetCredit() { return __awaiter(this, void 0, void 0, function () { var num, categories, done, failed, liked, _i, categories_1, category, data, resources, _a, resources_1, resource, resourceId, resourceData, result, likeResult, beforeDone, checkSuccess; return __generator(this, function (_b) { switch (_b.label) { case 0: if (!isLogined()) { showMessage("你还没有登录!", "red"); return [2 /*return*/]; } return [4 /*yield*/, addMedal()]; case 1: num = _b.sent(); if (num !== undefined) { showMessage("成功领取禁毒徽章 [".concat(num, "]!"), "green"); } else if (num === null) { showMessage("领取徽章失败!", "red"); } else { console.warn("无法领取徽章(可能已领取过),已跳过!"); } categories = [ { name: "public_good", tag: "read" }, { name: "ma_yun_recommend", tag: "labour" }, { name: "ma_yun_recommend", tag: "movie" }, { name: "ma_yun_recommend", tag: "music" }, { name: "ma_yun_recommend", tag: "physicalEducation" }, { name: "ma_yun_recommend", tag: "arts" }, { name: "ma_yun_recommend", tag: "natural" }, { name: "ma_yun_recommend", tag: "publicWelfareFoundation" }, { name: "school_safe", tag: "safeVolunteer" }, ]; done = 0; failed = 0; liked = 0; _i = 0, categories_1 = categories; _b.label = 2; case 2: if (!(_i < categories_1.length)) return [3 /*break*/, 9]; category = categories_1[_i]; data = { categoryName: category.name, pageNo: 1, pageSize: 100, reqtoken: reqtoken(), tag: category.tag, }; return [4 /*yield*/, getBeforeResourcesByCategoryName(data)]; case 3: resources = _b.sent(); if (resources === null) { console.error("无法获取分类 ".concat(category.name, " 的资源,已跳过!")); return [3 /*break*/, 8]; } console.debug("获取分类 ".concat(category.name, " 的资源"), resources); _a = 0, resources_1 = resources; _b.label = 4; case 4: if (!(_a < resources_1.length)) return [3 /*break*/, 8]; resource = resources_1[_a]; resourceId = resource.resourceId; resourceData = { resourceId: resourceId, reqtoken: reqtoken() }; return [4 /*yield*/, addPCPlayPV(resourceData)]; case 5: result = _b.sent(); if (result) { console.debug("成功完成资源 [".concat(resourceId, "]:").concat(resource.title)); done++; } else { console.error("无法完成资源 ".concat(resourceId, ",已跳过!")); failed++; } return [4 /*yield*/, likePC(resourceData)]; case 6: likeResult = _b.sent(); if (likeResult) { console.debug("成功点赞资源 [".concat(resourceId, "]!")); liked++; } else { console.error("资源点赞失败 [".concat(resourceId, "],已跳过!")); } _b.label = 7; case 7: _a++; return [3 /*break*/, 4]; case 8: _i++; return [3 /*break*/, 2]; case 9: beforeDone = done; checkSuccess = setInterval(function () { if (done !== 0) { if (done === beforeDone) { showMessage("成功完成 ".concat(done, "/").concat(failed, " 个资源,点赞 ").concat(liked, " 个!"), "green"); clearInterval(checkSuccess); } else { beforeDone = done; } } }, 500); return [2 /*return*/]; } }); }); } function taskFinalExamination() { return __awaiter(this, void 0, void 0, function () { var supportedFinal, gradeLevel, paperName, papers_1; return __generator(this, function (_a) { switch (_a.label) { case 0: supportedFinal = libs.supportedFinal; gradeLevel = accountGradeLevel(); if (!supportedFinal.hasOwnProperty(gradeLevel)) return [3 /*break*/, 2]; paperName = supportedFinal[gradeLevel]; papers_1 = libs[paperName]; papers_1 = papers_1.map(function (it) { return { question: it.question, answer: toAnswer(it.answer) }; }); return [4 /*yield*/, emulateExamination(papers_1.map(function (it) { return it.answer; }), "#app > div > div.home-container > div > div > div > div > div > button", "#app > div > div.home-container > div > div > div > div > div > div.exam-content-btnbox > button", "#app > div > div.home-container > div > div > div > div > div > div.exam-content-btnbox > div > button.ant-btn.ant-btn-primary", function (_, question) { var _a = accurateFind(papers_1, question) || fuzzyFind(papers_1, question), answer = _a.answer, realQuestion = _a.realQuestion; return { answer: answer, matchedQuestion: realQuestion, }; }, "期末考试", 10 // TODO 这个 10 是干什么的我还没搞清楚,之后再说 )]; case 1: _a.sent(); return [3 /*break*/, 3]; case 2: showMessage("你的年级 [".concat(gradeLevel, "] 暂未支持期末考试!"), "red"); return [2 /*return*/]; case 3: return [2 /*return*/]; } }); }); } function showMessage(text, color) { Toastify({ text: text, duration: toastifyDuration, newWindow: true, gravity: toastifyGravity, position: toastifyPosition, stopOnFocus: true, style: { background: color }, }).showToast(); } function featureNotAvailable(name) { if (name === void 0) { name = "(未知)"; } showMessage("".concat(name, " 功能当前不可用,请尝试刷新页面。如果问题依旧请上报这个 bug!"), "red"); } function isNone(obj) { return obj == undefined || obj == null; } function getGMValue(name, defaultValue) { var value = GM_getValue(name); if (isNone(value)) { value = defaultValue; GM_setValue(name, defaultValue); } return value; } function waitForElementLoaded(querySelector) { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { return [2 /*return*/, new Promise(function (resolve, reject) { var attempts = 0; var tryFind = function () { var element = document.querySelector(querySelector); if (element) { resolve(element); } else { attempts++; if (attempts >= 30) { console.error("无法找到元素 [".concat(querySelector, "],已放弃!")); reject(); } else { setTimeout(tryFind, 250 * Math.pow(1.1, attempts)); } } }; tryFind(); })]; }); }); } function removeSpaces(string) { return string.replace(/\s*/g, ""); } function toDisplayAnswer(answer) { var alphas = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""); var result = ""; for (var _i = 0, _a = answer.split(","); _i < _a.length; _i++) { var singleAnswer = _a[_i]; var index = Number(singleAnswer); result = result + alphas[index]; } return result; } function toAnswer(answers) { var alphas = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""); var result = ""; for (var _i = 0, answers_1 = answers; _i < answers_1.length; _i++) { var answer = answers_1[_i]; result = result + alphas.indexOf(answer); } return result; } function nodeListToArray(nodeList) { return Array.prototype.slice.call(nodeList); } function converToGenericGradeLevel(gradeLevel) { var mapping = { 七年级: "初一", 八年级: "初二", 九年级: "初三", }; return mapping[gradeLevel]; } function arrayDiff(array1, array2) { return array1.concat(array2).filter(function (v, _, array) { return array.indexOf(v) === array.lastIndexOf(v); }); } function accurateFind(papers, question) { var result = papers.find(function (it) { return removeSpaces(it.question) === question; }); if (!isNone(result)) { console.debug("精确匹配问题:".concat(question, " → ").concat(result.question)); return { answer: result.answer, realQuestion: question }; } else { return null; } } function fuzzyFind(papers, question) { var chars = question.split(""); var length = chars.length; var percentages = []; for (var _i = 0, papers_2 = papers; _i < papers_2.length; _i++) { var paper = papers_2[_i]; var questionChars = paper.question.split(""); var diff = arrayDiff(chars, questionChars); var diffLength = diff.length; var percentage = diffLength / length; percentages.push({ question: paper.question, answer: paper.answer, unconfidence: percentage, }); } var theMostConfident = percentages.sort(function (a, b) { return a.unconfidence - b.unconfidence; })[0]; var theMostConfidentQuestion = theMostConfident.question; var confidence = 1 - theMostConfident.unconfidence; console.debug("模糊匹配问题(".concat(confidence, "):").concat(question, " → ").concat(theMostConfidentQuestion)); return { answer: theMostConfident.answer, realQuestion: theMostConfidentQuestion, }; } var container = document.createElement("div"); container.setAttribute("id", "qjh-menu"); container.innerHTML = "\n\n