User:Zppix/testgblock.js: Difference between revisions
Content added Content deleted
No edit summary |
(use cleaner implementation) |
||
(5 intermediate revisions by one other user not shown) | |||
Line 10: | Line 10: | ||
mw.loader.using( ['mediawiki.api', 'oojs-ui'], function () { |
mw.loader.using( ['mediawiki.api', 'oojs-ui'], function () { |
||
if( mw.config.get( 'wgPageName' ) !== 'Special:MassGlobalBlock' ) { |
if( mw.config.get( 'wgPageName' ) !== 'Special:MassGlobalBlock' ) { |
||
⚫ | |||
return; |
return; |
||
} |
} |
||
if( mw.config.get(wgUserGroups).includes( ' |
if( !mw.config.get( 'wgUserGroups' ).includes( 'flooder' ) ) { |
||
return alert( 'You do not have permission to access this interface, or missing the flooder usergroup.' ); |
|||
} |
|||
var api = new mw.Api(); |
var api = new mw.Api(); |
||
Line 285: | Line 286: | ||
$( '#bodyContent' ).text( '' ); |
$( '#bodyContent' ).text( '' ); |
||
$( '#bodyContent' ).append( mgbForm.$element ); |
$( '#bodyContent' ).append( mgbForm.$element ); |
||
⚫ | |||
} ); |
Latest revision as of 22:29, 7 September 2019
/**
* Script that allows for mass (global) blocking via Special:MassGlobalBlock
* To use, add the following to your common.js:
* mw.loader.load( 'https://meta.miraheze.org/w/index.php?title=User:Void/massGBlock.js&action=raw&ctype=text/javascript' );
* Then, navigate to Special:MassGlobalBlock
* Note: this script is only compatible with IPv4 ranges.
* All ranges listed must be on their own line and be in a valid CIDR format.
*/
mw.loader.using( ['mediawiki.api', 'oojs-ui'], function () {
if( mw.config.get( 'wgPageName' ) !== 'Special:MassGlobalBlock' ) {
return;
}
if( !mw.config.get( 'wgUserGroups' ).includes( 'flooder' ) ) {
return alert( 'You do not have permission to access this interface, or missing the flooder usergroup.' );
}
var api = new mw.Api();
var inRanges = new OO.ui.MultilineTextInputWidget( {
id: 'mgb-ranges',
required: true,
rows: 10,
validate: 'not-empty'
} );
var inExpiry = new OO.ui.ComboBoxInputWidget( {
id: 'mgb-expiry',
options: [
{ data: '1 month' },
{ data: '3 months' },
{ data: '6 months' },
{ data: '1 year' }
],
required: true,
value: '1 year',
validate: 'not-empty'
} );
var inReason = new OO.ui.ComboBoxInputWidget( {
id: 'mgb-reason',
options: [
{ data: 'Crosswiki spamming. Contact cvt{{@}}miraheze.org if affected.' },
{ data: 'Crosswiki abuse. Contact cvt{{@}}miraheze.org if affected.' },
{ data: 'Vandalism. Contact cvt{{@}}miraheze.org if affected.' },
{ data: 'Long term abuse. Contact cvt{{@}}miraheze.org if affected.' },
{ data: 'Web host or proxy. Contact cvt{{@}}miraheze.org if affected.' }
],
required: true,
value: 'Web host or proxy. Contact cvt{{@}}miraheze.org if affected.',
validate: 'not-empty'
} );
var inAnonOnly = new OO.ui.CheckboxInputWidget( {
id: 'mgb-anononly',
selected: true,
value: 1
} );
var inGlobalBlocks = new OO.ui.CheckboxInputWidget( {
id: 'mgb-globalblocks',
selected: true,
value: 1
} );
var inLocalBlocks = new OO.ui.CheckboxInputWidget( {
id: 'mgb-localblocks',
selected: true,
value: 1
} );
var inSubmit = new OO.ui.ButtonWidget( {
id: 'mgb-submit',
label: 'Submit',
flags: ['destructive', 'primary']
} );
inSubmit.on( 'click', doSubmit );
var mgbForm = new OO.ui.FieldsetLayout( {
label: 'Mass blocking interface'
} );
mgbForm.addItems( [
new OO.ui.FieldLayout(
inRanges,
{ label: 'IP Ranges:', align: 'top', help: 'Only works with IPv4!', helpInline: true }
),
new OO.ui.FieldLayout(
inExpiry,
{ label: 'Expiry:', align: 'top' }
),
new OO.ui.FieldLayout(
inReason,
{ label: 'Reason', align: 'top' }
),
new OO.ui.FieldLayout(
inAnonOnly,
{ label: 'Block anonymous users only', align: 'inline' }
),
new OO.ui.FieldLayout(
inGlobalBlocks,
{ label: 'Block ranges globally', align: 'inline' }
),
new OO.ui.FieldLayout(
inLocalBlocks,
{ label: 'Block ranges locally', align: 'inline' }
),
new OO.ui.FieldLayout(
inSubmit
),
] );
var IPRange = function IPR ( value ) {
this.getRange = function () {
return this.ip + '/' + this.cidr;
};
this.getDecimal = function () {
var dots = this.ip.split( '.' );
if( dots.length !== 4 ) {
throw 'Invalid IP ' + this.ip;
}
return ( ( ( ( ( parseInt( dots[0] ) * 256 ) + parseInt( dots[1] ) ) * 256 ) + parseInt( dots[2] ) ) * 256 ) + parseInt( dots[3] );
};
this.getNext = function () {
var jump = Math.pow( 2, 32 - parseInt( this.cidr ) );
return this.getDecimal() + jump;
};
this.combine = function ( other ) {
var ourDecimal = this.getDecimal(), otherDecimal = other.getDecimal();
if( ourDecimal > otherDecimal ) {
return other.combine( this ); // Impossible, but let's account for it anyway
}
var ip = null, cidr = null;
if( ourDecimal === otherDecimal ) {
ip = this.ip;
cidr = ( parseInt( this.cidr ) < parseInt( other.cidr ) ? this.cidr : other.cidr );
} else if( ourDecimal < otherDecimal && this.getNext() >= other.getNext() ) {
ip = this.ip;
cidr = this.cidr;
} else if( this.getNext() == otherDecimal && this.cidr === other.cidr ) {
ip = this.ip;
cidr = '' + ( parseInt( this.cidr ) - 1 );
} else {
throw 'Cannot combine ' + this.getRange() + ' with ' + other.getRange();
}
return new IPRange( ip + '/' + cidr );
};
var vlist = value.split( '/' );
if( vlist.length !== 2 ) {
throw 'Invalid CIDR';
}
this.ip = vlist[0];
this.cidr = vlist[1];
if( this.getDecimal() % Math.pow( 2, ( 32 - parseInt( this.cidr ) ) ) ) {
throw 'Invalid IP range';
}
};
function consolidateIPRanges ( ranges ) {
var cleanList = [];
for( i = 0; i < ranges.length; i++ ) {
try {
cleanList.push( new IPRange( ranges[i] ) );
} catch( e ) {
console.log( 'Invalid input: ' + ranges[i], e );
}
}
ranges = cleanList.sort( function ( a, b ) { return a.getDecimal() - b.getDecimal(); } );
var change = true;
while( change ) {
change = false;
var cranges = [];
for( i = 0; i < ranges.length; i++ ) {
try {
cranges[cranges.length - 1] = cranges[cranges.length - 1].combine( ranges[i] );
change = true;
} catch( e ) {
cranges.push( ranges[i] );
}
var change2 = true;
while( change2 ) {
change2 = false;
var range = cranges.pop();
try {
cranges[cranges.length - 1].combine( range );
change2 = true;
} catch( e ) {
cranges.push( range );
}
}
}
ranges = cranges;
}
return ranges;
}
function doSubmit () {
if( !inGlobalBlocks.isSelected() && !inLocalBlocks.isSelected() ) {
return alert( 'You must apply a block locally or globally!' );
}
if( !mgbForm.items.every( function ( e ) { return e.fieldWidget.value !== ''; } ) ) {
return alert( 'Please fill all required parts of the form!' );
}
mgbForm.items.forEach( function ( e ) {
e.fieldWidget.setDisabled( true );
} );
var ranges = inRanges.value.split( '\n' ),
deferred = null,
conf = {
reason: inReason.value,
expiry: inExpiry.value,
anononly: inAnonOnly.isSelected() ? 1 : 0
};
ranges = consolidateIPRanges( ranges );
if( inGlobalBlocks.isSelected() ) {
deferred = makeBlockFunc( true, ranges[0].getRange(), conf )();
}
if( inLocalBlocks.isSelected() ) {
if( deferred ) {
deferred = deferred.then( makeBlockFunc( false, ranges[0].getRange(), conf ) );
} else {
deferred = makeBlockFunc( false, ranges[0].getRange(), conf )();
}
}
for( i = 1; i < ranges.length; i++ ) {
if( inGlobalBlocks.isSelected() ) {
deferred = deferred.then( makeBlockFunc( true, ranges[i].getRange(), conf ) );
}
if( inLocalBlocks.isSelected() ) {
deferred = deferred.then( makeBlockFunc( false, ranges[i].getRange(), conf ) );
}
}
$.when( deferred ).then( doFinish );
}
function makeBlockFunc ( global, range, config ) {
return function () {
return $.Deferred( function ( deferred ) {
var data = {
format: 'json',
expiry: config.expiry,
reason: config.reason,
anononly: config.anononly
};
if ( global ) {
data.action = 'globalblock';
data.target = range;
} else {
data.action = 'block';
data.user = range;
data.nocreate = 1;
}
var promise = api.postWithToken( 'csrf', data );
promise.fail( function ( e ) {
console.log( 'Could not ' + ( global ? 'globally' : 'locally' ) + ' block ' + range );
console.log( e );
} );
promise.always( function () {
deferred.resolve();
} );
} );
};
}
function doFinish () {
alert( 'Done blocking' );
mgbForm.items.forEach( function ( e ) { e.fieldWidget.setDisabled( false ); } );
}
// Create UI
$( '.firstHeading' ).text( 'Mass Global Block' );
$( '#bodyContent' ).text( '' );
$( '#bodyContent' ).append( mgbForm.$element );
} );