improve killpage logic

relying on an interval causes the process to never exit, because the interval is still running in the background. this is bad for oneshot scripts like ours. instead the check works by comparing the current date to the last known date any time a post request is sent
This commit is contained in:
ewin 2025-09-04 23:04:54 -04:00
parent d0e5bf33ff
commit 436acf7299
Signed by: erin
SSH key fingerprint: SHA256:swjoHhREbZPbWe+gyJNi24d4NAxJSyUIm3fpZj4z3wc

View file

@ -27,9 +27,26 @@ export class MediaWikiClient {
constructor (wikiURL, {killPage}) { constructor (wikiURL, {killPage}) {
this.wikiURL = wikiURL; this.wikiURL = wikiURL;
this.killPage = killPage; this.killPage = killPage;
this.lastKillPageCheck = 0; // first check is triggered after login
this.fetch = makeFetchCookie(fetch); this.fetch = makeFetchCookie(fetch);
} }
/** Checks the kill page if needed, killing the process if not empty. */
async tryKillPageCheck () {
if (!this.killPage) return;
// wait at least 10 seconds since the last check
if (Date.now() > this.lastKillPageCheck + 10 * 1000) return;
this.lastKillPageCheck = Date.now();
const response = await this.fetch(`${this.wikiURL}/index.php?action=raw&title=${encodeURIComponent(this.killPage)}`);
const content = await response.text();
if (content.trim()) {
console.error('*** Kill page is not empty; stopping ***\n');
console.error(content);
process.exit(1);
}
};
/** /**
* Makes a GET request against `index.php`. * Makes a GET request against `index.php`.
* @param {Record<string, string>} params Query string parameters * @param {Record<string, string>} params Query string parameters
@ -71,6 +88,7 @@ export class MediaWikiClient {
* @returns {Promise<any>} * @returns {Promise<any>}
*/ */
async fetchApiPost (params, options = {}) { async fetchApiPost (params, options = {}) {
await this.tryKillPageCheck();
const response = await this.fetch(`${this.wikiURL}/api.php`, { const response = await this.fetch(`${this.wikiURL}/api.php`, {
...options, ...options,
method: 'POST', method: 'POST',
@ -128,20 +146,6 @@ export class MediaWikiClient {
if (body.login.result === 'Failed') { if (body.login.result === 'Failed') {
throw new Error(body.login.reason); throw new Error(body.login.reason);
} }
if (this.killPage) {
// start the kill page check loop as soon as we're logged in
const checkKillPage = async () => {
let content = await this.readPage(this.killPage);
if (content.trim()) {
console.error('*** Kill page is not empty; stopping ***\n');
console.error(content);
process.exit(1);
}
setTimeout(checkKillPage, 30 * 1000); // every 30 seconds
};
checkKillPage();
}
} }
/** /**
@ -182,6 +186,19 @@ export class MediaWikiClient {
return body; return body;
} }
async purgePages (titles) {
if (!titles.length) return;
// mediawiki has a 50 title per request limit, so we grab the first 50
// and recurse to handle the rest
let currentTitles = titles.splice(0, 50);
const body = await this.fetchApiPost({
action: 'purge',
titles: currentTitles.join('|'),
});
return this.purgePages(titles);
}
/** /**
* *
* @param {string} from The page's current name * @param {string} from The page's current name
@ -239,4 +256,28 @@ export class MediaWikiClient {
}); });
return body.query.categorymembers; return body.query.categorymembers;
} }
/**
* Gets the list of a user's contributions.
* @param {string} username Name of the user whose contribs should be fetched
* @param {object} options
* @param {number | number[] | '*'} [options.namespaces] List of namespaces from which to return results
* @param {number} [options.limit] Maximum number of items to return
* @param {string} [options.show] See the documentation of `ucshow` at https://www.mediawiki.org/wiki/API:Usercontribs
* @returns {Promise<{pageid: string; revid: string; timestamp: string; title: string}[]>}
*/
async listUserContribs (username, {namespaces = '*', limit = 50, show}) {
if (Array.isArray(namespaces)) {
namespaces = namespaces.join('|');
}
const body = await this.fetchApiGet({
action: 'query',
list: 'usercontribs',
ucuser: username,
uclimit: limit,
ucnamespace: namespaces,
ucshow: show,
});
return body.query.usercontribs;
}
} }