- // 源代码
- (function () {
- const KEY_LOCALCDN = 'LOCAL-CDN';
- const KEY_LOCALCDN_VERSION = 'version';
- const VALUE_LOCALCDN_VERSION = '0.1';
- const KEY_POLYFILL = 'wenku8-plus-injecter';
- GM_PolyFill(KEY_POLYFILL);
- DoLog();
- DoLog(LogLevel.Success, 'wenku8+ loader loaded successfully on this page');
-
- const main_url = 'https://gf.qytechs.cn/scripts/416310/code/script.user.js';
- const loader_url = 'https://gf.qytechs.cn/scripts/437461/code/script.js';
-
- dealDocument();
-
- function dealDocument(oDom=document) {
- // Hook window.open
- const open = window.open;
- window.open = openWithInjector;
- function openWithInjector(strUrl, strWindowName, strWindowFeatures) {
- const newTab = open(strUrl, strWindowName, strWindowFeatures);
- const oDom = newTab.document;
- const oWin = newTab.window;
- oWin.addEventListener('load', function() {
- const script = oDom.createElement('script');
- script.src = loader_url;
- oWin.document.head.appendChild(script);
- });
- return newTab;
- }
-
- // Hook <a>
- hooklinks();
- setInterval(hooklinks, 200);
-
- // Load wenku8+
- const script = oDom.createElement('script');
- script.src = main_url;
- document.head.appendChild(script);
-
- function hooklinks() {
- // Hook <a>
- for (const a of document.querySelectorAll('a')) {
- !a.wenku8_loader_hooked && a.addEventListener('click', onclick);
- a.wenku8_loader_hooked = true;
- }
-
- function onclick(e) {
- const a = e.currentTarget;
- const href = a.href;;
- if (!a.href.match(/^https?:\/\//)) {return;}
-
- destroyEvent(e);
- window.open(href);
- }
- }
- }
-
-
-
- // Just stopPropagation and preventDefault
- function destroyEvent(e) {
- if (!e) {return false;};
- if (!e instanceof Event) {return false;};
- e.stopPropagation();
- e.preventDefault();
- }
-
- // Load/Read and Save javascript from given url
- // Auto reties when xhr fails.
- // If load success then callback(true), else callback(false)
- function loadJSPlus(url, callback, oDoc=document, maxRetry=3, retried=0) {
- const fn = callback || function () {};
- const localCDN = GM_getValue(KEY_LOCALCDN, {});
- if (localCDN[url]) {
- DoLog(LogLevel.Info, 'Loading js from localCDN: ' + url);
- const js = localCDN[url];
- appendScript(js);
- fn(true);
- return;
- }
-
- DoLog(LogLevel.Info, 'Loading js from web: ' + url);
- GM_xmlhttpRequest({
- method : 'GET',
- url : url,
- responseType : 'text',
- onload : function(e) {
- if (e.status === 200) {
- const js = e.responseText;
- localCDN[url] = js;
- localCDN[KEY_LOCALCDN_VERSION] = VALUE_LOCALCDN_VERSION;
- GM_setValue(KEY_LOCALCDN, localCDN);
-
- appendScript(js);
- fn(true);
- } else {
- retry();
- }
- },
- onerror : retry
- })
-
- function appendScript(code) {
- const script = oDoc.createElement('script');
- script.type = 'text/javascript';
- script.innerHTML = code;
- oDoc.head.appendChild(script);
- }
-
- function retry() {
- retried++;
- if (retried <= maxRetry) {
- loadJSPlus(url, callback, oDoc, maxRetry, retried);
- } else {
- fn(false);
- }
- }
- }
-
- // GM_Polyfill By PY-DNG
- // 2021.07.18
- // Simply provides the following GM_functions using localStorage, XMLHttpRequest and window.open:
- // Returns object GM_POLYFILLED which has the following properties that shows you which GM_functions are actually polyfilled:
- // GM_setValue, GM_getValue, GM_deleteValue, GM_listValues, GM_xmlhttpRequest, GM_openInTab, GM_setClipboard
- function GM_PolyFill(name='default') {
- const GM_POLYFILL_KEY_STORAGE = 'GM_STORAGE_POLYFILL';
- const GM_POLYFILL_storage = GM_POLYFILL_getStorage();
- const GM_POLYFILLED = {
- GM_setValue: true,
- GM_getValue: true,
- GM_deleteValue: true,
- GM_listValues: true,
- GM_xmlhttpRequest: true,
- GM_openInTab: true,
- GM_setClipboard: true,
- };
-
- GM_setValue_polyfill();
- GM_getValue_polyfill();
- GM_deleteValue_polyfill();
- GM_listValues_polyfill();
- GM_xmlhttpRequest_polyfill();
- GM_openInTab_polyfill();
- GM_setClipboard_polyfill();
-
- function GM_POLYFILL_getStorage() {
- let gstorage = localStorage.getItem(GM_POLYFILL_KEY_STORAGE);
- gstorage = gstorage ? JSON.parse(gstorage) : {};
- let storage = gstorage[name] ? gstorage[name] : {};
- return storage;
- };
-
- function GM_POLYFILL_saveStorage() {
- let gstorage = localStorage.getItem(GM_POLYFILL_KEY_STORAGE);
- gstorage = gstorage ? JSON.parse(gstorage) : {};
- gstorage[name] = GM_POLYFILL_storage;
- localStorage.setItem(GM_POLYFILL_KEY_STORAGE, JSON.stringify(gstorage));
- };
-
- // GM_setValue
- function GM_setValue_polyfill() {
- typeof (GM_setValue) === 'function' ? GM_POLYFILLED.GM_setValue = false: window.GM_setValue = PF_GM_setValue;;
-
- function PF_GM_setValue(name, value) {
- name = String(name);
- GM_POLYFILL_storage[name] = value;
- GM_POLYFILL_saveStorage();
- };
- };
-
- // GM_getValue
- function GM_getValue_polyfill() {
- typeof (GM_getValue) === 'function' ? GM_POLYFILLED.GM_getValue = false: window.GM_getValue = PF_GM_getValue;
-
- function PF_GM_getValue(name, defaultValue) {
- name = String(name);
- if (GM_POLYFILL_storage.hasOwnProperty(name)) {
- return GM_POLYFILL_storage[name];
- } else {
- return defaultValue;
- };
- };
- };
-
- // GM_deleteValue
- function GM_deleteValue_polyfill() {
- typeof (GM_deleteValue) === 'function' ? GM_POLYFILLED.GM_deleteValue = false: window.GM_deleteValue = PF_GM_deleteValue;
-
- function PF_GM_deleteValue(name) {
- name = String(name);
- if (GM_POLYFILL_storage.hasOwnProperty(name)) {
- delete GM_POLYFILL_storage[name];
- GM_POLYFILL_saveStorage();
- };
- };
- };
-
- // GM_listValues
- function GM_listValues_polyfill() {
- typeof (GM_listValues) === 'function' ? GM_POLYFILLED.GM_listValues = false: window.GM_listValues = PF_GM_listValues;
-
- function PF_GM_listValues() {
- return Object.keys(GM_POLYFILL_storage);
- };
- };
-
- // GM_xmlhttpRequest
- // not supported properties of details: synchronous binary nocache revalidate context fetch
- // not supported properties of response(onload arguments[0]): finalUrl
- // ---!IMPORTANT!--- DOES NOT SUPPORT CROSS-ORIGIN REQUESTS!!!!! ---!IMPORTANT!---
- function GM_xmlhttpRequest_polyfill() {
- typeof (GM_xmlhttpRequest) === 'function' ? GM_POLYFILLED.GM_xmlhttpRequest = false: window.GM_xmlhttpRequest = PF_GM_xmlhttpRequest;
-
- // details.synchronous is not supported as Tempermonkey
- function PF_GM_xmlhttpRequest(details) {
- const xhr = new XMLHttpRequest();
-
- // open request
- const openArgs = [details.method, details.url, true];
- if (details.user && details.password) {
- openArgs.push(details.user);
- openArgs.push(details.password);
- }
- xhr.open.apply(xhr, openArgs);
-
- // set headers
- if (details.headers) {
- for (const key of Object.keys(details.headers)) {
- xhr.setRequestHeader(key, details.headers[key]);
- };
- };
- details.cookie ? xhr.setRequestHeader('cookie', details.cookie) : function () {};
- details.anonymous ? xhr.setRequestHeader('cookie', '') : function () {};
-
- // properties
- xhr.timeout = details.timeout;
- xhr.responseType = details.responseType;
- details.overrideMimeType ? xhr.overrideMimeType(details.overrideMimeType) : function () {};
-
- // events
- xhr.onabort = details.onabort;
- xhr.onerror = details.onerror;
- xhr.onloadstart = details.onloadstart;
- xhr.onprogress = details.onprogress;
- xhr.onreadystatechange = details.onreadystatechange;
- xhr.ontimeout = details.ontimeout;
- xhr.onload = function (e) {
- const response = {
- readyState: xhr.readyState,
- status: xhr.status,
- statusText: xhr.statusText,
- responseHeaders: xhr.getAllResponseHeaders(),
- response: xhr.response
- };
- (details.responseType === '' || details.responseType === 'text') ? (response.responseText = xhr.responseText) : function () {};
- (details.responseType === '' || details.responseType === 'document') ? (response.responseXML = xhr.responseXML) : function () {};
- details.onload(response);
- };
-
- // send request
- details.data ? xhr.send(details.data) : xhr.send();
-
- return {
- abort: xhr.abort
- };
- };
- };
-
- // NOTE: options(arg2) is NOT SUPPORTED! if provided, then will just be skipped.
- function GM_openInTab_polyfill() {
- typeof (GM_openInTab) === 'function' ? GM_POLYFILLED.GM_openInTab = false: window.GM_openInTab = PF_GM_openInTab;
-
- function PF_GM_openInTab(url) {
- window.open(url);
- };
- };
-
- // NOTE: needs to be called in an event handler function, and info(arg2) is NOT SUPPORTED!
- function GM_setClipboard_polyfill() {
- typeof (GM_setClipboard) === 'function' ? GM_POLYFILLED.GM_setClipboard = false: window.GM_setClipboard = PF_GM_setClipboard;
-
- function PF_GM_setClipboard(text) {
- // Create a new textarea for copying
- const newInput = document.createElement('textarea');
- document.body.appendChild(newInput);
- newInput.value = text;
- newInput.select();
- document.execCommand('copy');
- document.body.removeChild(newInput);
- };
- };
-
- return GM_POLYFILLED;
- };
-
- // Arguments: level=LogLevel.Info, logContent, asObject=false
- // Needs one call "DoLog();" to get it initialized before using it!
- function DoLog() {
- // Global log levels set
- window.LogLevel = {
- None: 0,
- Error: 1,
- Success: 2,
- Warning: 3,
- Info: 4,
- }
- window.LogLevelMap = {};
- window.LogLevelMap[LogLevel.None] = {prefix: '' , color: 'color:#ffffff'}
- window.LogLevelMap[LogLevel.Error] = {prefix: '[Error]' , color: 'color:#ff0000'}
- window.LogLevelMap[LogLevel.Success] = {prefix: '[Success]' , color: 'color:#00aa00'}
- window.LogLevelMap[LogLevel.Warning] = {prefix: '[Warning]' , color: 'color:#ffa500'}
- window.LogLevelMap[LogLevel.Info] = {prefix: '[Info]' , color: 'color:#888888'}
- window.LogLevelMap[LogLevel.Elements] = {prefix: '[Elements]', color: 'color:#000000'}
-
- // Current log level
- DoLog.logLevel = window.isPY_DNG ? LogLevel.Info : LogLevel.Warning; // Info Warning Success Error
-
- // Log counter
- DoLog.logCount === undefined && (DoLog.logCount = 0);
- if (++DoLog.logCount > 512) {
- console.clear();
- DoLog.logCount = 0;
- }
-
- // Get args
- let level, logContent, asObject;
- switch (arguments.length) {
- case 1:
- level = LogLevel.Info;
- logContent = arguments[0];
- asObject = false;
- break;
- case 2:
- level = arguments[0];
- logContent = arguments[1];
- asObject = false;
- break;
- case 3:
- level = arguments[0];
- logContent = arguments[1];
- asObject = arguments[2];
- break;
- default:
- level = LogLevel.Info;
- logContent = 'DoLog initialized.';
- asObject = false;
- break;
- }
-
- // Log when log level permits
- if (level <= DoLog.logLevel) {
- let msg = '%c' + LogLevelMap[level].prefix;
- let subst = LogLevelMap[level].color;
-
- if (asObject) {
- msg += ' %o';
- } else {
- switch(typeof(logContent)) {
- case 'string': msg += ' %s'; break;
- case 'number': msg += ' %d'; break;
- case 'object': msg += ' %o'; break;
- }
- }
-
- console.log(msg, subst, logContent);
- }
- }
- })();