Jump to content

User:SD0001/RFUD-helper.js

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by SD0001 (talk | contribs) at 07:36, 28 August 2019 (SD0001 moved page User:SD0001/rfud-helper.js to User:SD0001/RFUD-helper.js). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
/**
 * ****** STILL UNDER DEVELOPMENT ******
 *
 * Script to easily respond to requests made at [[Wp:Requests for undeletion]]
 * (WP:RFUD). When accepting a request, the script would do the following:
 * - Post a response below the request
 * - Undelete the page
 * - Remove any deletion tags from the page
 * - Undelete the talk page if it existed
 * - If is a WT:AFC subpage, move it to draft namespace
 * - Offer to userfy the page instead of restoring to source
 *
 */

// <nowiki>

$.when(
	mw.loader.using([ 'mediawiki.util', 'mediawiki.api', 'mediawiki.Title', 'jquery.ui.dialog', 'jquery.tipsy' ]),
	mw.loader.getScript( 'https://en.wikipedia.org/w/index.php?title=MediaWiki:Gadget-morebits.js&action=raw&ctype=text/javascript' ),
	importStylesheet( 'MediaWiki:Gadget-morebits.css' ),
	$.ready
).then(function() {


if (mw.config.get('wgPageName') !== 'Wikipedia:Requests_for_undeletion') {
	return;
}


// Until the patch to morebits is accepted, see #643
Morebits.wiki.actionCompleted.event = function() {
	new Morebits.status( Morebits.wiki.actionCompleted.notice, Morebits.wiki.actionCompleted.postfix, 'info' );
	if( Morebits.wiki.actionCompleted.redirect ) {
		// if it isn't a URL, make it one. TODO: This breaks on the articles 'http://', 'ftp://', and similar ones.
		if( !( (/^\w+:\/\//).test( Morebits.wiki.actionCompleted.redirect ) ) ) {
			Morebits.wiki.actionCompleted.redirect = mw.util.getUrl( Morebits.wiki.actionCompleted.redirect );
			if( Morebits.wiki.actionCompleted.followRedirect === false ) {
				Morebits.wiki.actionCompleted.redirect += "?redirect=no";
			}
		}
		window.setTimeout( function() {
			window.location = Morebits.wiki.actionCompleted.redirect;
			// force reload if redirect location differs from current location only by the hash
			if (Morebits.wiki.actionCompleted.redirect.indexOf(mw.util.getUrl() + '#') === 0) {
				window.location.reload(true);
			}
		}, Morebits.wiki.actionCompleted.timeOut);
	}
};

var rfud = {};
window.rfud = rfud;

rfud.config = {
	advert: ' ([[User:SD0001/rfud-helper.js|rfud-helper]])',
	version: '1.0.0'
};

Morebits.wiki.api.setApiUserAgent('[[w:User:SD0001/rfud-helper.js|rfud-helper]]');

var pageName;

var params = {};

rfud.callback = function(e) {
	e.preventDefault();
	pageName = e.target.parentElement.firstChild.nextElementSibling.title.slice(17).replace(/_/g,' ');
	var buttonResponse = e.target.classList[1].slice('rfud-'.length);

	var Window = new Morebits.simpleWindow( 700, 500 );
	Window.setTitle( "Respond to undeletion request of " + pageName );
	Window.setScriptName( "RFUD helper" );
	Window.addFooterLink( "Administrator instructions", "Wikipedia:Requests for undeletion/Administrator instructions" );
	// Window.addFooterLink( "Script documentation", "WP:RFUDHELPER" );

	var form = new Morebits.quickForm( rfud.evaluate );

	if (pageName === 'Page name goes here') {
		form.append({
			type: 'div',
			label: Morebits.htmlNode('div', 'Caution: Accepting this will undelete "Page name goes here", please fix the template usage before proceeding.', 'red')
		});
	}

	var field = form.append({
		type: 'field',
		label: 'Response'
	});

	field.append({
		type: 'radio',
		name: 'response',
		list: [
			{
				label: 'Accept',
				value: 'accept',
				checked: buttonResponse === 'accept'
			},
			{
				label: 'Decline',
				value: 'decline',
				checked: buttonResponse === 'decline'
			}
		],
		event: rfud.toggleResponse
	});

	form.append( {
		type: 'field',
		label: 'Work area',
		name: 'work_area'
	} );

	var previewlink = document.createElement( 'a' );
	previewlink.addEventListener('click', function() {
		rfud.preview(result);  // `result` is defined below
	});

	previewlink.style.cursor = "pointer";
	previewlink.textContent = 'Preview';
	form.append( { type: 'div', id: 'rfudpreview', label: [ previewlink ] } );
	form.append( { type: 'div', id: 'rfud-previewbox', style: 'display: none' } );

	form.append( { type:'submit' } );

	var result = form.render();
	Window.setContent(result);
	Window.display();
	result.previewer = new Morebits.wiki.preview(document.getElementById('rfud-previewbox'));

	// Init the controls
	var evt = document.createEvent( "Event" );
	evt.initEvent( 'change', true, true );
	result.response[ buttonResponse === 'accept' ? 0 : 1 ].dispatchEvent( evt );

};

rfud.toggleResponse = function(e) {
	var form = e.target.form;
	var work_area;

	if (e.target.value === 'accept') {

		work_area = new Morebits.quickForm.element({
			type: 'field',
			label: 'Accept request',
			name: 'work_area'
		});

		work_area.append({
			type: 'input',
			label: 'Undeletion summary',
			name: 'logsummary',
			tooltip: 'Summary for the deletion log',
			size: '66px',
			value: 'Undelete per request at [[WP:RFUD]]'
		});

		work_area.append({
			type: 'checkbox',
			list: [ {
				label: 'Userfy this page',
				name: 'userfy',
				value: 'userfy',
				checked: false,
				subgroup: [ {
					type: 'input',
					label: 'Userfy to: ',
					name: 'page',
					size: '60px',
					tooltip: 'User page to move the page to which the page is to be moved',
					value: 'User:USERNAME/' + pageName.replace(/^Draft:/, '')
							.replace(/^Wikipedia talk:Articles for creation\//, '')
				} ],
				event: function(e) {
					if (e.target.checked) {
						var userfypagefield = form['userfy.page'];
						if (userfypagefield.value.includes('USERNAME')) {
							userfypagefield.setSelectionRange('User:'.length, 'User:USERNAME'.length);
							userfypagefield.focus();
						}
						if (form.movetodraft) {
							form.movetodraft.disabled = true;
						} else if (form.undeletetalk) {
							form.undeletetalk.disabled = true;
						}
					} else {
						if (form.movetodraft) {
							form.movetodraft.disabled = false;
						} else if (form.undeletetalk) {
							form.undeletetalk.disabled = false;
						}
					}
				}
			} ]
		});

		var title = new mw.Title(pageName);
		if (! title.isTalkPage()) {
			work_area.append({
				type: 'checkbox',
				list: [ {
					label: 'Undelete talk page if it existed',
					name: 'undeletetalk',
					value: 'undeletetalk',
					checked: true
				} ]
			});
		}

		if (pageName.startsWith('Wikipedia talk:Articles for creation/')) {
			work_area.append({
				type: 'checkbox',
				list: [ {
					label: 'Move to draft namespace',
					name: 'movetodraft',
					value: 'movetodraft',
					checked: true
				} ]
			});
		}

	} else if (e.target.value === 'decline') {

		work_area = new Morebits.quickForm.element({
			type: 'field',
			label: 'Decline request',
			name: 'work_area'
		});

	}

	var template_responses = work_area.append({
		type: 'select',
		label: 'Select a template response: ',
		name: 'template',
		event: rfud.responseTemplateChanged
	});

	$.each(rfud.template_responses[e.target.value], function(i, el) {
		template_responses.append({
			type: 'option',
			value: i,
			label: (i ? (i + ': ') : '') + el,
			selected: /^(Done|Not done)$/.test(el)
		});
	});

	work_area.append({
		type: 'textarea',
		label: 'Comments',
		tooltip: 'Any comments in addition to the template response',
		name: 'comments'
	});


	var old_area = $("[name=work_area]")[0];
	var result = work_area.render();
	old_area.replaceWith( result );


};

rfud.template_responses = {
	accept: {
		'' : "No template response",
		'{{UND|done}}' : "Done",
		'{{UND|prod}}' : "contested proposed deletion",
		'{{UND|g13}}' : "draft deleted under G13",
		'{{UND|afc}}' : "for G13s where {{AFC submission}} was used and the draft was submitted and declined",
		'{{UND|afc-ns}}' : "for G13s where {{AFC submission}} was used and where the draft was never submitted",
		'{{UND|g13-draft}}' : "for G13s of draft namespace pages never part of the AfC process"

	},
	decline: {
		'' : "No template response",
		'{{UND|notdone}}' : "Not done",
		'{{UND|notdone2}}' : "Not done and will not be done",
		'{{UND|doesnotexist}}' : "No deleted page with this name",
		'{{UND|notdonecompany}}' : "Company article failing NCORP",
		'{{UND|notdoneperson}}' : "Biographical article failing NBIO",
		'{{UND|g11}}' : "Blatant advertisement",
		'{{UND|discussion}}' : "Article deleted at a discussion", // has subgroup
		'{{UND|csd}}' : "Article deleted per CSD criteria", // has subgroup
		'{{UND|copyvio}}' : "Copyright violation" // has subgroup

	}
};

rfud.responseTemplateChanged = function(e) {
	var template = e.target.value;
	var newInput;
	if (template === '{{UND|discussion}}') {
		newInput = new Morebits.quickForm.element({
			type: 'input',
			label: 'Discussion: ',
			name: 'discussion',
			size: '70px',
			className: 'UNDtemplateinput'
		});
		newInput.append({
			type: 'input',
			label: 'Closing admin: ',
			name: 'closingadmin',
			className: 'UNDtemplateinput'
		});
	} else if (template === '{{UND|csd}}') {
		newInput = new Morebits.quickForm.element({
			type: 'input',
			label: 'Deleting admin: ',
			name: 'deletingadmin',
			className: 'UNDtemplateinput'
		});
	} else if (template === '{{UND|copyvio}}') {
		newInput = new Morebits.quickForm.element({
			type: 'input',
			label: 'Copyvio source: ',
			name: 'copyviosource',
			size: '70px',
			className: 'UNDtemplateinput'
		});
	}
	$('.UNDtemplateinput').remove();
	if (newInput) {
		$(e.target.form).find('h5').before(newInput.render());
	}
};

rfud.getResponseWikitext = function(forPreview) {
	var templatetext = params.template.replace(/^\{\{/, '{{subst:');
	switch (params.template) {
		case '{{UND|discussion}}':
			templatetext = templatetext.replace('}}', '|' + params.discussion + '|' + params.closingadmin + '}}');
			break;
		case '{{UND|csd}}':
			templatetext = templatetext.replace('}}', '|' + params.deletingadmin + '}}');
			break;
		case '{{UND|copyvio}}':
			templatetext = templatetext.replace('}}', '|' + params.copyviosource + '}}');
			break;
	}
	if (forPreview) {
		var text = (templatetext ? (templatetext + (params.comments ? '\n\n' : '' )) : '') + params.comments + ' ~~~~';
	} else {
		var text = '\n:' + (templatetext ? (templatetext + (params.comments ? '\n\n:' : '' )) : '') + params.comments + ' ~~~~';
	}
	return text;
};

rfud.preview = function(result) {
	params = {};
	$(result).find('input, select, textarea').each(function(i, e) {
		params[e.name] = (e.type === 'checkbox' ? e.checked : e.value);
	}); // params is not set fully correctly, but this is ok as the incorrectly set fields are not required in preview
	result.previewer.beginRender(rfud.getResponseWikitext(true), "API"); // Force wikitext
};

rfud.evaluate = function(e) {

	var form = e.target;

	params = {};
	params.response = form.response.value; // radio input
	$(form).find('input, select, textarea').each(function(i, e) {
		if (e.type === 'radio') return true;
		if (e.disabled) return true;
		params[e.name] = (e.type === 'checkbox' ? e.checked : e.value);
	});

	if (!params.template && !params.comments) {
		alert('Please select a template response or add a comment');
		return;
	}

	if (params['userfy.page'] && params['userfy.page'].includes('USERNAME')) {
		alert('Please replace "USERNAME" with a valid username');
		return;
	}

	Morebits.simpleWindow.setButtonsEnabled( false );
	Morebits.status.init( form );

	Morebits.wiki.actionCompleted.redirect = 'Wikipedia:Requests for undeletion#' + pageName;
	Morebits.wiki.actionCompleted.timeOut = 1000;

	if (params.response === 'accept') {
		Morebits.wiki.actionCompleted.notice = "Undeletion";
		var p = new Morebits.wiki.page(pageName);
		p.setEditSummary(params.logsummary + rfud.config.advert);
		p.undeletePage(rfud.doExtras);
	} else {
		var rfudpage = new Morebits.wiki.page('Wikipedia:Requests for undeletion');
		rfudpage.load(rfud.addResponse);
	}

};

rfud.doExtras = function(e) {

	var pageobj = e.parent;

	// UNDELETE TALK PAGE
	if (params.undeletetalk) {
		// code here is copied off [[Mediawiki:Gadget-Twinklebatchdelete.js]], written by [[User:Amorymeltzer]]
		var talkpagename = new mw.Title(pageName).getTalkPage().getPrefixedText();
		var query = {
			'action': 'query',
			'prop': 'deletedrevisions',
			'drvprop': 'ids',
			'drvlimit': 1,
			'titles': talkpagename
		};
		new Morebits.wiki.api( 'Checking talk page for deleted revisions', query, function talk_undel( apiobj ) {
			var xml = apiobj.responseXML;
			var exists = $(xml).find('page:not([missing])').length > 0;
			var delrevs = $(xml).find('rev').attr('revid');

			if( exists || !delrevs ) {
				// page exists or has no deleted revisions; forget about it
				return;
			}

			var talkpage = new Morebits.wiki.page(apiobj.query.titles, "Undeleting talk page of " + pageName);
			talkpage.setEditSummary('Undeleting [[Help:Talk page|talk page]] of "' + pageName + '"' + rfud.config.advert);
			talkpage.undeletePage();
		} ).post();
	}


	// USERFY
	if (params.userfy) {
		Morebits.status.info(pageName, 'Userfying to ' + params['userfy.page']);
		params.newPageName = params['userfy.page'];
		pageobj.setMoveDestination(params.newPageName);
		pageobj.setEditSummary('Userfying' + rfud.config.advert);
		pageobj.move(rfud.removeDeletionTags);
	}


	// MOVE WT:AFC PAGES TO DRAFT: SPACE
	if (params.movetodraft) {
		Morebits.status.info(pageName, 'Moving page to draft namespace');
		params.newPageName = pageName.replace('Wikipedia talk:Articles for creation/', 'Draft:');
		pageobj.setMoveDestination(params.newPageName);
		pageobj.setEditSummary('Moving to new location for drafts' + rfud.config.advert);
		pageobj.move(rfud.removeDeletionTags);
	}


	// REMOVE DELETION TAGS
	if (!params.userfy && !params.movetodraft) {
		rfud.removeDeletionTags();
	}


	// ADD RESPONSE AT WP:RFUD
	var rfudpage = new Morebits.wiki.page('Wikipedia:Requests for undeletion');
	rfudpage.load(rfud.addResponse);

};

rfud.removeDeletionTags = function() {
	var pageobj = new Morebits.wiki.page(params.newPageName ? params.newPageName : pageName,
		'Removing deletion tags from page if any');

	pageobj.load(function(pageobj) {
		var pageText = pageobj.getPageText();

		var newPageText = pageText.replace(
			// Regex adapted from [[Mediawiki:Gadget-friendlytag.js]]
			new RegExp(
				// leading whitespace
				'^\\s*' +
				// capture template(s)
				'(?:((?:\\s*' +
				// AfD
				'(?:<!--.*AfD.*\\n\\{\\{(?:Article for deletion\\/dated|AfDM).*\\}\\}\\n<!--.*(?:\\n<!--.*)?AfD.*(?:\\s*\\n))?|' + // trailing whitespace/newline needed since this subst's a newline
				// CFD
				'<!-- BEGIN CFD TEMPLATE -->[\\s\\S]*?<!-- END CFD TEMPLATE -->|' +
				// begin template format
				'\\{\\{\\s*(?:' +
				// CSD
				'db|delete|db-.*?|speedy deletion-.*?|' +
				// PROD
				'(proposed deletion|prod blp|book-prod)\\/dated(?:\\s+\\|(?:concern|user|timestamp|help).*)+|' +
				// sometimes under a CSD or AfD
				'|salt|proposed deletion endorsed' +
				// MFD/FFD
				'|mfd|ffd' +
				// end main template name
				')\\s*' +
				// template parameters
				'(\\|(?:\\{\\{[^{}]*\\}\\}|[^{}])*)?' +
				// end template format
				'\\}\\})+' +
				// end capture
				'(?:\\s*\\n)?)' +
				// trailing whitespace
				'\\s*)?',
			'i'), ''
		);

		var changed = false;

		// RFD
		if (/#invoke:RfD/.test(newPageText)) {
			newPageText = newPageText.replace(/\{\{.*?#invoke:RfD[\s\S]*?\|content=\n([\s\S]*?)<!-- Don.*?-->\n?\}\}/, '$1');
			changed = true;
		}

		// TFD
		else if (/Template for discussion\/dated/.test(newPageText)) {
			newPageText = newPageText.replace(/\{\{Template for discussion\/dated.*?(\{\{#invoke:Noinclude.*?\}\})?\}\}/, '');
			changed = true;
		}

		if (changed || newPageText !== pageText) {
			pageobj.setPageText(newPageText);
			pageobj.setEditSummary('Removing deletion tags from undeleted page' + rfud.config.advert);
			pageobj.save();
		}

	});
};

rfud.addResponse = function rfudAddResponse() {

	var sectionName = pageName;
	var sectionNumber;
	$('.toctext').each(function(i,e) {
		if ( Morebits.string.toUpperCaseFirstChar(e.textContent) === sectionName ) {
			sectionNumber = e.previousElementSibling.textContent;
			return false; // break
		}
	});

	var editsummary = '/* ' + sectionName + ' */ ' + Morebits.string.toUpperCaseFirstChar(params.response) + 'ing request' + rfud.config.advert;

	new Morebits.wiki.api('Adding response to request', {
		action: 'edit',
		section: sectionNumber,
		appendtext: rfud.getResponseWikitext(),
		title: 'Wikipedia:Requests for undeletion',
		summary: editsummary,
		token: mw.user.tokens.get('editToken')
	}).post();

};

// Add Accept/Decline button
$('h2').next().find('li .sysop-show a').each(function(i,e) {

	var rfudhelperlink_accept = Morebits.htmlNode('a', 'Accept');
	rfudhelperlink_accept.href = '#';
	rfudhelperlink_accept.className = 'rfud-helper-button rfud-accept';

	var rfudhelperlink_decline = Morebits.htmlNode('a', 'Decline');
	rfudhelperlink_decline.href = '#';
	rfudhelperlink_decline.className = 'rfud-helper-button rfud-decline';

	e.after(document.createTextNode(' | '), rfudhelperlink_accept,
		document.createTextNode(' | '), rfudhelperlink_decline);
});

// Attach click event handler
$('.rfud-helper-button').click(rfud.callback);


});
// </nowiki>