User:Void/findInactiveSysops.js: Difference between revisions

m
Per removal. Consul action
(add shiny new interface)
m (Per removal. Consul action)
 
(24 intermediate revisions by 3 users not shown)
Line 1:
/* jslint strict:false */
//<nowiki>
//This script automates the process of finding inactive sysops.
//Warning: the script will replace the contents of the page you are currently viewing when you click the link at the top right of the page.
//Output is in the format of "[[User:Example|Example]] || [[Special:PermanentLink/1234|timestamp]] || [[Special:Log/Example|timestamp]]"
mw.loader.using(['oojs-ui', 'mediawiki.util']).done( function () {
var scriptActivationLink = mw.util.addPortletLink(
'p-tb',
'#',
'Find Inactive Sysops',
'pt-testscript',
'Replaces the contents of the current page with a list of inactive sysops',
null,
'#pt-adminlinks'
);
 
var $( scriptActivationLink = mw).util.addPortletLinkclick( function () {
var progressBar = new OO.ui.ProgressBarWidget();
'p-tb',
var progressField = new OO.ui.FieldLayout(
'#',
progressBar,
'Find Inactive Sysops',
{
'pt-testscript',
label: "Fetching users...",
'Replaces the contents of the current page with a list of inactive sysops',
align: 'top'
null,
}
'#pt-adminlinks'
);
 
var textPanel = new OO.ui.PanelLayout( {
$( scriptActivationLink ).click( function () {
expanded: false,
var progressBar = new OO.ui.ProgressBarWidget();
framed: false,
var progressField = new OO.ui.FieldLayout(
padded: false,
progressBar,
{} );
 
label: "Fetching users...",
var canSave = false;
align: 'top'
}
function InactiveUsersProc( config ) {
);
InactiveUsersProc.super.call( this, config );
var textPanel = new OO.ui.PanelLayout( {
expanded: false,
framed: false,
padded: false,
} );
var canSave = false;
function InactiveUsersProc( config ) {
InactiveUsersProc.super.call( this, config );
}
OO.inheritClass( InactiveUsersProc, OO.ui.ProcessDialog );
InactiveUsersProc.static.name = "Inactive Users Process";
InactiveUsersProc.static.title = "List of Inactive Users:";
InactiveUsersProc.static.actions = [
{
action: "save",
label: "Update",
flags: "primary"
},
{
label: "Cancel",
flags: "safe"
}
OO.inheritClass( InactiveUsersProc, OO.ui.ProcessDialog );
];
 
InactiveUsersProc.prototypestatic.initializename = function()"Inactive {Users Process";
InactiveUsersProc.superstatic.prototype.initialize.apply(title = "List this,of argumentsInactive )Users:";
InactiveUsersProc.static.actions = [
this.content = new OO.ui.FieldsetLayout();
{
this.content.addItems([ progressField ]);
action: "save",
this.content.$element.css( 'padding', '1em' );
label: "Update",
this.$body.append( this.content.$element );
flags: "primary"
};
},
{
InactiveUsersProc.prototype.getActionProcess = function( action ) {
label: "Cancel",
var dialog = this;
flags: "safe"
if( action && canSave ) {
}
return new OO.ui.Process( function() {
];
if( action == "save" ) {
 
updList();
InactiveUsersProc.prototype.initialize = function() {
}
InactiveUsersProc.super.prototype.initialize.apply( this, arguments );
dialog.close( { action: action } );
 
});
this.content = new OO.ui.FieldsetLayout();
}
this.content.addItems([ progressField ]);
return InactiveUsersProc.super.prototype.getActionProcess.call( this, action );
this.content.$element.css( 'padding', '1em' );
};
 
this.$body.append( this.content.$element );
InactiveUsersProc.prototype.getBodyHeight = function() {
};
return this.content.$element.outerHeight( true );
};
InactiveUsersProc.prototype.getActionProcess = function( action ) {
var dialog = this;
var windowManager = new OO.ui.WindowManager();
if( action && canSave ) {
var inactiveUsersProc = new InactiveUsersProc( {
return new OO.ui.Process( function() {
size: "large"
if( action == "save" ) {
} );
updList();
windowManager.addWindows([ inactiveUsersProc ]);
}
$('#bodyContent').append(windowManager.$element);
 
windowManager.openWindow(inactiveUsersProc);
dialog.close( {
var checked = 0;
action: action
var inactive = [];
} );
});
$.getJSON(
}
//Get userlist
return InactiveUsersProc.super.prototype.getActionProcess.call( this, action );
mw.util.wikiScript( 'api' ),
};
{
format: 'json',
InactiveUsersProc.prototype.getBodyHeight = function() {
action: 'query',
return this.content.$element.outerHeight( true );
list: 'allusers',
};
augroup: 'bot|sysop|bureaucrat|consul|autopatrolled|rollbacker|interface-admin|flow-bot',
aulimit: 150, //Unlikely to be more than 150 privilged users
var windowManager = new OO.ui.WindowManager();
}
var inactiveUsersProc = new InactiveUsersProc( {
).done( function ( data ) {
size: "large"
try {
} );
var users = data.query.allusers;
 
var userlist = [];
windowManager.addWindows([ inactiveUsersProc ]);
users.forEach( function( object ) {
$('body').append(windowManager.$element);
userlist.push( object.name );
windowManager.openWindow(inactiveUsersProc);
});
 
filterUsers( userlist );
var checked = 0;
}
var inactive = [];
catch ( e ) {
var checkList = [];
console.log( "Content request error: " + e.message );
var total = 0;
console.log( "Content request response: " + JSON.stringify( data ) );
 
}
// Get user list
} ).fail( function () {
console.log( "While getting the userlist, there was an AJAX error." );
} );
function filterUsers ( userlist ) {
var userstring = userlist.toString();
var exempt = ["John", "Void", "NDKilla", "Reception123", "Revi", "Southparkfan", "Abuse filter", "Void-bot", "Voidwalker", "Paladox", "Zppix", "ZppixBot", "RhinosF1", "MediaWiki message delivery", "ZI Jony", "Bonnedav", "Babel AutoCreate", "HeartsDo"];
for ( i = 0; i < exempt.length; i++ ) {
userstring = userstring.replace( exempt[i] + ",", "" );
}
var reducedList = userstring.split( "," );
for ( x = 0; x < reducedList.length; x++ ) {
checkUser( reducedList[x], reducedList.length );
}
}
function checkUser( user, total ) {
$.getJSON(
mw.util.wikiScript( 'api' ),
Line 129 ⟶ 101:
format: 'json',
action: 'query',
list: 'logevents|usercontribsallusers',
augroup: 'bot|sysop|bureaucrat|consul|autopatrolled|rollbacker|interface-admin|flow-bot',
leprop: 'timestamp',
lediraulimit: 'older',150 // Unlikely to be more than 150 privilged users
leuser: user,
lelimit: 1, //We only need the most recent log action/edit
uclimit: 1,
ucuser: user,
ucdir: 'older',
ucprop: 'timestamp|ids'
}
).done( function ( data ) {
try {
var tribsDatausers = data.query.usercontribsallusers;
var logsDatauserlist = data.query.logevents[];
 
var activeLogs, activeTribs, active;
users.forEach( function( object var) tribsInfo;{
userlist.push( object.name );
});
if( typeof( logsData[0].timestamp ) != "undefined" ) {
activeLogs = compareDatesfilterUsers( logsData[0].timestamp, "logs"userlist );
}
else {
activeLogs = false;
}
if( typeof( tribsData[0] ) != "undefined" ) {
tribsInfo = tribsData[0].revid + "|" + tribsData[0].timestamp;
activeTribs = compareDates( tribsInfo, "tribs" );
}
else {
activeTribs = false;
}
if( activeLogs === false && activeTribs === false ) {
inactive.push([user, tribsData, logsData]);
}
checked++;
progressBar.setProgress( parseInt(checked / total) * 100 );
if( checked == total ) {
listInactiveUsers();
}
}
catch ( e ) {
Line 172 ⟶ 119:
console.log( "Content request response: " + JSON.stringify( data ) );
}
} ).fail( function () {
} );
console.log( "While getting the userlist, there was an AJAX error." );
}
} );
 
function compareDates ( data, dataType ) {
function filterUsers ( userlist ) {
//Gets current date in yyyymmdd
var todayuserstring = new Dateuserlist.toString();
var exempt = ["John", "NDKilla", "Reception123", "Revi", "Southparkfan", "Abuse filter", "Void", "Zppix", "RhinosF1", "MediaWiki message delivery", "MediaWiki default", "Babel AutoCreate", "Dmehus", "Revibot", "Delete page script", "Move page script", "Flow talk page manager", "Universal Omega", "HeartsDo", "MacFan4000"];
var dd = today.getDate();
 
var mm = today.getMonth() + 1; //January is 0!
for ( i = 0; i < exempt.length; i++ ) {
var yyyy = today.getFullYear();
userstring = userstring.replace( exempt[i] + ",", "" );
//Set back 3 months
}
mm -= 3;
 
if( mm < 0 ) {
checkList = userstring.split( "," );
mm += 12;
yyyytotal -= 1checkList.length;
checkUser( checkList.pop() );
}
 
iffunction checkUser( dd < 10user ) {
$.getJSON(
dd = '0' + dd;
mw.util.wikiScript( 'api' ),
}
{
format: 'json',
if( mm<10 ) {
mm = '0' + mm; action: 'query',
list: 'logevents|usercontribs',
}
today = '' + yyyy + mm + dd; //This is a stringleprop: 'timestamp',
ledir: 'older',
leuser: user,
var date;
lelimit: 1, //We only need the most recent log action/edit
var isActive;
uclimit: 1,
if( dataType === "logs" ) {
ucuser: user,
date = data.slice( 0, data.indexOf('T') );
ucdir: 'older',
date = date.replace( "-", "" );
ucprop: 'timestamp|ids'
}
else if( dataType === "tribs" ) { }
date = data.slice( data ).indexOfdone('|') +function 1,( data.indexOf('T' ) );{
try {
date = date.replace( "-", "" );
var tribsData = data.query.usercontribs;
var logsData = data.query.logevents;
var activeLogs, activeTribs, active, tribsInfo;
 
if( typeof( logsData[0] ) != "undefined" ) {
activeLogs = compareDates( logsData[0].timestamp, "logs" );
} else {
activeLogs = false;
}
 
if( typeof( tribsData[0] ) != "undefined" ) {
tribsInfo = tribsData[0].revid + "|" + tribsData[0].timestamp;
activeTribs = compareDates( tribsInfo, "tribs" );
} else {
activeTribs = false;
}
 
if( activeLogs === false && activeTribs === false ) {
inactive.push([user, tribsData, logsData]);
}
 
checked++;
progressBar.setProgress( parseInt( (checked/total) * 100 ) );
 
if( checkList.length > 0 ) {
checkUser( checkList.pop() );
} else {
listInactiveUsers();
}
} catch ( e ) {
console.log( "Content request error: " + e.message );
console.log( "Content request response: " + JSON.stringify( data ) );
}
} );
}
if ( date < today ) {
function compareDates ( data, dataType ) {
isActive = false;
//Gets current date in yyyymmdd
}
var today = new Date();
else {
isActivevar dd = truetoday.getDate();
var mm = today.getMonth() + 1; //January is 0!
}
var yyyy = today.getFullYear();
return isActive;
 
}
//Set back 3 months
mm -= 3;
function listInactiveUsers() {
sorted = inactive.sort if( function(mm a,< b0 ) {
mm += 12;
return a[0].localeCompare( b[0] );
} yyyy )-= 1;
for( var i in sorted ) {
var userName = sorted[i][0];
var tribsArray = sorted[i][1];
var logsArray = sorted[i][2];
var userLink = "[[User:<a href=\"https://publictestwiki.com/wiki/Special:Contribs/" + userName + "\">" + userName + "</a>|" + userName + "]]";
var tribsInfo;
if( tribsArray[0] !== undefined ) {
tribsInfo = tribsArray[0].timestamp;
tribsInfo = tribsInfo.slice( 0, tribsInfo.indexOf("T") );
tribsInfo = tribsArray[0].revid + "|" + tribsInfo;
tribsInfo = "[[Special:PermanentLink/" + tribsInfo + "]]";
}
 
else {
if( dd < 10 ) {
tribsInfo = 'None';
dd = '0' + dd;
}
 
var logsInfo = logsArray[0].timestamp;
if( mm<10 ) {
logsInfo = logsInfo.slice( 0, logsInfo.indexOf("T") );
mm = '0' + mm;
logsInfo = "[[Special:Log/" + userName + "|" + logsInfo + "]]";
}
textPanel.$element.append( "<li>" + userLink + " || " + tribsInfo + " || " + logsInfo + "</li>" );
 
today = '' + yyyy + mm + dd; //This is a string
var date;
var isActive;
 
if( dataType === "logs" ) {
date = data.slice( 0, data.indexOf('T') );
date = date.replace( /-/g, "" );
} else if( dataType === "tribs" ) {
date = data.slice( data.indexOf('|') + 1, data.indexOf('T') );
date = date.replace( /-/g, "" );
}
 
return date >= today;
}
 
inactiveUsersProc.content.clearItems();
function listInactiveUsers() {
inactiveUsersProc.content.addItems([textPanel]);
sorted = inactive.sort( function( a, b ) {
inactiveUsersProc.updateSize();
return a[0].localeCompare( b[0] );
canSave = true;
} );
}
 
for( var i in sorted ) {
function updList() {
var listuserName = textPanel.$elementsorted[i][0].innerText;
var tribsArray = sorted[i][1];
list = '|-\n|' + list;
var logsArray = sorted[i][2];
while( list.indexOf("\n[[User:") > 0 ) {
var userLink = "[[User:<a href=\"https://publictestwiki.com/wiki/Special:Contribs/" + userName + "\">" + userName + "</a>|" + userName + "]]";
list = list.substr( 0, list.indexOf( "\n[[User:" ) ) + '\n|-\n|' + list.substr( list.indexOf( "\n[[User:" ) + 1 );
 
var tribsInfo;
if( tribsArray[0] !== undefined ) {
tribsInfo = tribsArray[0].timestamp;
tribsInfo = tribsInfo.slice( 0, tribsInfo.indexOf("T") );
tribsInfo = tribsArray[0].revid + "|" + tribsInfo;
tribsInfo = "[[Special:PermanentLink/" + tribsInfo + "]]";
} else {
tribsInfo = 'None';
}
 
var logsInfo;
if( logsArray[0] !== undefined ) {
logsInfo = logsArray[0].timestamp;
logsInfo = logsInfo.slice( 0, logsInfo.indexOf("T") );
logsInfo = "[[Special:Log/" + userName + "|" + logsInfo + "]]";
} else {
logsInfo = 'None';
}
 
textPanel.$element.append( "<li>" + userLink + " || " + tribsInfo + " || " + logsInfo + "</li>" );
}
inactiveUsersProc.content.clearItems();
inactiveUsersProc.content.addItems([textPanel]);
inactiveUsersProc.updateSize();
canSave = true;
}
$.getJSON(
function updList() {
mw.util.wikiScript( 'api' ),
var list = textPanel.$element[0].innerText;
{
list = '|-\n|' + list;
format: 'json',
while( list.indexOf("\n[[User:") > 0 ) {
action: 'query',
list = list.substr( 0, list.indexOf( "\n[[User:" ) ) + '\n|-\n|' + list.substr( list.indexOf( "\n[[User:" ) + 1 );
pageids: 238,
}
prop: 'revisions',
rvprop: 'content'
}
).done( function ( data ) {
try {
var wtext = data.query.pages[238].revisions[0]['*'];
wtext = wtext.substr( 0, wtext.indexOf("|-") ) + list + '\n' + wtext.substr( wtext.indexOf( "|}" ) );
$.ajax( {
url: mw.util.wikiScript( 'api' ),
type: 'POST',
dataType: 'json',
data: {
format: 'json',
action: 'edit',
title: 'TestWiki:Inactivity/Inactive administrators',
text: wtext,
summary: '[[User:Void/findInactiveSysops.js|Automatically]] updating list',
token: mw.user.tokens.get( 'csrfToken' ),
}
} ).done( function() {
alert( "Updated TestWiki:Inactivity/Inactive administrators" );
var reload = new OO.ui.ButtonWidget( { label: 'Load original page' } );
$('#upd-inactive-bttn').replaceWith( reload.$element.click( function() { window.location.reload(); } ) );
} ).fail( function ( e, data ) {
console.log( e.message );
console.log( JSON.stringify( data ) );
} );
}
catch( e ) {
// ignore
}
} ).fail( function ( e, data ) {
console.log( e.message );
console.log( JSON.stringify( data ) );
} );
}
} );
 
// Get contents of TestWiki:Inactivity/Inactive administrators
$.getJSON(
mw.util.wikiScript( 'api' ),
{
format: 'json',
action: 'query',
pageids: 238,
prop: 'revisions',
rvprop: 'content',
rvslots: 'main'
}
).done( function ( data ) {
try {
var wtext = data.query.pages[238].revisions[0].slots.main['*'];
wtext = wtext.substr( 0, wtext.indexOf("|-") ) + list + '\n' + wtext.substr( wtext.indexOf( "|}" ) );
 
$.ajax( {
url: mw.util.wikiScript( 'api' ),
type: 'POST',
dataType: 'json',
data: {
format: 'json',
action: 'edit',
title: 'TestWiki:Inactivity/Inactive administrators',
text: wtext,
summary: '[[User:Void/findInactiveSysops.js|Automatically]] updating list',
token: mw.user.tokens.get( 'csrfToken' ),
}
} ).done( function() {
alert( "Updated TestWiki:Inactivity/Inactive administrators" );
} ).fail( function ( e, data ) {
console.log( e.message );
console.log( JSON.stringify( data ) );
} );
}
catch( e ) {
// ignore
}
} ).fail( function ( e, data ) {
console.log( e.message );
console.log( JSON.stringify( data ) );
} );
}
} );
});
//</nowiki>