- /* eslint-disable no-multi-spaces */
-
- // ==UserScript==
- // @name 中国大学MOOC反检测
- // @name:zh-CN 中国大学MOOC反检测
- // @name:en iCourse163 Anti-detect
- // @namespace iCourse163-Anti-detect
- // @version 0.1
- // @description 防止中国大学MOOC页面检测模拟点击类插件/脚本(目前已发现的检测只有检测模拟点击类的)
- // @description:zh-CN 防止中国大学MOOC页面检测模拟点击类插件/脚本(目前已发现的检测只有检测模拟点击类的)
- // @description:en Prevent plugins(e.g. userscripts) being detected by 1course163 while simulating clicks on webpage
- // @author PY-DNG
- // @license WTFPL - See https://www.wtfpl.net/
- // @match http*://www.icourse163.org/*
- // @icon https://pic.jitudisk.com/public/2022/06/04/59e467b286dcb.png
- // @grant none
- // @run-at document-start
- // ==/UserScript==
-
- /**
- * Copyright © 2022 PY-DNG <NO EMAIL HERE>
- * This work is free. You can redistribute it and/or modify it under the
- * terms of the Do What The Fuck You Want To Public License, Version 2,
- * as published by Sam Hocevar. See http://www.wtfpl.net/ for more details.
- **/
-
- /**
- * This program is free software. It comes without any warranty, to
- * the extent permitted by applicable law. You can redistribute it
- * and/or modify it under the terms of the Do What The Fuck You Want
- * To Public License, Version 2, as published by Sam Hocevar. See
- * http://www.wtfpl.net/ for more details.
- **/
-
- (function(window, document) {
- /* Protect.js by PY-DNG */
- /* !IMPORTANT! MAKE SURE THIS CODE IS EXECUTED BEFORE WINDOW ONLOAD !IMPORTANT! */
-
- try {
- // Unpolluted resources
- const iframe = document.createElement('iframe');
- iframe.srcdoc = '<html></html>';
- iframe.style.position = 'fixed';
- iframe.style.width = iframe.style.height = '0';
- (document.body ? document.body : document.head).appendChild(iframe);
- const UNPOLLUTED = new Proxy({}, {
- get: function(target, property, receiver) {
- switch (property) {
- case 'iframe': return iframe;
- default: {
- let value = iframe;
- for (const prop of property.split(/[\.\/]/)) {
- value = value[prop];
- }
- return value;
- }
- }
- }
- });
-
- // Protect addEventListener & removeEventListener
- defineProperty(Node.prototype, 'addEventListener', addEventListener);
- defineProperty(Node.prototype, 'removeEventListener', UNPOLLUTED['contentWindow.EventTarget.prototype.removeEventListener']);
- for (const func of ['createElement', 'createElementNS', 'querySelector', 'querySelectorAll', 'getElementById', 'getElementsByClassName', 'getElementsByName', 'getElementsByTagName', 'getElementsByTagNameNS']) {
- hookAPIFunc(func);
- }
-
- // Protect root & root-like elements
- for (const elm of [document.querySelector('#g-body'), document.documentElement, document, window]) {
- const addEventListener = UNPOLLUTED['contentWindow.EventTarget.prototype.addEventListener'];
- typeof elm === 'object' && elm !== null && hookElm(elm);
- }
-
- function hookAPIFunc(funcName) {
- for (const api of ['Document', 'Element']) {
- const API = window[api];
- const proto = API.prototype;
- proto.hasOwnProperty(funcName) && defineProperty(proto, funcName, function() {
- let value = UNPOLLUTED['contentWindow.'+api+'.prototype.'+funcName].apply(this, Array.from(arguments));
-
- if (value instanceof NodeList) {
- value = Array.prototype.map.call(value, (elm) => (hookElm(elm)));
- value.item = (i) => (i < value.length ? value[i] : null);
- } else if (value instanceof EventTarget) {
- value = hookElm(value);
- }
- return value;
- });
- }
- }
-
- function hookElm(elm) {
- defineProperty(elm, 'addEventListener', addEventListener);
- defineProperty(elm, 'removeEventListener', UNPOLLUTED['contentWindow.EventTarget.prototype.removeEventListener']);
- return elm;
- }
-
- function defineProperty(obj, prop, value) {
- // Check repeat
- if (obj._protected && obj._protected[prop] && obj[prop].toString() === value.toString()) {
- return false;
- }
-
- // Define property
- define(obj, prop, value, true);
-
- // Prevent repeat
- !obj._protected && define(obj, '_protected', {}, false);
- define(obj._protected, prop, true, true);
-
- return true;
-
- function define(obj, prop, value, enumerable) {
- Object.defineProperty(obj, prop, {
- value: value,
- writable: false,
- configurable: false,
- enumerable: enumerable
- });
- }
- }
-
- function addEventListener(type, listener) {
- const banlist = ['function(a5){if(', 'function(a6){a6'];
- for (const bancode of banlist) {
- if (type === 'click' && listener.toString().startsWith(bancode)) {
- return;
- }
- }
- return UNPOLLUTED['contentWindow.EventTarget.prototype.addEventListener'].apply(this, Array.from(arguments));
- }
-
- function toString(o) {
- return UNPOLLUTED['contentWindow.Object.prototype.toString'].call(o);
- }
- } catch (err) {
- throw err;
- debugger;
- }
- }).apply(null, typeof unsafeWindow === 'object' ? [unsafeWindow, unsafeWindow.document] : [window, document]);