您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
缓存部分Api请求结果以提升速度减少WAF几率
// ==UserScript== // @name 萌娘百科缓存部分Api请求 // @namespace https://github.com/gui-ying233/mwApiCache // @version 3.8.0 // @description 缓存部分Api请求结果以提升速度减少WAF几率 // @author 鬼影233 // @license MIT // @match zh.moegirl.org.cn/* // @match mzh.moegirl.org.cn/* // @match commons.moegirl.org.cn/* // @match library.moegirl.org.cn/* // @match en.moegirl.org.cn/* // @match ja.moegirl.org.cn/* // @icon http://moegirl.org.cn/favicon.ico // @supportURL https://github.com/gui-ying233/mwApiCache/issues // @run-at document-start // @grant none // ==/UserScript== (() => { "use strict"; if (new URLSearchParams(window.location.search).get("safemode")) return; const ver = 2; const log = (type, ...args) => { console.debug( `%cmwApiCache-${type}\n${args.join("\n")}`, "border-left:1em solid #4E3DA4;background-color:#3C2D73;color:#D9D9D9;padding:1em" ); }; log("Beg", new Date().toISOString()); log("Ver", ver); log("Svd", +window.localStorage.getItem("mwApiCache-Svd")); let win; window.XMLHttpRequest = class extends window.XMLHttpRequest { constructor() { super(); this.addEventListener("load", () => { const url = new URL(this.responseURL); if ( url.hostname.match( /^(?:m?zh|commons|library|en|ja)\.moegirl\.org\.cn$/ ) && this.status === 200 && this.responseText.match( "https://ssl.captcha.qq.com/TCaptcha.js" ) ) { if (win) win.focus(); else { win = window.open( url, "_blank", "width=360,height=360" ); win.addEventListener( "DOMContentLoaded", () => { if ( ![...win.document.scripts].some( ({ src }) => src === "https://ssl.captcha.qq.com/TCaptcha.js" ) ) { win.close(); win = null; } const id = setInterval(() => { if ( !win?.performance .getEntriesByType("navigation") .some(nav => nav.type === "reload") ) return; clearInterval(id); if ( location.hostname === win.location.hostname ) document.cookie = win.document.cookie; win.close(); win = null; }, 50); }, { passive: true, once: true } ); } } }); } }; const id = setInterval(async () => { if (!window.mediaWiki?.Api?.prototype) return; clearInterval(id); const originalMediaWikiApiPost = window.mediaWiki.Api.prototype.post; await window.$.ready; const cfg = window.mediaWiki.config; const userName = cfg.get("wgUserName"); window.addEventListener( "storage", e => { if (!e.key.startsWith("mwApiCache-")) return; if (e.newValue) { if ( e.key === "mwApiCache-Svd" && +e.newValue <= +e.oldValue ) return; e.storageArea.setItem(e.key, e.newValue); log("Set", e.key, e.newValue); } else { e.storageArea.removeItem(e.key); log("Del", e.key); } }, { passive: true } ); const timestamp = Date.now(); for (const key in window.localStorage) { if (!key.startsWith("mwApiCache-")) continue; if (key === "mwApiCache-Svd") continue; const cache = JSON.parse(window.localStorage.getItem(key)); if (cache.timestamp < timestamp || cache.ver !== ver) { log("Del", key); window.localStorage.removeItem(key); } } const bc = new BroadcastChannel("mwApiCache"); bc.addEventListener("message", e => { if (e.data === "init") Object.keys(sessionStorage).forEach( key => key.startsWith("mwApiCache-") && bc.postMessage({ key: key.replace("mwApiCache-", ""), value: JSON.parse(sessionStorage.getItem(key)), }) ); else { const { key, value } = e.data; window.sessionStorage.setItem( `mwApiCache-${key}`, JSON.stringify(value) ); log("Set", key, JSON.stringify(value)); } }); bc.postMessage("init"); const second = 1000, minute = second * 60, hour = minute * 60, day = hour * 24; const getCache = (t, method, arg, ms = day * 7) => { const _arg = JSON.stringify(arg); const cache = JSON.parse( window[ms ? "localStorage" : "sessionStorage"].getItem( `mwApiCache-${_arg}` ) ); if (!cache) { const res = method.call( t, Object.assign( { maxage: ms / 1000, smaxage: ms / 1000, }, arg ) ); res.then(_res => { log("Set", _arg, JSON.stringify(_res)); const key = `mwApiCache-${_arg}`; const value = { ver, timestamp: timestamp + ms, res: _res, }; window[ms ? "localStorage" : "sessionStorage"].setItem( key, JSON.stringify(value) ); if (!ms) bc.postMessage({ key: _arg, value }); return _res; }); return res; } window.localStorage.setItem( "mwApiCache-Svd", +window.localStorage.getItem("mwApiCache-Svd") + 1 ); log("Get", _arg); const promise = $() .promise() .then(() => cache.res); promise.abort = () => {}; return promise; }; const apiFilter = (t, method, [payload, ...args]) => { const arg = JSON.stringify(payload); switch (arg) { case `{"action":"query","ususers":"${userName}","meta":["userinfo","siteinfo"],"list":["users"],"uiprop":["rights"],"siprop":["specialpagealiases"],"usprop":["blockinfo"]}`: case '{"action":"query","meta":"siteinfo","siprop":"specialpagealiases","formatversion":2,"uselang":"content","maxage":3600}': case '{"action":"query","meta":"userinfo","uiprop":["groups","rights"]}': case `{"action":"query","prop":"revisions","titles":"User:${userName}/codemirror-mediawiki.json","rvprop":"content","rvlimit":1}`: case '{"action":"paraminfo","modules":"main","helpformat":"html","uselang":"zh"}': case '{"action":"paraminfo","modules":"json","helpformat":"html","uselang":"zh"}': case '{"action":"query","meta":"siteinfo","siprop":["general","namespaces"]}': return getCache(t, method, payload); case `{"action":"query","meta":"allmessages","ammessages":["Editnotice-${cfg.get( "wgNamespaceNumber" )}","Editnotice-${cfg.get("wgNamespaceNumber")}-${cfg .get("wgPageName") .replaceAll("_", " ") .replace( `${ cfg.get("wgFormattedNamespaces")[ cfg.get("wgNamespaceNumber") ] }:`, "" )}"],"amenableparser":1}`: return getCache(t, method, payload, 3 * day); case `{"action":"query","prop":"revisions|info","inprop":"protection|watched","format":"json","pageids":${cfg.get( "wgArticleId" )}}`: return getCache(t, method, payload, 0); case '{"action":"query","meta":"notifications","formatversion":2,"notfilter":"!read","notprop":"list","notformat":"model","notlimit":"max"}': return getCache(t, method, payload, 5 * minute - 1); default: if ( /^{"action":"query","meta":"allmessages","ammessages":\[".*?"\],"amlang":"zh","formatversion":2}$/.test( arg ) || /^{"action":"parse","text":"<span id=\\"mw_editnotice_test_var\\".+?","preview":true,"disablelimitreport":true,"disableeditsection":true,"disabletoc":true}$/.test( arg ) ) return getCache(t, method, payload); if ( /^{"action":"query","meta":"allmessages","ammessages":\["Editnotice-\d+","Editnotice-\d+-.+"],"amenableparser":1}$/.test( arg ) ) return getCache(t, method, payload, 3 * day); if ( payload?.action === "compare" || /^{"action":"query","prop":"revisions\|info","inprop":"protection\|watched","format":"json","pageids":\d+}$/.test( arg ) ) return getCache(t, method, payload, 0); if (payload?.maxage ?? payload?.smaxage) return getCache( t, method, payload, (payload?.maxage ?? payload?.smaxage) * 1000 ); log("Ign", arg); return method.apply(t, [payload, ...args]); } }; window.mediaWiki.Api.prototype.get = function (...args) { return apiFilter(this, originalMediaWikiApiPost, args); }; window.mediaWiki.Api.prototype.post = function (...args) { return apiFilter(this, originalMediaWikiApiPost, args); }; }, 5); })();