Skip to content

Commit

Permalink
Merge pull request #333 from andrewnicols/protectEndpoint
Browse files Browse the repository at this point in the history
Add Protect API
  • Loading branch information
macbre authored May 6, 2022
2 parents 72a9b9d + 52071e9 commit 486da1b
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 0 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ divdavem (https://github.com/divdavem)
maxkueng (https://github.com/maxkueng)
stdob (https://github.com/stdob)
Technical-13 (https://github.com/Technical-13)
Andrew Lyons (https://github.com/andrewnicols)
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,22 @@ Purge a given list of articles (titles or page IDs can be provided) - [read more

> By providing `Category:Foo` as `titles` argument you can purge all pages in a given category (available since [MW 1.21](https://github.com/wikimedia/mediawiki/commit/62216932c197f1c248ca2d95bc230f87a79ccd71))
### bot.protect(title, protections, options, callback)

Protect a page (A title or page ID can be provided) - [read more](https://www.mediawiki.org/wiki/API:Protect)

The `protections` value is an Array of protection information in the format:

```
{
action: string,
level?: string = 'all',
expiry?: string | number = 'never'
}
```

Calls to the Protect endpoint are not additive. Each call must include a list of _all_ intended protections, including any already in place. Each call will _replace_ all existing protections.

### bot.sendEmail(username, subject, text, callback)

Send an email to an user - [read more](http://www.mediawiki.org/wiki/API:Email)
Expand Down
26 changes: 26 additions & 0 deletions examples/protect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/usr/bin/env node
/**
* Example script getting current user information
*
* @see http://www.mediawiki.org/wiki/API:Protect
*/
'use strict';

const Bot = require( '..' );
const client = new Bot( 'examples/config.js' );

client.logIn( function () {
// Protections takes an array so allow multiple protections to be configured.
const protections = [];

// Protect the page from edits.
protections.push( {
type: 'edit',
level: 'sysop',
expiry: 'never'
} );

client.protect( 'Albert_Einstein', protections, ( err, data ) => {
console.log( JSON.stringify( data, null, '\t' ) );
} );
} );
94 changes: 94 additions & 0 deletions lib/bot.js
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,100 @@ Bot.prototype = {
} );
},

protect( title, protections, options, callback ) {
// @see https://www.mediawiki.org/wiki/API:Protect
if ( this.dryRun ) {
callback( new Error( 'In dry-run mode' ) );
return;
}

if ( typeof options === 'function' ) {
// This is the callback; options was nonexistent.
callback = options;
options = {};
}

if ( !options ) {
options = {};
}

const params = {
action: 'protect'
};

if ( typeof title === 'number' ) {
params.pageid = title;
} else {
params.title = title;
}

const formattedProtections = [];
const expiries = [];
let failed = false;
Array.from( protections ).forEach( ( protection ) => {
if ( !protection.type ) {
callback( new Error( 'Invalid protection. An action type must be specified.' ) );
failed = true;
return;
}

const level = protection.level ? protection.level : 'all';
formattedProtections.push( `${protection.type}=${level}` );

if ( protection.expiry ) {
expiries.push( protection.expiry );
} else {
// If no expiry was specified, then set the expiry to never.
expiries.push( 'never' );
}
} );

if ( failed ) {
return;
}

params.protections = formattedProtections.join( '|' );
params.expiry = expiries.join( '|' );

if ( options.reason ) {
params.reason = options.reason;
}

if ( options.tags ) {
if ( Array.isArray( options.tags ) ) {
params.tags = options.tags.join( '|' );
} else if ( typeof options.tags === 'string' ) {
params.tags = options.tags;
}
}

if ( options.cascade ) {
params.cascade = options.cascade ? 1 : 1;
}

if ( options.watchlist && typeof options.watchlist === 'string' ) {
params.watchlist = options.watchlist;
}

// Params have been generated. Now fetch the csrf token and call the API.
this.getToken( title, 'csrf', ( err, token ) => {
if ( err ) {
callback( err );
return;
}

params.token = token;

this.api.call( params, ( _err, data ) => {
if ( !_err && data.title && data.protections ) {
callback( null, data );
} else {
callback( _err );
}
}, 'POST' );
} );
},

purge( titles, callback ) {
// @see https://www.mediawiki.org/wiki/API:Purge
const params = {
Expand Down
27 changes: 27 additions & 0 deletions test/mediawiki-api-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,5 +155,32 @@ vows.describe( 'Mediawiki API' ).addBatch( {
assert.isTrue( firstItem.ns === 0 );
assert.isTrue( firstItem.title.includes( 'Albert Einstein' ) );
}
},
'protect()': {
'Command cannot run in dry-run mode.': {
topic: function () {
client.dryRun = true;
client.protect(
ARTICLE,
[ { type: 'edit', level: 'sysop' } ],
this.callback
);
},
'Command not available in dry-run mode': function ( e, res ) {
assert.isTrue( res !== null );
}
},
'When no action type is provided, no error is thrown': {
topic: function () {
client.protect(
ARTICLE,
[ { level: 'all' } ],
this.callback
);
},
'Missing action throws an Error': function ( e, res ) {
assert.isTrue( res !== null );
}
}
}
} ).export( module );

0 comments on commit 486da1b

Please sign in to comment.