Skip to content

Commit

Permalink
Enable emergency shutoff support
Browse files Browse the repository at this point in the history
  • Loading branch information
siddharthvp committed Oct 22, 2020
1 parent 9307b0f commit be030bb
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 0 deletions.
64 changes: 64 additions & 0 deletions src/bot.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,18 @@ class mwn {
// shutoffPage: null,
// shutoffRegex: /^\s*$/,

/**
* Bot emergency shutoff options
* @type {{condition: RegExp | Function, page: string,
* intervalDuration: number, onShutoff: Function}}
*/
shutoff: {
intervalDuration: 10000,
page: null,
condition: /^\s*$/,
onShutoff: function () {}
},

// default parameters included in every API request
defaultParams: {
format: 'json',
Expand Down Expand Up @@ -198,6 +210,15 @@ class mwn {
responseType: 'json'
}, mwn.requestDefaults);

/**
* Emergency shutoff config
* @type {{hook: ReturnType<typeof setTimeout>, state: boolean}}
*/
this.shutoff = {
state: false,
hook: null
};

/**
* Title class associated with the bot instance
*/
Expand Down Expand Up @@ -409,6 +430,14 @@ class mwn {
* @returns {Promise<Object>}
*/
async request(params, customRequestOptions = {}) {

if (this.shutoff.state) {
return this.rejectWithError({
code: 'bot-shutoff',
info: `Bot was shut off (check ${this.options.shutoff.page})`
});
}

params = merge(this.options.defaultParams, params);

const getOrPost = function (data) {
Expand Down Expand Up @@ -865,6 +894,41 @@ class mwn {
});
}

/**
* Enable bot emergency shutoff
* @param {Object} [shutoffOptions]
* @config {string} [page]
* @config {number} [intervalDuration]
* @config {RegExp | Function} [condition]
* @config {Function} [onShutoff]
*/
enableEmergencyShutoff(shutoffOptions) {
Object.assign(this.options.shutoff, shutoffOptions);

this.shutoff.hook = setInterval(async () => {
let text = await new this.page(this.options.shutoff.page).text();
let cond = this.options.shutoff.condition;
if (
(cond instanceof RegExp && !cond.test(text)) ||
(cond instanceof Function && !cond(text))
) {
this.shutoff.state = true;
this.disableEmergencyShutoff();
// user callback executed last, so that an error thrown by
// it doesn't prevent the the above from being run
this.options.shutoff.onShutoff(text);
}
}, this.options.shutoff.intervalDuration);
}

/**
* Disable emergency shutoff detection.
* Use this only if it was ever enabled.
*/
disableEmergencyShutoff() {
clearInterval(this.shutoff.hook);
}

/***************** HELPER FUNCTIONS ******************/

/**
Expand Down
62 changes: 62 additions & 0 deletions tests/shutoff.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
'use strict';

const { bot, expect, loginBefore, logoutAfter} = require('./test_base');


describe('bot emergency shutoff', async function() {
this.timeout(10000);

before('logs in and gets token & namespaceInfo', loginBefore);
after('logs out', logoutAfter);

it('set shutoff=true on non-matching regex', async function () {
bot.enableEmergencyShutoff({
page: 'SD0001test',
intervalDuration: 1000,
condition: /^\s*$/
});
await bot.save('SD0001test', 'shutoff', 'Testing bot shutoff (mwn)');
await bot.sleep(1500); // wait till we can be sure that shutoff check is queried
expect(bot.shutoff.state).to.equal(true);
bot.disableEmergencyShutoff();
});

it('set shutoff=true on condition function returns falsy value', async function () {
bot.shutoff.state = false; // restore to default state

bot.enableEmergencyShutoff({
page: 'SD0001test',
intervalDuration: 1000,
condition: function () {
return false; // function returns false means bot would shut down
}
});
await bot.sleep(1500); // wait till we can be sure that shutoff check is queried
expect(bot.shutoff.state).to.equal(true);
bot.disableEmergencyShutoff();
});

it ('sets shutoff=true even if shutoff options are not configured in function', async function () {
bot.shutoff.state = false; // restore to default state

bot.options.shutoff.page = 'SD0001test';
bot.options.shutoff.intervalDuration = 1000;
bot.options.shutoff.condition = /^\s*$/;
bot.enableEmergencyShutoff();
await bot.save('SD0001test', 'shutoff', 'Testing bot shutoff (mwn)');
await bot.sleep(1500); // wait till we can be sure that shutoff check is queried
expect(bot.shutoff.state).to.equal(true);
bot.disableEmergencyShutoff();
});

it('refuses to do API requests when shut off', function () {
bot.shutoff.state = true;
return bot.request({action: 'query', titles: 'testtitle'})
.then(() => {
expect(true).to.equal(false); // should never execute
}, (err) => {
expect(err.code).to.equal('bot-shutoff');
});
});

});

0 comments on commit be030bb

Please sign in to comment.