wenku8+ loader

load wenku8+ temporarily

目前為 2021-12-23 提交的版本,檢視 最新版本

此腳本不應該直接安裝,它是一個供其他腳本使用的函式庫。欲使用本函式庫,請在腳本 metadata 寫上: // @require https://update.gf.qytechs.cn/scripts/437461/1001439/wenku8%2B%20loader.js

  1. // 源代码
  2. (function () {
  3. const KEY_LOCALCDN = 'LOCAL-CDN';
  4. const KEY_LOCALCDN_VERSION = 'version';
  5. const VALUE_LOCALCDN_VERSION = '0.1';
  6. const KEY_POLYFILL = 'wenku8-plus-injecter';
  7. GM_PolyFill(KEY_POLYFILL);
  8. DoLog();
  9. DoLog(LogLevel.Success, 'wenku8+ loader loaded successfully on this page');
  10.  
  11. const main_url = 'https://gf.qytechs.cn/scripts/416310/code/script.user.js';
  12. const loader_url = 'https://gf.qytechs.cn/scripts/437461/code/script.js';
  13. dealDocument();
  14.  
  15. function dealDocument(oDom=document) {
  16. // Hook window.open
  17. const open = window.open;
  18. window.open = openWithInjector;
  19. function openWithInjector(strUrl, strWindowName, strWindowFeatures) {
  20. const newTab = open(strUrl, strWindowName, strWindowFeatures);
  21. const oDom = newTab.document;
  22. const oWin = newTab.window;
  23. oWin.addEventListener('load', function() {
  24. const script = oDom.createElement('script');
  25. script.src = loader_url;
  26. oWin.document.head.appendChild(script);
  27. });
  28. return newTab;
  29. }
  30.  
  31. // Hook <a>
  32. hooklinks();
  33. setInterval(hooklinks, 200);
  34.  
  35. // Load wenku8+
  36. const script = oDom.createElement('script');
  37. script.src = main_url;
  38. document.head.appendChild(script);
  39.  
  40. function hooklinks() {
  41. // Hook <a>
  42. for (const a of document.querySelectorAll('a')) {
  43. !a.wenku8_loader_hooked && a.addEventListener('click', onclick);
  44. a.wenku8_loader_hooked = true;
  45. }
  46.  
  47. function onclick(e) {
  48. const a = e.currentTarget;
  49. const href = a.href;;
  50. if (!a.href.match(/^https?:\/\//)) {return;}
  51.  
  52. destroyEvent(e);
  53. window.open(href);
  54. }
  55. }
  56. }
  57.  
  58.  
  59.  
  60. // Just stopPropagation and preventDefault
  61. function destroyEvent(e) {
  62. if (!e) {return false;};
  63. if (!e instanceof Event) {return false;};
  64. e.stopPropagation();
  65. e.preventDefault();
  66. }
  67.  
  68. // Load/Read and Save javascript from given url
  69. // Auto reties when xhr fails.
  70. // If load success then callback(true), else callback(false)
  71. function loadJSPlus(url, callback, oDoc=document, maxRetry=3, retried=0) {
  72. const fn = callback || function () {};
  73. const localCDN = GM_getValue(KEY_LOCALCDN, {});
  74. if (localCDN[url]) {
  75. DoLog(LogLevel.Info, 'Loading js from localCDN: ' + url);
  76. const js = localCDN[url];
  77. appendScript(js);
  78. fn(true);
  79. return;
  80. }
  81.  
  82. DoLog(LogLevel.Info, 'Loading js from web: ' + url);
  83. GM_xmlhttpRequest({
  84. method : 'GET',
  85. url : url,
  86. responseType : 'text',
  87. onload : function(e) {
  88. if (e.status === 200) {
  89. const js = e.responseText;
  90. localCDN[url] = js;
  91. localCDN[KEY_LOCALCDN_VERSION] = VALUE_LOCALCDN_VERSION;
  92. GM_setValue(KEY_LOCALCDN, localCDN);
  93.  
  94. appendScript(js);
  95. fn(true);
  96. } else {
  97. retry();
  98. }
  99. },
  100. onerror : retry
  101. })
  102.  
  103. function appendScript(code) {
  104. const script = oDoc.createElement('script');
  105. script.type = 'text/javascript';
  106. script.innerHTML = code;
  107. oDoc.head.appendChild(script);
  108. }
  109.  
  110. function retry() {
  111. retried++;
  112. if (retried <= maxRetry) {
  113. loadJSPlus(url, callback, oDoc, maxRetry, retried);
  114. } else {
  115. fn(false);
  116. }
  117. }
  118. }
  119.  
  120. // GM_Polyfill By PY-DNG
  121. // 2021.07.18
  122. // Simply provides the following GM_functions using localStorage, XMLHttpRequest and window.open:
  123. // Returns object GM_POLYFILLED which has the following properties that shows you which GM_functions are actually polyfilled:
  124. // GM_setValue, GM_getValue, GM_deleteValue, GM_listValues, GM_xmlhttpRequest, GM_openInTab, GM_setClipboard
  125. function GM_PolyFill(name='default') {
  126. const GM_POLYFILL_KEY_STORAGE = 'GM_STORAGE_POLYFILL';
  127. const GM_POLYFILL_storage = GM_POLYFILL_getStorage();
  128. const GM_POLYFILLED = {
  129. GM_setValue: true,
  130. GM_getValue: true,
  131. GM_deleteValue: true,
  132. GM_listValues: true,
  133. GM_xmlhttpRequest: true,
  134. GM_openInTab: true,
  135. GM_setClipboard: true,
  136. };
  137.  
  138. GM_setValue_polyfill();
  139. GM_getValue_polyfill();
  140. GM_deleteValue_polyfill();
  141. GM_listValues_polyfill();
  142. GM_xmlhttpRequest_polyfill();
  143. GM_openInTab_polyfill();
  144. GM_setClipboard_polyfill();
  145.  
  146. function GM_POLYFILL_getStorage() {
  147. let gstorage = localStorage.getItem(GM_POLYFILL_KEY_STORAGE);
  148. gstorage = gstorage ? JSON.parse(gstorage) : {};
  149. let storage = gstorage[name] ? gstorage[name] : {};
  150. return storage;
  151. };
  152.  
  153. function GM_POLYFILL_saveStorage() {
  154. let gstorage = localStorage.getItem(GM_POLYFILL_KEY_STORAGE);
  155. gstorage = gstorage ? JSON.parse(gstorage) : {};
  156. gstorage[name] = GM_POLYFILL_storage;
  157. localStorage.setItem(GM_POLYFILL_KEY_STORAGE, JSON.stringify(gstorage));
  158. };
  159.  
  160. // GM_setValue
  161. function GM_setValue_polyfill() {
  162. typeof (GM_setValue) === 'function' ? GM_POLYFILLED.GM_setValue = false: window.GM_setValue = PF_GM_setValue;;
  163.  
  164. function PF_GM_setValue(name, value) {
  165. name = String(name);
  166. GM_POLYFILL_storage[name] = value;
  167. GM_POLYFILL_saveStorage();
  168. };
  169. };
  170.  
  171. // GM_getValue
  172. function GM_getValue_polyfill() {
  173. typeof (GM_getValue) === 'function' ? GM_POLYFILLED.GM_getValue = false: window.GM_getValue = PF_GM_getValue;
  174.  
  175. function PF_GM_getValue(name, defaultValue) {
  176. name = String(name);
  177. if (GM_POLYFILL_storage.hasOwnProperty(name)) {
  178. return GM_POLYFILL_storage[name];
  179. } else {
  180. return defaultValue;
  181. };
  182. };
  183. };
  184.  
  185. // GM_deleteValue
  186. function GM_deleteValue_polyfill() {
  187. typeof (GM_deleteValue) === 'function' ? GM_POLYFILLED.GM_deleteValue = false: window.GM_deleteValue = PF_GM_deleteValue;
  188.  
  189. function PF_GM_deleteValue(name) {
  190. name = String(name);
  191. if (GM_POLYFILL_storage.hasOwnProperty(name)) {
  192. delete GM_POLYFILL_storage[name];
  193. GM_POLYFILL_saveStorage();
  194. };
  195. };
  196. };
  197.  
  198. // GM_listValues
  199. function GM_listValues_polyfill() {
  200. typeof (GM_listValues) === 'function' ? GM_POLYFILLED.GM_listValues = false: window.GM_listValues = PF_GM_listValues;
  201.  
  202. function PF_GM_listValues() {
  203. return Object.keys(GM_POLYFILL_storage);
  204. };
  205. };
  206.  
  207. // GM_xmlhttpRequest
  208. // not supported properties of details: synchronous binary nocache revalidate context fetch
  209. // not supported properties of response(onload arguments[0]): finalUrl
  210. // ---!IMPORTANT!--- DOES NOT SUPPORT CROSS-ORIGIN REQUESTS!!!!! ---!IMPORTANT!---
  211. function GM_xmlhttpRequest_polyfill() {
  212. typeof (GM_xmlhttpRequest) === 'function' ? GM_POLYFILLED.GM_xmlhttpRequest = false: window.GM_xmlhttpRequest = PF_GM_xmlhttpRequest;
  213.  
  214. // details.synchronous is not supported as Tempermonkey
  215. function PF_GM_xmlhttpRequest(details) {
  216. const xhr = new XMLHttpRequest();
  217.  
  218. // open request
  219. const openArgs = [details.method, details.url, true];
  220. if (details.user && details.password) {
  221. openArgs.push(details.user);
  222. openArgs.push(details.password);
  223. }
  224. xhr.open.apply(xhr, openArgs);
  225.  
  226. // set headers
  227. if (details.headers) {
  228. for (const key of Object.keys(details.headers)) {
  229. xhr.setRequestHeader(key, details.headers[key]);
  230. };
  231. };
  232. details.cookie ? xhr.setRequestHeader('cookie', details.cookie) : function () {};
  233. details.anonymous ? xhr.setRequestHeader('cookie', '') : function () {};
  234.  
  235. // properties
  236. xhr.timeout = details.timeout;
  237. xhr.responseType = details.responseType;
  238. details.overrideMimeType ? xhr.overrideMimeType(details.overrideMimeType) : function () {};
  239.  
  240. // events
  241. xhr.onabort = details.onabort;
  242. xhr.onerror = details.onerror;
  243. xhr.onloadstart = details.onloadstart;
  244. xhr.onprogress = details.onprogress;
  245. xhr.onreadystatechange = details.onreadystatechange;
  246. xhr.ontimeout = details.ontimeout;
  247. xhr.onload = function (e) {
  248. const response = {
  249. readyState: xhr.readyState,
  250. status: xhr.status,
  251. statusText: xhr.statusText,
  252. responseHeaders: xhr.getAllResponseHeaders(),
  253. response: xhr.response
  254. };
  255. (details.responseType === '' || details.responseType === 'text') ? (response.responseText = xhr.responseText) : function () {};
  256. (details.responseType === '' || details.responseType === 'document') ? (response.responseXML = xhr.responseXML) : function () {};
  257. details.onload(response);
  258. };
  259.  
  260. // send request
  261. details.data ? xhr.send(details.data) : xhr.send();
  262.  
  263. return {
  264. abort: xhr.abort
  265. };
  266. };
  267. };
  268.  
  269. // NOTE: options(arg2) is NOT SUPPORTED! if provided, then will just be skipped.
  270. function GM_openInTab_polyfill() {
  271. typeof (GM_openInTab) === 'function' ? GM_POLYFILLED.GM_openInTab = false: window.GM_openInTab = PF_GM_openInTab;
  272.  
  273. function PF_GM_openInTab(url) {
  274. window.open(url);
  275. };
  276. };
  277.  
  278. // NOTE: needs to be called in an event handler function, and info(arg2) is NOT SUPPORTED!
  279. function GM_setClipboard_polyfill() {
  280. typeof (GM_setClipboard) === 'function' ? GM_POLYFILLED.GM_setClipboard = false: window.GM_setClipboard = PF_GM_setClipboard;
  281.  
  282. function PF_GM_setClipboard(text) {
  283. // Create a new textarea for copying
  284. const newInput = document.createElement('textarea');
  285. document.body.appendChild(newInput);
  286. newInput.value = text;
  287. newInput.select();
  288. document.execCommand('copy');
  289. document.body.removeChild(newInput);
  290. };
  291. };
  292.  
  293. return GM_POLYFILLED;
  294. };
  295.  
  296. // Arguments: level=LogLevel.Info, logContent, asObject=false
  297. // Needs one call "DoLog();" to get it initialized before using it!
  298. function DoLog() {
  299. // Global log levels set
  300. window.LogLevel = {
  301. None: 0,
  302. Error: 1,
  303. Success: 2,
  304. Warning: 3,
  305. Info: 4,
  306. }
  307. window.LogLevelMap = {};
  308. window.LogLevelMap[LogLevel.None] = {prefix: '' , color: 'color:#ffffff'}
  309. window.LogLevelMap[LogLevel.Error] = {prefix: '[Error]' , color: 'color:#ff0000'}
  310. window.LogLevelMap[LogLevel.Success] = {prefix: '[Success]' , color: 'color:#00aa00'}
  311. window.LogLevelMap[LogLevel.Warning] = {prefix: '[Warning]' , color: 'color:#ffa500'}
  312. window.LogLevelMap[LogLevel.Info] = {prefix: '[Info]' , color: 'color:#888888'}
  313. window.LogLevelMap[LogLevel.Elements] = {prefix: '[Elements]', color: 'color:#000000'}
  314.  
  315. // Current log level
  316. DoLog.logLevel = window.isPY_DNG ? LogLevel.Info : LogLevel.Warning; // Info Warning Success Error
  317.  
  318. // Log counter
  319. DoLog.logCount === undefined && (DoLog.logCount = 0);
  320. if (++DoLog.logCount > 512) {
  321. console.clear();
  322. DoLog.logCount = 0;
  323. }
  324.  
  325. // Get args
  326. let level, logContent, asObject;
  327. switch (arguments.length) {
  328. case 1:
  329. level = LogLevel.Info;
  330. logContent = arguments[0];
  331. asObject = false;
  332. break;
  333. case 2:
  334. level = arguments[0];
  335. logContent = arguments[1];
  336. asObject = false;
  337. break;
  338. case 3:
  339. level = arguments[0];
  340. logContent = arguments[1];
  341. asObject = arguments[2];
  342. break;
  343. default:
  344. level = LogLevel.Info;
  345. logContent = 'DoLog initialized.';
  346. asObject = false;
  347. break;
  348. }
  349.  
  350. // Log when log level permits
  351. if (level <= DoLog.logLevel) {
  352. let msg = '%c' + LogLevelMap[level].prefix;
  353. let subst = LogLevelMap[level].color;
  354.  
  355. if (asObject) {
  356. msg += ' %o';
  357. } else {
  358. switch(typeof(logContent)) {
  359. case 'string': msg += ' %s'; break;
  360. case 'number': msg += ' %d'; break;
  361. case 'object': msg += ' %o'; break;
  362. }
  363. }
  364.  
  365. console.log(msg, subst, logContent);
  366. }
  367. }
  368. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址