// ==UserScript==
// @name laat alle antwoorden zien
// @version 0.6
// @description voeg "laat alle antwoorden zien" toe
// @match https://apps.noordhoff.nl/*
// @run-at document-start
// @author Jouke van Dam
// @namespace https://greasyfork.org/users/1511158
// ==/UserScript==
(function() {
'use strict';
// inject real script into page context (avoids userscript sandbox issues)
const injectedCode = function() {
'use strict';
const TAG = '[NoordhoffInjector]';
console.log(TAG, 'running in page context — initializing interceptor');
// helper: try to parse JSON and force isTeacher if relevant; return modified string or null if nothing changed
function tryModifyResponseText(text) {
if (!text) return null;
try {
const obj = JSON.parse(text);
if (obj && obj.data && obj.data.me) {
console.log(TAG, 'found data.me — original isTeacher =', obj.data.me.isTeacher);
obj.data.me.isTeacher = true;
console.log(TAG, 'forced data.me.isTeacher = true');
return JSON.stringify(obj);
}
} catch (e) {
// not JSON — ignore
}
return null;
}
// ------- patch fetch -------
try {
const _fetch = window.fetch;
window.fetch = async function(input, init) {
try {
const url = (typeof input === 'string') ? new URL(input, location.origin).href : (input && input.url) || '';
if (url && url.includes('/se/api/')) {
console.log(TAG, 'fetch -> intercepted request to', url, 'init:', init);
const resp = await _fetch.apply(this, arguments);
const clone = resp.clone();
const text = await clone.text();
const modified = tryModifyResponseText(text);
if (modified !== null) {
const newHeaders = new Headers(resp.headers);
if (!newHeaders.has('content-type')) newHeaders.set('content-type', 'application/json');
const newResp = new Response(modified, {
status: resp.status,
statusText: resp.statusText,
headers: newHeaders
});
console.log(TAG, 'fetch -> returning modified Response for', url);
return newResp;
} else {
console.log(TAG, 'fetch -> response had no data.me; passing through for', url);
return resp;
}
}
} catch (err) {
console.error(TAG, 'fetch wrapper error', err);
}
return _fetch.apply(this, arguments);
};
console.log(TAG, 'fetch patched');
} catch (e) {
console.error(TAG, 'failed to patch fetch', e);
}
// ------- patch XMLHttpRequest -------
try {
const origOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function(method, url) {
try {
this._ni_url = url ? new URL(url, location.origin).href : '';
} catch (e) {
this._ni_url = url || '';
}
return origOpen.apply(this, arguments);
};
const origSend = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function(body) {
try {
const url = this._ni_url || '';
if (url && url.includes('/se/api/')) {
console.log(TAG, 'XHR -> send to', url, 'body preview:', (typeof body === 'string') ? body.slice(0, 300) : (body ? '[object]' : '[empty]'));
const onLoad = () => {
try {
const txt = this.responseText;
const modified = tryModifyResponseText(txt);
if (modified !== null) {
// try best-effort to override responseText/response
try {
Object.defineProperty(this, 'responseText', { value: modified, configurable: true });
Object.defineProperty(this, 'response', { value: modified, configurable: true });
console.log(TAG, 'XHR -> modified responseText/response for', url);
} catch (e) {
console.warn(TAG, 'XHR -> could not redefine responseText/response on instance', e);
}
} else {
console.log(TAG, 'XHR -> response had no data.me for', url);
}
} catch (e) {
console.error(TAG, 'XHR onload handler error', e);
}
};
this.addEventListener('load', onLoad);
}
} catch (e) {
console.error(TAG, 'XHR send wrapper error', e);
}
return origSend.apply(this, arguments);
};
console.log(TAG, 'XMLHttpRequest patched');
} catch (e) {
console.error(TAG, 'failed to patch XHR', e);
}
console.log(TAG, 'interceptor active — forcing data.me.isTeacher = true for /se/api/ responses when present');
};
// create script tag and inject into page
const s = document.createElement('script');
s.setAttribute('data-noordhoff-inject', '1');
s.textContent = '(' + injectedCode.toString() + ')();';
// If documentElement exists, append immediately; otherwise wait DOMContentLoaded
if (document.documentElement) {
document.documentElement.appendChild(s);
console.log('[NoordhoffInjector] injected script tag into page');
} else {
window.addEventListener('DOMContentLoaded', () => {
document.documentElement.appendChild(s);
console.log('[NoordhoffInjector] injected script tag after DOMContentLoaded');
});
}
})();