UNPKG

wiki-saikou

Version:

The library provides the out of box accessing to MediaWiki API in both browsers & Node.js, and the syntax is very similar to vanilla `new mw.Api()`. TypeScript definition included~

250 lines (245 loc) 8.05 kB
'use strict'; const WikiSaikou = require('./shared/wiki-saikou.1DPaxo4l.cjs'); const plugins = require('fexios/plugins'); const fexios = require('fexios'); /** * WikiSaikou * @description Standalone MediaWiki API SDK with `mw.Api`-like API in any environments * @author Dragon-Fish <dragon-fish@qq.com> * @license MIT */ class MediaWikiApi extends WikiSaikou.WikiSaikouCore { autoReloginEnabled = false; loginCredentials; constructor(configOrBaseURL, defaultOptions, defaultParams) { const config = WikiSaikou.resolveLegacyCtor( configOrBaseURL, defaultOptions, defaultParams ); super(config); this.request.plugin(plugins.pluginCookieJar); this.request.on("beforeRequest", (ctx) => this.handleBeforeRequest(ctx)); this.request.on("afterResponse", (ctx) => this.handleAfterResponse(ctx)); } canAutoRelogin() { return Boolean(this.autoReloginEnabled && this.loginCredentials?.username); } getAssertUser() { return this.loginCredentials?.username; } getAutoReloginRetries() { return this.loginCredentials?.autoReloginRetries ?? 3; } getParam(data, key) { if (!data) return void 0; if (data instanceof URLSearchParams) { return data.get(key); } if (typeof FormData !== "undefined" && data instanceof FormData) { return data.get(key); } return data[key]; } hasParam(data, key) { if (!data) return false; if (data instanceof URLSearchParams) { return data.has(key); } if (typeof FormData !== "undefined" && data instanceof FormData) { return data.has(key); } return data[key] !== void 0; } setParam(data, key, value) { if (data instanceof URLSearchParams) { data.set(key, value); } else if (typeof FormData !== "undefined" && data instanceof FormData) { data.set(key, value); } else { data[key] = value; } } getAction(query, body) { const action = this.getParam(query, "action") ?? this.getParam(body, "action"); return action === void 0 ? void 0 : String(action); } toStringArray(value) { if (value === void 0 || value === null) return []; if (Array.isArray(value)) { return value.map((item) => String(item)).filter(Boolean); } return String(value).split("|").map((item) => item.trim()).filter(Boolean); } isLoginTokenRequest(query, body) { const check = (data) => { if (!data) return false; const action = this.getParam(data, "action"); if (action && String(action) !== "query") return false; if (!action) return false; const meta = this.toStringArray(this.getParam(data, "meta")); if (!meta.includes("tokens")) return false; const types = this.toStringArray(this.getParam(data, "type")); return types.includes("login"); }; return check(query) || check(body); } shouldSkipAutoRelogin(query, body) { const action = this.getAction(query, body); if (action === "login") return true; if (this.isLoginTokenRequest(query, body)) { return true; } return false; } isAssertUserFailed(data) { const isAssertFailedCode = (code) => code === "assertuserfailed" || code === "assertnameduserfailed"; if (WikiSaikou.MediaWikiApiError.is(data)) { return data.errors.some((error) => isAssertFailedCode(error.code)); } return WikiSaikou.WikiSaikouError.extractMediaWikiApiErrors(data).some( (error) => isAssertFailedCode(error.code) ); } async reloginIfNeeded() { if (!this.canAutoRelogin() || !this.loginCredentials) return; await this.login( this.loginCredentials.lgname, this.loginCredentials.lgpassword, void 0, { autoRelogin: true, autoReloginRetries: this.loginCredentials.autoReloginRetries } ); } get cookieJar() { return this.request.cookieJar; } handleBeforeRequest(ctx) { if (!this.canAutoRelogin()) return ctx; const { query, body } = ctx.request; if (this.shouldSkipAutoRelogin(query, body)) return ctx; if (this.hasParam(query, "assertuser") || this.hasParam(body, "assertuser")) { return ctx; } const assertUser = this.getAssertUser(); if (body !== void 0 && body !== null) { this.setParam(body, "assertuser", assertUser); } else { if (!ctx.request.query) { ctx.request.query = {}; } this.setParam(ctx.request.query, "assertuser", assertUser); } return ctx; } async handleAfterResponse(ctx) { if (!this.canAutoRelogin()) return ctx; const { query, body } = ctx.request; if (this.shouldSkipAutoRelogin(query, body)) { return ctx; } if (!this.hasParam(query, "assertuser") && !this.hasParam(body, "assertuser")) { return ctx; } if (!this.isAssertUserFailed(ctx.data)) return ctx; const attempt = Number(ctx.runtime.customEnv?.autoReloginAttempt ?? 0); const maxAttempts = this.getAutoReloginRetries(); if (attempt >= maxAttempts) return ctx; await this.reloginIfNeeded(); const { rawRequest, ...requestOptions } = ctx.request; const nextEnv = { ...ctx.runtime.customEnv, autoReloginAttempt: attempt + 1 }; const retryResponse = await this.request.request({ ...requestOptions, url: ctx.request.url, customEnv: nextEnv }); return retryResponse ?? ctx; } async login(lgname, lgpassword, params, postOptions) { this.config.fexiosConfigs.credentials = "include"; const { autoRelogin = true, autoReloginRetries = 3, ...tokenOptions } = postOptions || {}; if (tokenOptions.noCache === void 0) { tokenOptions.noCache = true; } const res = await this.postWithToken( "login", { action: "login", lgname, lgpassword, ...params }, { tokenName: "lgtoken", ...tokenOptions } ); const data = res?.data; if (data?.login?.result !== "Success") { throw new WikiSaikou.WikiSaikouError( WikiSaikou.WikiSaikouErrorCode.LOGIN_FAILED, data?.login?.reason?.text || data?.login?.result || "Login failed with unknown reason", data ); } if (autoRelogin === true) { this.autoReloginEnabled = true; this.loginCredentials = { lgname, lgpassword, username: data?.login?.lgusername, autoReloginRetries: Number.isFinite(autoReloginRetries) && autoReloginRetries >= 0 ? Math.floor(autoReloginRetries) : 3 }; } else if (autoRelogin === false) { this.autoReloginEnabled = false; this.loginCredentials = void 0; } return data.login; } async logout() { this.autoReloginEnabled = false; this.loginCredentials = void 0; await this.postWithToken("csrf", { action: "logout" }).catch(() => { }); this.tokens.clear(); this.request.cookieJar?.clear(); } } exports.MediaWikiApiError = WikiSaikou.MediaWikiApiError; exports.MwApiBase = WikiSaikou.WikiSaikouCore; Object.defineProperty(exports, "MwParamNormalizer", { enumerable: true, get: function () { return WikiSaikou.MwParamNormalizer; } }); exports.WikiSaikouCore = WikiSaikou.WikiSaikouCore; Object.defineProperty(exports, "WikiSaikouError", { enumerable: true, get: function () { return WikiSaikou.WikiSaikouError; } }); exports.WikiSaikouErrorCode = WikiSaikou.WikiSaikouErrorCode; exports.createFexiosSaikou = WikiSaikou.createFexiosSaikou; exports.CookieJar = plugins.CookieJar; exports.MediaWikiApi = MediaWikiApi; exports.MediaWikiNodeClient = MediaWikiApi; exports.MwApi = MediaWikiApi; Object.prototype.hasOwnProperty.call(fexios, '__proto__') && !Object.prototype.hasOwnProperty.call(exports, '__proto__') && Object.defineProperty(exports, '__proto__', { enumerable: true, value: fexios['__proto__'] }); Object.keys(fexios).forEach(function (k) { if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) exports[k] = fexios[k]; }); //# sourceMappingURL=node.cjs.map