// ==UserScript==
// @name 深圳大学大物实验预习题小助手增强版 (modified by WYK)
// @namespace https://github.com/AnotiaWang
// @version 0.56
// @description 自动提供参考答案
// @author AnotiaWang
// @match http://172.31.80.102:7101/Student/ReadyForExam/*
// @match http://172.31.80.245:8101/Student/ReadyForExam/*
// @match http://172.31.80.45:8101/Student/ReadyForExam/*
// @match http://172.31.80.16:8101/Student/ReadyForExam/*
// @match http://172.31.80.95:8101/Student/ReadyForExam/*
// @match http://172.31.80.1:8101/Student/ReadyForExam/*
// @match http://172.31.80.102:8101/Student/ReadyForExam/*
// @match http://172.31.80.14:7101/Student/ReadyForExam/*
// @grant none
// @require https://unpkg.com/[email protected]/dist/ajaxhook.min.js
// @license WTFPL
// ==/UserScript==
(function(e, a) { for(var i in a) e[i] = a[i]; }(window, /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // identity function for calling harmony imports with the correct context
/******/ __webpack_require__.i = function(value) { return value; };
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 3);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
exports.configEvent = configEvent;
exports.hook = hook;
exports.unHook = unHook;
/*
* author: wendux
* email: [email protected]
* source code: https://github.com/wendux/Ajax-hook
*/
// Save original XMLHttpRequest as _rxhr
var realXhr = "_rxhr";
function configEvent(event, xhrProxy) {
var e = {};
for (var attr in event) {
e[attr] = event[attr];
} // xhrProxy instead
e.target = e.currentTarget = xhrProxy;
return e;
}
function hook(proxy) {
// Avoid double hookAjax
window[realXhr] = window[realXhr] || XMLHttpRequest;
XMLHttpRequest = function XMLHttpRequest() {
var xhr = new window[realXhr]();
// We shouldn't hookAjax XMLHttpRequest.prototype because we can't
// guarantee that all attributes are on the prototype。
// Instead, hooking XMLHttpRequest instance can avoid this problem.
for (var attr in xhr) {
var type = "";
try {
type = _typeof(xhr[attr]); // May cause exception on some browser
} catch (e) {}
if (type === "function") {
// hookAjax methods of xhr, such as `open`、`send` ...
this[attr] = hookFunction(attr);
} else {
Object.defineProperty(this, attr, {
get: getterFactory(attr),
set: setterFactory(attr),
enumerable: true
});
}
}
var that = this;
xhr.getProxy = function () {
return that;
};
this.xhr = xhr;
};
// Generate getter for attributes of xhr
function getterFactory(attr) {
return function () {
var v = this.hasOwnProperty(attr + "_") ? this[attr + "_"] : this.xhr[attr];
var attrGetterHook = (proxy[attr] || {})["getter"];
return attrGetterHook && attrGetterHook(v, this) || v;
};
}
// Generate setter for attributes of xhr; by this we have an opportunity
// to hookAjax event callbacks (eg: `onload`) of xhr;
function setterFactory(attr) {
return function (v) {
var xhr = this.xhr;
var that = this;
var hook = proxy[attr];
// hookAjax event callbacks such as `onload`、`onreadystatechange`...
if (attr.substring(0, 2) === 'on') {
that[attr + "_"] = v;
xhr[attr] = function (e) {
e = configEvent(e, that);
var ret = proxy[attr] && proxy[attr].call(that, xhr, e);
ret || v.call(that, e);
};
} else {
//If the attribute isn't writable, generate proxy attribute
var attrSetterHook = (hook || {})["setter"];
v = attrSetterHook && attrSetterHook(v, that) || v;
this[attr + "_"] = v;
try {
// Not all attributes of xhr are writable(setter may undefined).
xhr[attr] = v;
} catch (e) {}
}
};
}
// Hook methods of xhr.
function hookFunction(fun) {
return function () {
var args = [].slice.call(arguments);
if (proxy[fun]) {
var ret = proxy[fun].call(this, args, this.xhr);
// If the proxy return value exists, return it directly,
// otherwise call the function of xhr.
if (ret) return ret;
}
return this.xhr[fun].apply(this.xhr, args);
};
}
// Return the real XMLHttpRequest
return window[realXhr];
}
function unHook() {
if (window[realXhr]) XMLHttpRequest = window[realXhr];
window[realXhr] = undefined;
}
/***/ }),
/* 1 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.proxy = proxy;
exports.unProxy = unProxy;
var _xhrHook = __webpack_require__(0);
var events = ['load', 'loadend', 'timeout', 'error', 'readystatechange', 'abort']; /*
* author: wendux
* email: [email protected]
* source code: https://github.com/wendux/Ajax-hook
*/
var eventLoad = events[0],
eventLoadEnd = events[1],
eventTimeout = events[2],
eventError = events[3],
eventReadyStateChange = events[4],
eventAbort = events[5];
var singleton,
prototype = 'prototype';
function proxy(proxy) {
if (singleton) throw "Proxy already exists";
return singleton = new Proxy(proxy);
}
function unProxy() {
singleton = null;
(0, _xhrHook.unHook)();
}
function trim(str) {
return str.replace(/^\s+|\s+$/g, '');
}
function getEventTarget(xhr) {
return xhr.watcher || (xhr.watcher = document.createElement('a'));
}
function triggerListener(xhr, name) {
var xhrProxy = xhr.getProxy();
var callback = 'on' + name + '_';
var event = (0, _xhrHook.configEvent)({ type: name }, xhrProxy);
xhrProxy[callback] && xhrProxy[callback](event);
var evt;
if (typeof Event === 'function') {
evt = new Event(name, { bubbles: false });
} else {
// https://stackoverflow.com/questions/27176983/dispatchevent-not-working-in-ie11
evt = document.createEvent('Event');
evt.initEvent(name, false, true);
}
getEventTarget(xhr).dispatchEvent(evt);
}
function Handler(xhr) {
this.xhr = xhr;
this.xhrProxy = xhr.getProxy();
}
Handler[prototype] = Object.create({
resolve: function resolve(response) {
var xhrProxy = this.xhrProxy;
var xhr = this.xhr;
xhrProxy.readyState = 4;
xhr.resHeader = response.headers;
xhrProxy.response = xhrProxy.responseText = response.response;
xhrProxy.statusText = response.statusText;
xhrProxy.status = response.status;
triggerListener(xhr, eventReadyStateChange);
triggerListener(xhr, eventLoad);
triggerListener(xhr, eventLoadEnd);
},
reject: function reject(error) {
this.xhrProxy.status = 0;
triggerListener(this.xhr, error.type);
triggerListener(this.xhr, eventLoadEnd);
}
});
function makeHandler(next) {
function sub(xhr) {
Handler.call(this, xhr);
}
sub[prototype] = Object.create(Handler[prototype]);
sub[prototype].next = next;
return sub;
}
var RequestHandler = makeHandler(function (rq) {
var xhr = this.xhr;
rq = rq || xhr.config;
xhr.withCredentials = rq.withCredentials;
xhr.open(rq.method, rq.url, rq.async !== false, rq.user, rq.password);
for (var key in rq.headers) {
xhr.setRequestHeader(key, rq.headers[key]);
}
xhr.send(rq.body);
});
var ResponseHandler = makeHandler(function (response) {
this.resolve(response);
});
var ErrorHandler = makeHandler(function (error) {
this.reject(error);
});
function Proxy(proxy) {
var onRequest = proxy.onRequest,
onResponse = proxy.onResponse,
onError = proxy.onError;
function handleResponse(xhr, xhrProxy) {
var handler = new ResponseHandler(xhr);
if (!onResponse) return handler.resolve();
var ret = {
response: xhrProxy.response,
status: xhrProxy.status,
statusText: xhrProxy.statusText,
config: xhr.config,
headers: xhr.resHeader || xhr.getAllResponseHeaders().split('\r\n').reduce(function (ob, str) {
if (str === "") return ob;
var m = str.split(":");
ob[m.shift()] = trim(m.join(':'));
return ob;
}, {})
};
onResponse(ret, handler);
}
function onerror(xhr, xhrProxy, e) {
var handler = new ErrorHandler(xhr);
var error = { config: xhr.config, error: e };
if (onError) {
onError(error, handler);
} else {
handler.next(error);
}
}
function preventXhrProxyCallback() {
return true;
}
function errorCallback(xhr, e) {
onerror(xhr, this, e);
return true;
}
function stateChangeCallback(xhr, xhrProxy) {
if (xhr.readyState === 4 && xhr.status !== 0) {
handleResponse(xhr, xhrProxy);
} else if (xhr.readyState !== 4) {
triggerListener(xhr, eventReadyStateChange);
}
return true;
}
return (0, _xhrHook.hook)({
onload: preventXhrProxyCallback,
onloadend: preventXhrProxyCallback,
onerror: errorCallback,
ontimeout: errorCallback,
onabort: errorCallback,
onreadystatechange: function onreadystatechange(xhr) {
return stateChangeCallback(xhr, this);
},
open: function open(args, xhr) {
var _this = this;
var config = xhr.config = { headers: {} };
config.method = args[0];
config.url = args[1];
config.async = args[2];
config.user = args[3];
config.password = args[4];
config.xhr = xhr;
var evName = 'on' + eventReadyStateChange;
if (!xhr[evName]) {
xhr[evName] = function () {
return stateChangeCallback(xhr, _this);
};
}
var defaultErrorHandler = function defaultErrorHandler(e) {
onerror(xhr, _this, (0, _xhrHook.configEvent)(e, _this));
};
[eventError, eventTimeout, eventAbort].forEach(function (e) {
var event = 'on' + e;
if (!xhr[event]) xhr[event] = defaultErrorHandler;
});
// 如果有请求拦截器,则在调用onRequest后再打开链接。因为onRequest最佳调用时机是在send前,
// 所以我们在send拦截函数中再手动调用open,因此返回true阻止xhr.open调用。
//
// 如果没有请求拦截器,则不用阻断xhr.open调用
if (onRequest) return true;
},
send: function send(args, xhr) {
var config = xhr.config;
config.withCredentials = xhr.withCredentials;
config.body = args[0];
if (onRequest) {
// In 'onRequest', we may call XHR's event handler, such as `xhr.onload`.
// However, XHR's event handler may not be set until xhr.send is called in
// the user's code, so we use `setTimeout` to avoid this situation
var req = function req() {
onRequest(config, new RequestHandler(xhr));
};
config.async === false ? req() : setTimeout(req);
return true;
}
},
setRequestHeader: function setRequestHeader(args, xhr) {
// Collect request headers
xhr.config.headers[args[0].toLowerCase()] = args[1];
return true;
},
addEventListener: function addEventListener(args, xhr) {
var _this = this;
if (events.indexOf(args[0]) !== -1) {
var handler = args[1];
getEventTarget(xhr).addEventListener(args[0], function (e) {
var event = (0, _xhrHook.configEvent)(e, _this);
event.type = args[0];
event.isTrusted = true;
handler.call(_this, event);
});
return true;
}
},
getAllResponseHeaders: function getAllResponseHeaders(_, xhr) {
var headers = xhr.resHeader;
if (headers) {
var header = "";
for (var key in headers) {
header += key + ': ' + headers[key] + '\r\n';
}
return header;
}
},
getResponseHeader: function getResponseHeader(args, xhr) {
var headers = xhr.resHeader;
if (headers) {
return headers[(args[0] || '').toLowerCase()];
}
}
});
}
/***/ }),
/* 2 */,
/* 3 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.ah = undefined;
var _xhrHook = __webpack_require__(0);
var _xhrProxy = __webpack_require__(1);
// ah(ajax hook)
/*
* author: wendux
* email: [email protected]
* source code: https://github.com/wendux/Ajax-hook
*/
var ah = exports.ah = {
proxy: _xhrProxy.proxy,
unProxy: _xhrProxy.unProxy,
hook: _xhrHook.hook,
unHook: _xhrHook.unHook
};
/***/ })
/******/ ])));
ah.proxy({
//请求发起前进入
onRequest: (config, handler) => {
handler.next(config);
},
//请求发生错误时进入,比如超时;注意,不包括http状态码错误,如404仍然会认为请求成功
onError: (err, handler) => {
console.log(err.type)
handler.next(err)
},
//请求成功后进入
onResponse: (response, handler) => {
if (response.config.url == "/Student/ReadyForExam/GetPaperContent") {
//各类正则匹配获取数据
let finalArr = {}
let obj = String(response.response).replace(/\\r\\n/g, "")
let data = JSON.parse(obj).OtherDate
let arrHtml = data.match(/<Question Type=(.*?)<\/Question>/g)
for (const i in arrHtml) {
try {
let qusArr = arrHtml[i].match(/<Describe>(.*?)<\/Describe>/)[0].match(/Text="(.*?)\"/g)
let quse = ""
let ans = arrHtml[i].match(/<StdAnswer>(.*?)<\/StdAnswer>/)[0].slice(11, -12)
for (const j in qusArr) {
quse += qusArr[j].replace(/ /g, "").slice(6, -1)
}
if (!finalArr[arrHtml[i].slice(16, 18)]) {
finalArr[arrHtml[i].slice(16, 18)] = []
}
finalArr[arrHtml[i].slice(16, 18)].push({
qusetion: quse,
answer: ans
})
} catch {}
}
//需要延缓答案生成时间,保证答案被生成
setTimeout(function () {
for (const i in finalArr) {
//利用之前的finalArr搜索doc
let question = document.getElementById(i.toLowerCase())
for (let j = 0; j < question.childNodes.length; j = j + 2) {
let item = question.childNodes[j].childNodes[0]
let answerBox = question.childNodes[j].childNodes[1]
let lastSpan = item.getElementsByTagName("span")[item.getElementsByTagName("span").length - 1]
let aSpan = document.createElement("span")
let answer = finalArr[i][j / 2].answer
aSpan.style = "color: red;font-size: 16px;"
aSpan.innerHTML = answer
lastSpan.append(aSpan)
let inputBoxes
// 选择答案
switch (i) {
// 判断题
case 'TF':
inputBoxes = answerBox.getElementsByTagName('input')
inputBoxes[answer === '正确' ? 0 : 1].checked = true;
break
// 多选
case 'MS':
inputBoxes = answerBox.getElementsByTagName('input')
for (let k in inputBoxes) {
if (answer.includes(inputBoxes[k].value)) {
inputBoxes[k].checked = true
}
}
break
// 单选
case 'SS':
inputBoxes = answerBox.getElementsByTagName('input')
for (let k of inputBoxes) {
if (k.value === answer) {
k.checked = true
break
}
}
break
// 填空
case 'BL':
inputBoxes = answerBox.getElementsByTagName('select')
const answers = answer.split(';')
for (let k in inputBoxes) {
const selectValue = answers[k]
for (const e in inputBoxes[k]) {
const optionElement = inputBoxes[k][e]
if (optionElement.value === selectValue) {
optionElement.selected = true
break
}
}
}
break
default:
break
}
}
}
}, 2000)
}
//拦截处理完数据发回给网页
handler.next(response)
}
})