MediaWiki:Gadget-twinkledeprod.js: Difference between revisions

From Sarkarverse
Jump to navigation Jump to search
m (1 revision)
 
(Localise)
 
(6 intermediate revisions by 2 users not shown)
Line 15: Line 15:


Twinkle.deprod = function() {
Twinkle.deprod = function() {
if( mw.config.get( 'wgNamespaceNumber' ) !== 14 || ! Morebits.userIsInGroup( 'sysop' ) || !((/^Category:Proposed_deletion_as_of/).test(mw.config.get( 'wgPageName' ))) ) {
if(
mw.config.get( 'wgNamespaceNumber' ) !== 14 ||
! Morebits.userIsInGroup( 'sysop' ) ||
!((/proposed_deletion/i).test(mw.config.get( 'wgPageName' )))
) {
return;
return;
}
}
Twinkle.addPortletLink( callback, "Deprod", "tw-deprod", "Delete prod pages found in this category");
Twinkle.addPortletLink( Twinkle.deprod.callback, "Deprod", "tw-deprod", "Delete prod pages found in this category");
};
};


var unlinkCache = {},
var concerns = {};
concerns = {},
currentDeleteCounter = 0,
currentUnlinkCounter = 0,
currentDeletor = null,


callback = function() {
Twinkle.deprod.callback = function() {
var Window = new Morebits.simpleWindow( 800, 400 );
var Window = new Morebits.simpleWindow( 800, 400 );
Window.setTitle( "PROD cleaning" );
Window.setTitle( "PROD cleaning" );
Window.setScriptName( "Twinkle" );
Window.setScriptName( "Twinkle" );
Window.addFooterLink( "Proposed deletion", "WP:PROD" );
Window.addFooterLink( "Proposed deletion", "SV:PROD" );
Window.addFooterLink( "Twinkle help", "WP:TW/DOC#deprod" );
Window.addFooterLink( "Twinkle help", "SV:TW/DOC#deprod" );


var form = new Morebits.quickForm( callback_commit );
var form = new Morebits.quickForm( callback_commit );
var statusdiv = document.createElement( 'div' );
statusdiv.style.padding = '15px';  // just so it doesn't look broken
Window.setContent(statusdiv);
Morebits.status.init(statusdiv);
Window.display();


var query = {
var query = {
Line 41: Line 47:
'gcmtitle': mw.config.get( 'wgPageName' ),
'gcmtitle': mw.config.get( 'wgPageName' ),
'gcmlimit' : 5000, // the max for sysops
'gcmlimit' : 5000, // the max for sysops
'prop': [ 'categories', 'revisions' ],
'prop': [ 'info', 'revisions' ],
'rvprop': [ 'content' ]
'rvprop': [ 'content' ],
'inprop': [ 'protection' ]
};
};


var wikipedia_api = new Morebits.wiki.api( 'Grabbing pages', query,
var statelem = new Morebits.status("Grabbing list of pages");
function( self ) {
var wikipedia_api = new Morebits.wiki.api( 'loading...', query, function( apiobj ) {
var $doc = $(self.responseXML);
var $doc = $(apiobj.responseXML);
var $pages = $doc.find('page[ns!="6"]');  // all non-files
var $pages = $doc.find('page[ns!="6"]');  // all non-files
var list = [];
var list = [];
var re = /\{\{Proposed deletion/;
var re = /\{\{Proposed deletion/;
$pages.each(function() {
$pages.each(function() {
var $self = $(this);
var $page = $(this);
var page = $self.attr('title');
var title = $page.attr('title');
var content = $self.find('revisions rev').text();
var content = $page.find('revisions rev').text();
var concern = '';
var $editprot = $page.find('pr[type="edit"][level="sysop"]');
var res = re.exec(content);
var isProtected = $editprot.length > 0;
if( res ) {
var parsed = Morebits.wikitext.template.parse( content, res.index );
concern = parsed.parameters.concern || '';
}
list.push( {label:page + ' (' + concern + ')' , value:page, checked:concern !== '' });
concerns[page] = concern;


var metadata = [];
var res = re.exec(content);
if( res ) {
var parsed = Morebits.wikitext.template.parse( content, res.index );
concerns[title] = parsed.parameters.concern || '';
metadata.push(concerns[title]);
}
if (isProtected) {
metadata.push("fully protected" +
($editprot.attr('expiry') === 'infinity' ? ' indefinitely' : (', expires ' + $editprot.attr('expiry'))));
}
list.push({
label: (metadata.length ? ('(' + metadata.join('; ') + ')') : ''),
value: title,
checked: concerns[title] !== '',
style: (isProtected ? 'color:red' : '')
});
});
self.params.form.append({
});
'type': 'checkbox',
apiobj.params.form.append({ type: 'header', label: 'Pages to delete' });
'name': 'pages',
apiobj.params.form.append({
'list': list
type: 'button',
});
label: "Select All",
self.params.form.append({
event: function(e) {
'type': 'submit'
$(Morebits.quickForm.getElements(e.target.form, 'pages')).prop('checked', true);
});
}
self.params.Window.setContent( self.params.form.render() );
});
apiobj.params.form.append({
type: 'button',
label: "Deselect All",
event: function(e) {
$(Morebits.quickForm.getElements(e.target.form, 'pages')).prop('checked', false);
}
});
apiobj.params.form.append({
'type': 'checkbox',
'name': 'pages',
'list': list
});
apiobj.params.form.append({
'type': 'submit'
});
});


wikipedia_api.params = { form:form, Window:Window };
var rendered = apiobj.params.form.render();
wikipedia_api.post();
apiobj.params.Window.setContent( rendered );
var root = document.createElement( 'div' );
$(Morebits.quickForm.getElements(rendered, 'pages')).each(function(index, checkbox) {
Morebits.simpleWindow.setButtonsEnabled( true );
var $checkbox = $(checkbox);
var link = Morebits.htmlNode("a", $checkbox.val());
link.setAttribute("class", "deprod-page-link");
link.setAttribute("href", mw.util.getUrl($checkbox.val()));
link.setAttribute("target", "_blank");
$checkbox.next().prepend([link, " "]);
});
}, statelem );


Morebits.status.init( root );
wikipedia_api.params = { form:form, Window:Window };
Window.setContent( root );
wikipedia_api.post();
Window.display();
};
},


callback_commit = function(event) {
var callback_commit = function(event) {
var pages = event.target.getChecked( 'pages' );
var pages = event.target.getChecked( 'pages' );
Morebits.status.init( event.target );
Morebits.status.init( event.target );
function toCall( work ) {
 
if( work.length === 0 ) {
var batchOperation = new Morebits.batchOperation("Deleting articles");
Morebits.status.info( 'work done' );
batchOperation.setOption("chunkSize", Twinkle.getPref('proddeleteChunks'));
window.clearInterval( currentDeletor );
batchOperation.setOption("preserveIndividualStatusLines", true);
Morebits.wiki.removeCheckpoint();
batchOperation.setPageList(pages);
return;
batchOperation.run(function(pageName) {
} else if( currentDeleteCounter <= 0 || currentUnlinkCounter <= 0 ) {
var params = { page: pageName, reason: concerns[page] };
unlinkCache = []; // Clear the cache
 
var pages = work.pop(), i;
var query = {
for( i = 0; i < pages.length; ++i ) {
'action': 'query',
var page = pages[i];
'titles': pageName,
var query = {
'prop': 'redirects',
'action': 'query',
'rdlimit': 5000  // 500 is max for normal users, 5000 for bots and sysops
'prop': 'revisions',
};
'rvprop': [ 'content' ],
var wikipedia_api = new Morebits.wiki.api( 'Grabbing redirects', query, callback_deleteRedirects );
'rvlimit': 1,
wikipedia_api.params = params;
'titles': page
wikipedia_api.post();
};
 
var wikipedia_api = new Morebits.wiki.api( 'Checking if page ' + page + ' exists', query, callback_check );
query = {
wikipedia_api.params = { page:page, reason: concerns[page] };
'action': 'query',
wikipedia_api.post();
'titles': 'Talk:' + pageName
}
};
}
wikipedia_api = new Morebits.wiki.api( 'Checking whether ' + pageName + ' has a talk page', query,
}
callback_deleteTalk );
var work = Morebits.array.chunk( pages, Twinkle.getPref('proddeleteChunks') );
wikipedia_api.params = params;
Morebits.wiki.addCheckpoint();
wikipedia_api.post();
currentDeletor = window.setInterval( toCall, 1000, work );
 
var page = new Morebits.wiki.page(pageName, "Deleting article " + pageName);
page.setEditSummary("Expired [[SV:PROD|PROD]], concern was: " + concerns[pageName] + Twinkle.getPref('deletionSummaryAd'));
page.suppressProtectWarning();
page.deletePage(batchOperation.workerSuccess, batchOperation.workerFailure);
});
},
},
callback_check = function( self ) {
callback_deleteTalk = function( apiobj ) {
var $doc = $(self.responseXML);
var $doc = $(apiobj.responseXML);
var normal = $doc.find('normalized n').attr('to');
var exists = $doc.find('page:not([missing])').length > 0;
if( normal ) {
self.params.page = normal;
}
var exists = $doc.find('pages page:not([missing])').size() > 0;


if( ! exists ) {
if( !exists ) {
self.statelem.error( "It seems that the page doesn't exist, perhaps it has already been deleted" );
// no talk page; forget about it
return;
return;
}
}


var query = {
var page = new Morebits.wiki.page('Talk:' + apiobj.params.page, "Deleting talk page of article " + apiobj.params.page);
'action': 'query',
page.setEditSummary("[[SV:CSD#G8|G8]]: [[Help:Talk page|Talk page]] of deleted page \"" + apiobj.params.page + "\"" + Twinkle.getPref('deletionSummaryAd'));
'list': 'backlinks',
'blfilterredir': 'redirects',
'bltitle': self.params.page,
'bllimit': Morebits.userIsInGroup( 'sysop' ) ? 5000 : 500 // 500 is max for normal users, 5000 for bots and sysops
};
var wikipedia_api = new Morebits.wiki.api( 'Grabbing redirects', query, callback_deleteRedirects );
wikipedia_api.params = self.params;
wikipedia_api.post();
 
var page = new Morebits.wiki.page('Talk:' + self.params.page, "Deleting talk page");
page.setEditSummary("[[WP:CSD#G8|G8]]: [[Help:Talk page|Talk page]] of deleted page \"" + self.params.page + "\"" + Twinkle.getPref('deletionSummaryAd'));
page.deletePage();
 
page = new Morebits.wiki.page(self.params.page, "Deleting article");
page.setEditSummary("Expired [[WP:PROD|PROD]], concern was: " + self.params.reason + Twinkle.getPref('deletionSummaryAd'));
page.deletePage();
page.deletePage();
},
},
callback_deleteRedirects = function( self ) {
callback_deleteRedirects = function( apiobj ) {
$doc = $(self.responseXML);
var $doc = $(apiobj.responseXML);
$doc.find("backlinks bl").each(function(){
$doc.find("redirects rd").each(function(){
var title = $(this).attr('title');
var title = $(this).attr('title');
var page = new Morebits.wiki.page(title, "Deleting redirecting page " + title);
var page = new Morebits.wiki.page(title, "Deleting redirecting page " + title);
page.setEditSummary("[[WP:CSD#R1|R1]]: Redirect to deleted page \"" + self.params.page + "\"" + Twinkle.getPref('deletionSummaryAd'));
page.setEditSummary("[[SV:CSD#G8|G8]]: Redirect to deleted page \"" + apiobj.params.page + "\"" + Twinkle.getPref('deletionSummaryAd'));
page.deletePage();
page.deletePage();
});
});

Latest revision as of 21:47, 22 December 2018

//<nowiki>


(function($){


/*
****************************************
*** twinkledeprod.js: Batch deletion of expired PRODs (sysops only)
****************************************
* Mode of invocation:     Tab ("Deprod")
* Active on:              Categories whose name starts with "Category:Proposed deletion as of"
* Config directives in:   TwinkleConfig
*/

Twinkle.deprod = function() {
	if(
		mw.config.get( 'wgNamespaceNumber' ) !== 14 ||
		! Morebits.userIsInGroup( 'sysop' ) ||
		!((/proposed_deletion/i).test(mw.config.get( 'wgPageName' )))
	) {
		return;
	}
	Twinkle.addPortletLink( Twinkle.deprod.callback, "Deprod", "tw-deprod", "Delete prod pages found in this category");
};

var concerns = {};

Twinkle.deprod.callback = function() {
	var Window = new Morebits.simpleWindow( 800, 400 );
	Window.setTitle( "PROD cleaning" );
	Window.setScriptName( "Twinkle" );
	Window.addFooterLink( "Proposed deletion", "SV:PROD" );
	Window.addFooterLink( "Twinkle help", "SV:TW/DOC#deprod" );

	var form = new Morebits.quickForm( callback_commit );

	var statusdiv = document.createElement( 'div' );
	statusdiv.style.padding = '15px';  // just so it doesn't look broken
	Window.setContent(statusdiv);
	Morebits.status.init(statusdiv);
	Window.display();

	var query = {
		'action': 'query',
		'generator': 'categorymembers',
		'gcmtitle': mw.config.get( 'wgPageName' ),
		'gcmlimit' : 5000, // the max for sysops
		'prop': [ 'info', 'revisions' ],
		'rvprop': [ 'content' ],
		'inprop': [ 'protection' ]
	};

	var statelem = new Morebits.status("Grabbing list of pages");
	var wikipedia_api = new Morebits.wiki.api( 'loading...', query, function( apiobj ) {
		var $doc = $(apiobj.responseXML);
		var $pages = $doc.find('page[ns!="6"]');  // all non-files
		var list = [];
		var re = /\{\{Proposed deletion/;
		$pages.each(function() {
			var $page = $(this);
			var title = $page.attr('title');
			var content = $page.find('revisions rev').text();
			var $editprot = $page.find('pr[type="edit"][level="sysop"]');
			var isProtected = $editprot.length > 0;

			var metadata = [];
			var res = re.exec(content);
			if( res ) {
				var parsed = Morebits.wikitext.template.parse( content, res.index );
				concerns[title] = parsed.parameters.concern || '';
				metadata.push(concerns[title]);
			}
			if (isProtected) {
				metadata.push("fully protected" +
					($editprot.attr('expiry') === 'infinity' ? ' indefinitely' : (', expires ' + $editprot.attr('expiry'))));
			}
			list.push({
				label: (metadata.length ? ('(' + metadata.join('; ') + ')') : ''),
				value: title,
				checked: concerns[title] !== '',
				style: (isProtected ? 'color:red' : '')
			});
		});
		apiobj.params.form.append({ type: 'header', label: 'Pages to delete' });
		apiobj.params.form.append({
			type: 'button',
			label: "Select All",
			event: function(e) {
				$(Morebits.quickForm.getElements(e.target.form, 'pages')).prop('checked', true);
			}
		});
		apiobj.params.form.append({
			type: 'button',
			label: "Deselect All",
			event: function(e) {
				$(Morebits.quickForm.getElements(e.target.form, 'pages')).prop('checked', false);
			}
		});
		apiobj.params.form.append({
			'type': 'checkbox',
			'name': 'pages',
			'list': list
		});
		apiobj.params.form.append({
			'type': 'submit'
		});

		var rendered = apiobj.params.form.render();
		apiobj.params.Window.setContent( rendered );
		$(Morebits.quickForm.getElements(rendered, 'pages')).each(function(index, checkbox) {
			var $checkbox = $(checkbox);
			var link = Morebits.htmlNode("a", $checkbox.val());
			link.setAttribute("class", "deprod-page-link");
			link.setAttribute("href", mw.util.getUrl($checkbox.val()));
			link.setAttribute("target", "_blank");
			$checkbox.next().prepend([link, " "]);
		});
	}, statelem );

	wikipedia_api.params = { form:form, Window:Window };
	wikipedia_api.post();
};

var callback_commit = function(event) {
	var pages = event.target.getChecked( 'pages' );
	Morebits.status.init( event.target );

	var batchOperation = new Morebits.batchOperation("Deleting articles");
	batchOperation.setOption("chunkSize", Twinkle.getPref('proddeleteChunks'));
	batchOperation.setOption("preserveIndividualStatusLines", true);
	batchOperation.setPageList(pages);
	batchOperation.run(function(pageName) {
		var params = { page: pageName, reason: concerns[page] };

		var query = {
			'action': 'query',
			'titles': pageName,
			'prop': 'redirects',
			'rdlimit': 5000  // 500 is max for normal users, 5000 for bots and sysops
		};
		var wikipedia_api = new Morebits.wiki.api( 'Grabbing redirects', query, callback_deleteRedirects );
		wikipedia_api.params = params;
		wikipedia_api.post();

		query = {
			'action': 'query',
			'titles': 'Talk:' + pageName
		};
		wikipedia_api = new Morebits.wiki.api( 'Checking whether ' + pageName + ' has a talk page', query,
			callback_deleteTalk );
		wikipedia_api.params = params;
		wikipedia_api.post();

		var page = new Morebits.wiki.page(pageName, "Deleting article " + pageName);
		page.setEditSummary("Expired [[SV:PROD|PROD]], concern was: " + concerns[pageName] + Twinkle.getPref('deletionSummaryAd'));
		page.suppressProtectWarning();
		page.deletePage(batchOperation.workerSuccess, batchOperation.workerFailure);
	});
},
callback_deleteTalk = function( apiobj ) {
	var $doc = $(apiobj.responseXML);
	var exists = $doc.find('page:not([missing])').length > 0;

	if( !exists ) {
		// no talk page; forget about it
		return;
	}

	var page = new Morebits.wiki.page('Talk:' + apiobj.params.page, "Deleting talk page of article " + apiobj.params.page);
	page.setEditSummary("[[SV:CSD#G8|G8]]: [[Help:Talk page|Talk page]] of deleted page \"" + apiobj.params.page + "\"" + Twinkle.getPref('deletionSummaryAd'));
	page.deletePage();
},
callback_deleteRedirects = function( apiobj ) {
	var $doc = $(apiobj.responseXML);
	$doc.find("redirects rd").each(function(){
		var title = $(this).attr('title');
		var page = new Morebits.wiki.page(title, "Deleting redirecting page " + title);
		page.setEditSummary("[[SV:CSD#G8|G8]]: Redirect to deleted page \"" + apiobj.params.page + "\"" + Twinkle.getPref('deletionSummaryAd'));
		page.deletePage();
	});
};

})(jQuery);


//</nowiki>