diff --git a/.env.example b/.env.example index 90876d7..561eb92 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,4 @@ MW_SCRIPTPATH="https://ffxiv.consolegameswiki.com/mediawiki" MW_USERNAME="Wind-up Umbreon" MW_PASSWORD="..." +MW_KILLPAGE="User talk:Wind-up Umbreon" diff --git a/lib/api/mediawiki.js b/lib/api/mediawiki.js index b01788c..5dc2b7b 100644 --- a/lib/api/mediawiki.js +++ b/lib/api/mediawiki.js @@ -18,9 +18,15 @@ export class MediaWikiClient { * @param {string} wikiURL Target wiki's MediaWiki path (i.e. the path that * contains `index.php` and `api.php`) without a trailing slash. For example * for English Wikipedia this would be `'https://en.wikipedia.org/w'`. + * @param {object} options + * @param {string} [options.killPage] Name of a page that, if provided, will + * be read periodically. If the page ever contains text, the process will be + * killed. This is a safety measure allowing other editors to kill an + * unattended script if it misbehaves. */ - constructor (wikiURL) { + constructor (wikiURL, {killPage}) { this.wikiURL = wikiURL; + this.killPage = killPage; this.fetch = makeFetchCookie(fetch); } @@ -122,6 +128,20 @@ export class MediaWikiClient { if (body.login.result === 'Failed') { 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(); + } } /** diff --git a/lib/config.js b/lib/config.js index aff689d..7fa3ba7 100644 --- a/lib/config.js +++ b/lib/config.js @@ -1,12 +1,23 @@ import {MediaWikiClient} from './api/mediawiki.js'; +/** + * Creates a mediawiki client with config pulled from environment variables. + * @param {object} options + * @param {stromg} [options.unattended] If provided, the page specified by the + * `MW_KILLPAGE` environment variable will be checked periodically, and the + * script will be killed if the page contains text. This is a safety measure + * allowing other editors to kill an unattended script if it misbehaves. + * @returns {Promise} + */ export async function getMediawikiClient () { if (!process.env.MW_USERNAME || !process.env.MW_PASSWORD) { throw new Error('Environment variables `MW_USERNAME` and `MW_PASSWORD` are required.'); } // Log into our wiki client - const mw = new MediaWikiClient('https://ffxiv.consolegameswiki.com/mediawiki'); + const mw = new MediaWikiClient('https://ffxiv.consolegameswiki.com/mediawiki', { + killPage: process.env.MW_KILLPAGE || undefined, + }); await mw.login(process.env.MW_USERNAME, process.env.MW_PASSWORD); return mw; }