Merge branch 'patch-1' into 'master'

Added the stealthy overlay, no version number change yet

See merge request MrFry/moodle-test-userscript!2
This commit is contained in:
MrFry 2020-09-13 06:54:53 +00:00
commit 6da775af3e

View file

@ -31,6 +31,7 @@
// @match https://qmining.frylabs.net/*
// @match http://qmining.frylabs.net/*
// @noframes
// @run-at document-start
// @grant GM_getResourceText
// @grant GM_info
// @grant GM_getValue
@ -38,6 +39,7 @@
// @grant GM_deleteValue
// @grant GM_xmlhttpRequest
// @grant GM_openInTab
// @grant unsafeWindow
// @license GNU General Public License v3.0 or later
// @supportURL qmining.frylabs.net
// @contributionURL qmining.frylabs.net
@ -208,6 +210,86 @@
// all dom getting stuff are in this sections, so on
// moodle dom change, stuff breaks here
//Stealth by An0 with love
function StealthOverlay() { //call this before the document scripts
const document = window.document;
const neverEqualPlaceholder = Symbol(`never equal`); //block probing for undefined values in the hooks
let shadowRootHost = neverEqualPlaceholder;
let shadowRootNewHost = neverEqualPlaceholder;
const apply = Reflect.apply; //save some things in case they get hooked (only for unsafe contexts)
if(unsafeWindow.Error.hasOwnProperty('stackTraceLimit')) {
Reflect.defineProperty(unsafeWindow.Error, 'stackTraceLimit', { value: undefined, writable: false, enumerable: false, configurable: false });
}
const shadowGetHandler = { apply: (target, thisArg, argumentsList) => apply(target, (thisArg === shadowRootHost) ? shadowRootNewHost : thisArg, argumentsList) };
const original_attachShadow = unsafeWindow.Element.prototype.attachShadow;
const attachShadowProxy = new Proxy(original_attachShadow, shadowGetHandler);
unsafeWindow.Element.prototype.attachShadow = attachShadowProxy;
const getShadowRootProxy = new Proxy(Object.getOwnPropertyDescriptor(unsafeWindow.Element.prototype, 'shadowRoot').get, shadowGetHandler);
Object.defineProperty(unsafeWindow.Element.prototype, 'shadowRoot', { get: getShadowRootProxy });
const getHostHandler = { apply: function() { let result = apply(...arguments); return (result === shadowRootNewHost) ? shadowRootHost : result; } };
const getHostProxy = new Proxy(Object.getOwnPropertyDescriptor(unsafeWindow.ShadowRoot.prototype, 'host').get, getHostHandler);
Object.defineProperty(unsafeWindow.ShadowRoot.prototype, 'host', { get: getHostProxy });
const shadowRootSetInnerHtml = Object.getOwnPropertyDescriptor(ShadowRoot.prototype, 'innerHTML').set;
const documentFragmentGetChildren = Object.getOwnPropertyDescriptor(DocumentFragment.prototype, 'children').get;
const documentGetBody = Object.getOwnPropertyDescriptor(Document.prototype, 'body').get;
const nodeAppendChild = Node.prototype.appendChild;
const overlay = document.createElement('div');
overlay.style.cssText = "position:absolute;left:0;top:0";
const addOverlay = () => {
shadowRootHost = apply(documentGetBody, document, []);
const shadowRoot = apply(original_attachShadow, shadowRootHost, [{mode:'closed'}]);
apply(shadowRootSetInnerHtml, shadowRoot, [`<div><slot></slot></div>`]);
shadowRootNewHost = apply(documentFragmentGetChildren, shadowRoot, [])[0];
apply(nodeAppendChild, shadowRoot, [overlay]);
};
if (!document.body) {
document.addEventListener('DOMContentLoaded', addOverlay);
}
else {
addOverlay();
}
return overlay;
}
const overlay = StealthOverlay();
function createHoverOver(target) {
const overlayElement = document.createElement('div');
overlayElement.style.cssText = "position:fixed; pointer-events: none; user-select: none; z-index:10000";
overlay.append(overlayElement);
let currX, currY, currWidth, currHeight;
const copyBoundingRect = () => {
let { x, y, width, height } = target.getBoundingClientRect();
if(x !== currX) { overlayElement.style.left = x + 'px'; currX = x; }
if(y !== currY) { overlayElement.style.top = y + 'px'; currY = y; }
if(width !== currWidth) { overlayElement.style.width = width + 'px'; currWidth = width; }
if(height !== currHeight) { overlayElement.style.height = height + 'px'; currHeight = height; }
};
copyBoundingRect();
const interval = setInterval(copyBoundingRect, 30);
overlayElement.destroy = () => {
clearInterval(interval);
overlayElement.remove();
};
return overlayElement;
}
class QuestionsPageModell {
GetAllQuestionsDropdown () {
if (logElementGetting) { Log('getting dropdown question') }
@ -681,7 +763,12 @@
console.time('main')
timerStarted = true
Init()
if(document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', Init)
}
else {
Init()
}
}
function AfterLoad () {
@ -716,8 +803,8 @@
}
if (forceTestPage || forceResultPage || forceDefaultPage) {
if (document.getElementById('scriptMessage')) {
document.getElementById('scriptMessage').style.background = 'green'
if (overlay.querySelector('#scriptMessage')) {
overlay.querySelector('#scriptMessage').style.background = 'green'
}
}
}
@ -852,7 +939,7 @@
lastestVersion = inf.version
motd = inf.motd
subjInfo = inf.subjinfo
document.getElementById('infoMainDiv').innerText = `${subjInfo.subjects} tárgy, ${subjInfo.questions} kérdés. Felh #${inf.uid}`
overlay.querySelector('#infoMainDiv').innerText = `${subjInfo.subjects} tárgy, ${subjInfo.questions} kérdés. Felh #${inf.uid}`
// FIXME: if cwith() throws an unhandled error it sais server is not avaible
cwith()
}).catch(() => {
@ -1299,7 +1386,12 @@
if (results[0].match === 100) { // if the result is 100% correct
if (type !== 'radio' || toColor.length === 1) { // FIXME why not radio
for (let i = 0; i < toColor.length; i++) { // going through "toColor"
answers[toColor[i]].style.backgroundColor = '#8cff66'
let highlight = createHoverOver(answers[toColor[i]]);
Object.assign(highlight.style, {
border: "7px solid rgba(100, 240, 100, 0.8)",
borderRadius: "10px",
margin: "-13px 0 0 -8px"
});
}
}
} // and coloring the correct index
@ -1328,11 +1420,7 @@
// : Minor UI stuff {{{
function ClearAllMessages () {
let elem = document.getElementById('scriptMessage')
while (elem) {
elem.parentNode.removeChild(elem)
elem = document.getElementById('scriptMessage')
}
overlay.querySelectorAll('#scriptMessage').forEach(x => x.remove())
}
// shows a message with "msg" text, "matchPercent" tip and transp, and "timeout" time
@ -1360,7 +1448,7 @@
isSimpleMessage = true
}
var appedtTo = document.body // will be appended here
var appedtTo = overlay // will be appended here
var width = window.innerWidth - window.innerWidth / 6 // with of the box
var startFromTop = 25 // top distance
@ -1551,7 +1639,7 @@
// shows a fancy menu
function ShowMenu () {
try {
var appedtTo = document.body // will be appended here
var appedtTo = overlay // will be appended here
// mainDiv.style.left = (window.innerWidth - width) / 2 + 'px';
@ -1763,7 +1851,7 @@
}
function SafeGetElementById (id, next) {
let element = document.getElementById(id)
let element = overlay.querySelector('#' + id)
if (element) {
next(element)
} else {