From Wikipedia, the free encyclopedia
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.

/**

 *

 * 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

 * - Offer to userfy the page instead of restoring to source

 * - Offer to draftify the page instead of restoring to source

 * - Adds {{Old AfD}} to talk page if undoing an AfD soft deletion

 * - If is a WT:AFC subpage, move it to draft namespace

 *

 * In addition, a preview of the deleted page's last version is shown below

 * Special:Undelete, and when you follow the red link.

 */



// <nowiki>



/* jshint maxerr: 999 */

/* globals Morebits */



(function() {



if ((!mw.config.get('wgCurRevisionId') && $('.mw-undelete-subtitle').length) ||

	(mw.config.get('wgCanonicalSpecialPageName') === 'Undelete' && $('.mw-undelete-revlist').length)

) {

	mw.loader.using('mediawiki.api').then(showDeletedPagePreview);

	return;

}



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

	return;

}



$.when(

	mw.loader.using([ 'mediawiki.util', 'mediawiki.api', 'mediawiki.Title', 'mediawiki.Uri', 'ext.gadget.morebits' ]),

	$.ready

).then(function() {



var rfud = {};

window.rfud = rfud;



rfud.advert = ' ([[User:SD0001/RFUD-helper|rfud-helper]])';

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



var pageName;



var params = {};

rfud.params = params;



rfud.callback = function(e) {

	e.preventDefault();

	pageName = e.target.parentElement.childNodes1].title.slice(17).replace(/_/g, ' ');



	var $template_element = $(e.target).parent().parent().parent();

	var $header_div = $template_element.prev();

	while (!$header_div.hasClass('mw-heading')) {

		$header_div = $header_div.prev();

		if ($header_div.length === 0) { // Avoid an infinite loop, fail gracefully

			mw.notify("Failed to identify section heading", {title: 'RFUD-helper', type: 'error'});

			return;

		}

	}

	rfud.$header_container = $header_div;

	var $header_element = $header_div.find('h2');

	var $heading_element = $header_element.children(".mw-headline").length ? 

		$header_element.children(".mw-headline") : 

		// Following [[mw:Heading_HTML_changes]], and in Parsoid

		$header_element;

	rfud.sectionName = $heading_element0].id.replace(/_/g, ' ');

	

	// Detect requesting user

	var sig_span = $header_div.nextUntil('.mw-heading').find('.ext-discussiontools-init-replylink-buttons').get(0);

	var mw_thread_id = $(sig_span).data('mw-thread-id');

	if (mw_thread_id) {

		var userMatch = /c-(.+?)-20/g.exec(mw_thread_id);

		if (userMatch) {

			rfud.requestingUser = userMatch1].replace(/_/g, ' ');

		} else {

			rfud.requestingUser = null;

		}

	} else {

		rfud.requestingUser = null;

	}

	

	var buttonResponse = e.target.classList1].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')

		});

	}

	// pageName will never have underscores as it part of the mediawiki-generated link title

	// rfud.sectionName could have underscores if user entered them, hence normalize while comparing

	else if (pageName !== rfud.sectionName.replace(/_/g, ' ')) {

		form.append({

			type: 'div',

			label: Morebits.htmlNode('div', 'Note: page name used in template is different from the section name', '#d7280e')

		});

	}



	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).find('textarea').css('font-size', '130%');



	result.previewer = new Morebits.wiki.preview(document.getElementById('rfud-previewbox'));



	// Init the controls

	var evt = document.createEvent("Event");

	evt.initEvent('change', true, true);

	result.responsebuttonResponse === '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'

		});



		var permanent_section_link = 'Special:Permalink/' + mw.config.get('wgRevisionId') + '#' + rfud.sectionName;

		work_area.append({

			type: 'input',

			label: 'Undeletion summary',

			name: 'logsummary',

			tooltip: 'Summary for the deletion log',

			size: '66px',

			value: 'Undelete per [[' + permanent_section_link + '|request]] at [[WP:RFUD]]'

		});

		

		var titleObj = mw.Title.newFromText(pageName);



		if (titleObj && titleObj.namespace !== 2 && titleObj.namespace !== 6) {

			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 which the page is to be moved',

						value: 'User:' + (rfud.requestingUser || 'USERNAME') + '/' + pageName.replace(/^Draft:/, '')

								.replace(/^Wikipedia talk:Articles for creation\//, '')

					}, {

						type: 'checkbox',

						list:  {

							label: 'Suppress redirect',

							name: 'sredr',

							checked: true

						} 

					} ],

					event: function(e) {

						if (e.target.checked) {

							var userfypagefield = form'userfy.page'];

							if (userfypagefield.value.indexOf('USERNAME') !== -1) {

								userfypagefield.setSelectionRange('User:'.length, 'User:USERNAME'.length);

								userfypagefield.focus();

							}

	

							if (form.movetodraft) {

								form.movetodraft.checked = false;

								form.movetodraft.disabled = true;

							}

							if (form.draftify && form.draftify.checked) {

								form.draftify.click(); // need to trigger the event listener as well

							}

							if (form.undeletetalk) {

								form.undeletetalk.checked = false;

								form.undeletetalk.disabled = true;

							}

							form.template.value = '{{UND|userfy}}';

						} else {

							$('.UNDtemplateinput').parent().remove(); // remove deleting admin prompt from {{UND|userA7}}

							if (form.movetodraft) {

								form.movetodraft.disabled = false;

							}

							if (form.undeletetalk) {

								form.undeletetalk.disabled = false;

							}

							form.template.value = '{{UND|done}}';

						}

					}

				} 

			});	

		}

		

		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 (titleObj && titleObj.namespace !== 118 && titleObj.namespace !== 6) {

			work_area.append({

				type: 'checkbox',

				list:  {

					label: 'Draftify this page',

					name: 'draftify',

					value: 'draftify',

					checked: false, 

					subgroup:  {

						type: 'input',

						label: 'To: ',

						name: 'page',

						size: '60px',

						tooltip: 'Draft page to which the page is to be moved',

						value: 'Draft:' + pageName

					}, {

						type: 'checkbox',

						list:  {

							label: 'Suppress redirect',

							name: 'draftifysredr',

							checked: true

						} 

					} ],

					event: function (e) {

						if (e.target.checked) {

							if (form.userfy && form.userfy.checked) {

								form.userfy.click(); // need to trigger the event listener as well

							}

							if (form.undeletetalk) { // TODO: undelete and move the talk page too

								form.undeletetalk.checked = false;

								form.undeletetalk.disabled = true;

							}

							form.template.value = '{{UND|draftify}}';

						} else {

							form.template.value = '{{UND|done}}';

							if (form.undeletetalk) {

								form.undeletetalk.disabled = false;

							}

						}

					}

				} 

			});	

		} 

		

		if (titleObj && !titleObj.isTalkPage()) {

			work_area.append({

				type: 'checkbox',

				list:  {

					label: 'Undelete talk page if it existed',

					name: 'undeletetalk',

					value: 'undeletetalk',

					checked: true

				} 

			});

		}



		if (titleObj.namespace === 6) {

			work_area.append({

				type: 'checkbox',

				list:  {

					label: 'Add {{di-orphaned fair use}}',

					name: 'addF5',

					value: 'addF5',

					checked: false,

					tooltip: 'While restoring files deleted under CSD F5, tick this option unless the file has already been de-orphaned or you plan to do it after restoring it',

					event: function(e) {

						if (e.target.checked) {

							form.template.value = '{{UND|f5deferred}}';

						} else {

							form.template.value = '{{UND|done}}';

						}

					}

				} 

			});

		}



	} 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_responsese.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'

	});

	

	work_area.append({

		type: 'checkbox',

		list:  {

			label: 'Ping requesting user',

			name: 'pinguser',

			value: 'pinguser',

			checked: true,

			subgroup: rfud.requestingUser ? [] :  {

				type: 'input',

				label: 'User: ',

				name: 'pingusername',

				size: '50px',

				tooltip: 'Name of requesting user could not be auto-detected, you can fill this in manually'

			} 

		} 

	});





	var old_area = form.work_area;

	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|soft}}': "contested soft 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",

		'{{UND|f5deferred}}': "for files being restored and tagged as {{di-orphaned fair use}}",

		'{{UND|userfy}}': "Userfied",

		'{{UND|userA7}}': "Userfied A7 article, contact admin before moving back", // has subgroup

		'{{UND|draftify}}': "Draftified",



	},

	decline: {

		'': "No template response",

		'{{UND|notdone}}': "Not done",

		'{{UND|notdone2}}': "Not done and will not be done",

		'{{UND|2nd}}': "Was undeleted once, not worked on (soft-decline)",

		'{{UND|doesnotexist}}': "No deleted page with this name",

		'{{UND|notdonecompany}}': "Company article failing NCORP",

		'{{UND|notdoneperson}}': "Biographical article failing NBIO",

		'{{UND|inappropriate}}': "Inappropriate topic for Wikipedia",

		'{{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;

	$('.UNDtemplateinput').parent().remove();



	var newInput;

	if (template === '{{UND|discussion}}') {

		var newInput1 = new Morebits.quickForm.element({

			type: 'input',

			label: 'Discussion: ',

			name: 'discussion',

			size: '70px',

			className: 'UNDtemplateinput',

			value: 'Autofilling...'

		});

		var newInput2 = new Morebits.quickForm.element({

			type: 'input',

			label: 'Closing admin: ',

			name: 'closingadmin',

			className: 'UNDtemplateinput',

			value: 'Autofilling...'

		});

		$(e.target.form).find('h5').before(newInput1.render(), newInput2.render());

	} else if (template === '{{UND|csd}}' || template === '{{UND|userA7}}') {

		newInput = new Morebits.quickForm.element({

			type: 'input',

			label: 'Deleting admin: ',

			name: 'deletingadmin',

			className: 'UNDtemplateinput',

			value: 'Autofilling...'

		});

		$(e.target.form).find('h5').before(newInput.render());

	} else if (template === '{{UND|copyvio}}') {

		newInput = new Morebits.quickForm.element({

			type: 'input',

			label: 'Copyvio source: ',

			name: 'copyviosource',

			size: '70px',

			className: 'UNDtemplateinput'

		});

		$(e.target.form).find('h5').before(newInput.render());

	}



	if (template === '{{UND|userfy}}' || template === '{{UND|userA7}}') {

		if (e.target.form.userfy.checked === false) {

			e.target.form.userfy.click();

			e.target.value = template; // the click above will reset select value to {{UND|userfy}}

		}

	}

	

	if (template === '{{UND|draftify}}') {

		if (e.target.form.draftify.checked === false) {

			e.target.form.draftify.click();

		}

	}



	if (template === '{{UND|csd}}' || template === '{{UND|userA7}}') {

		// Auto-fill the name of deleting admin by parsing the deletion log

		var admininputbox = $('input.UNDtemplateinput[name=deletingadmin]')[0];

		rfud.getDeletionLog().done(function(html) {

			var userlink = $(html).find('.mw-logline-delete .mw-userlink')[0];

			if (userlink) {

				admininputbox.value = userlink.textContent;

			} else {

				admininputbox.value = '';

			}

		})

		.fail(function() {

			admininputbox.value = '';

		});

	} else if (template === '{{UND|discussion}}') {

		// Auto-fill parameters by parsing the deletion log

		var xfdinputbox = $('input.UNDtemplateinput[name=discussion]')[0];

		var closingadmininputbox = $('input.UNDtemplateinput[name=closingadmin]')[0];

		rfud.getDeletionLog().done(function(html) {

			var xfd, closingadmin;

			$(html).find('.mw-logline-delete .comment a').each(function() {

				if (/^Wikipedia:(?:Articles|Redirects|Templates|Categories|Files|Miscellany) for (?:deletion|discussion)/.test(this.title)) {

					xfd = this.title;

					closingadmin = $(this).parent().parent().find('.mw-userlink')[0].textContent;

					return false; // break

				}

			});

			xfdinputbox.value = xfd || '';

			closingadmininputbox.value = closingadmin || '';

		})

		.fail(function() {

			xfdinputbox.value = '';

			closingadmininputbox.value = '';

		});

	}

};



rfud.getResponseWikitext = function(forPreview) {

	var templatetext = params.template.replace(/^\{\{/, '{{subst:');

	var parameterText = '';

	switch (params.template) {

		case '{{UND|discussion}}':

			parameterText = '|' + params.discussion + '|' + params.closingadmin;

			break;

		case '{{UND|csd}}':

			parameterText = '|3=' + params.deletingadmin;

			break;

		case '{{UND|copyvio}}':

			parameterText = '|' + params.copyviosource;

			break;

		case '{{UND|userfy}}':

			parameterText = '|' + params'userfy.page'];

			break;

		case '{{UND|userA7}}':

			parameterText = '|' + params'userfy.page' + '|' + params.deletingadmin;

			break;

		case '{{UND|draftify}}':

			parameterText = '|' + params'draftify.page'];

			break;

	}

	templatetext = templatetext.replace('}}', parameterText + '}}');



	var separator = '';

	if (params.comments) {

		// these templates don't have any text (other than bolded stuff)

		if (params.template === '{{UND|done}}' ||

			params.template === '{{UND|notdone}}' ||

			params.template === '{{UND|notdone2}}') {

			separator = ' ';

		} else {

			separator = '\n\n';

			if (!forPreview) {

				separator += ':';

			}

		}

	}



	var userToPing = params'pinguser.pingusername' || rfud.requestingUser;

	var pingText = (userToPing && !mw.util.isIPAddress(userToPing)) ? ('{{re|' + userToPing + '}} ') : '';

	

	var text = (forPreview ? '' : '\n:') + (params.pinguser ? pingText : '') + (templatetext ? templatetext + separator : '') + params.comments + ' ~~~~';

	return text;

};



rfud.preview = function(result) {

	params = {};

	$(result).find('input, select, textarea').each(function(_, e) {

		paramse.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), "Wikipedia:Requests for undeletion");

};



rfud.evaluate = function(e) {



	var form = e.target;



	params = {};

	params.response = form.response.value; // radio input

	$(form).find('input, select, textarea').each(function(_, e) {

		if (e.type === 'radio') { return true; }

		if (e.disabled) { return true; }

		paramse.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'].indexOf('USERNAME') !== -1) {

		alert('Please replace "USERNAME" with a valid username');

		return;

	}



	// disable submit of this form only, leaving any other open morebits forms untouched

	$(form).parent().parent().find('.morebits-dialog-buttons button').prop('disabled', true);

	Morebits.status.init(form);



	// Never getting called for some reason, window doesn't autoclose

	// TODO: remove this, autoclose isn't really desirable

	Morebits.wiki.actionCompleted.event = function() {

		// removed

	};



	if (params.response === 'accept') {

		var p = new Morebits.wiki.page(pageName, 'Undeleting ' + pageName);

		p.setEditSummary(params.logsummary + rfud.advert);

		p.undeletePage(function onUndeleteSuccess(e) {

			e.getStatusElement().info('Done');

			rfud.doExtras(e.parent); // e = apiobj, e.parent = pagobj

		}, function onUndeleteFailure(e) {

			// XXX: show this error only when the api tells so, will need morebits pull merged first

			e.getStatusElement().warn("Page already exists or was already undeleted");

			rfud.doExtras(e); // e = pageobj

		});

	} else {

		rfud.addResponse();

	}



};



rfud.doExtras = function(pageobj) {



	// UNDELETE TALK PAGE

	if (params.undeletetalk) {

		// code adapted from [[Mediawiki:Gadget-Twinklebatchdelete.js]]

		var talkpagename = new mw.Title(pageName).getTalkPage().toText();

		var statelem = new Morebits.status('Talk page');

		var query = {

			'action': 'query',

			'prop': 'deletedrevisions',

			'drvprop': 'ids',

			'drvlimit': 1,

			'titles': talkpagename

		};

		new Morebits.wiki.api('Checking for deleted revisions', query, function talk_page(apiobj) {

			var xml = apiobj.responseXML;

			var exists = $(xml).find('page:not([missing])').length > 0;

			var delrevs = $(xml).find('rev').attr('revid');



			if (!delrevs) {

				statelem.info('No deleted revisions found');

				rfud.addOldAfd();   // XXX: this is pathetic, find some better way of organising code

				return;

			}

			if (exists) {

				statelem.update('Already exists');

				rfud.addOldAfd();

				return;

			}



			statelem.unlink();

			var talkpage = new Morebits.wiki.page(apiobj.query.titles, "Talk page");

			talkpage.setEditSummary('Undeleting [[Help:Talk page|talk page]] of "' + pageName + '"' + rfud.advert);

			talkpage.undeletePage(function onUndeleteTalkSuccess() {

				talkpage.getStatusElement().info('Undeleted');

				rfud.addOldAfd();

			});

		}, statelem).post();

	}





	// USERFY

	if (params.userfy) {

		pageobj = new Morebits.wiki.page(pageName, 'Userfying to ' + params'userfy.page']);

		pageobj.setMoveDestination(params'userfy.page']);

		pageobj.setMoveSuppressRedirect(params.sredr);

		pageobj.setEditSummary('Userfying' + rfud.advert);

		pageobj.move(function onUserfySuccess() {

			pageobj.getStatusElement().info('Done');

			rfud.removeDeletionTags(params'userfy.page']);

		}, function onUserfyFailure(e) {

			var statelem = pageobj.getStatusElement();

			if (e.errorCode === 'articleexists') {

				Morebits.wiki.numberOfActionsLeft++; // hold dialog from closing //



				var skip_button = Morebits.htmlNode('button', 'Skip move');

				skip_button.addEventListener('click', function() {

					Morebits.wiki.numberOfActionsLeft--; // allow dialog to close //

					statelem.warn('skipped following name conflict');

				});



				var newUserfy = $('<input>').attr('type', 'text')[0];

				var new_button = $('<button>').text('OK').click(function() {

					Morebits.wiki.numberOfActionsLeft--;

					var newTitle = newUserfy.value;

					pageobj.setMoveDestination(newTitle);

					pageobj.setMoveSuppressRedirect(params.sredr);

					pageobj.move(function() {

						statelem.info(['userfied to ' + newTitle + ' instead. ',

							Morebits.htmlNode('span', 'Please update your response to reflect the new page name', 'red')]);

						rfud.removeDeletionTags(newTitle);

					});

				});

				statelem.warn([ 'A user page of that name already exists, enter new user page name or skip ',

					newUserfy, new_button0], skip_button ]);

			}

		});

	}





	// MOVE WT:AFC PAGES TO DRAFT: SPACE

	if (params.movetodraft) {

		pageobj = new Morebits.wiki.page(pageName, 'Moving page to draft namespace');

		pageobj.setMoveDestination(pageName.replace('Wikipedia talk:Articles for creation/', 'Draft:'));

		pageobj.setEditSummary('Moving to new location for drafts' + rfud.advert);

		pageobj.move(function onAfcMoveSuccess() {

			pageobj.getStatusElement().info('Done');

			rfud.removeDeletionTags(pageName.replace('Wikipedia talk:Articles for creation/', 'Draft:'));

		}, function onAfcMoveFailure(e) {

			if (e.errorCode === 'articleexists') {

				pageobj.getStatusElement().warn('A draft page of that name already exists, skipping...');

				Morebits.wiki.numberOfActionsLeft++; // prevent dialog from closing //

				rfud.removeDeletionTags(pageName);

			}

		});

	}

	

	

	// DRAFTIFY

	if (params.draftify) {

		pageobj = new Morebits.wiki.page(pageName, 'Draftifying to ' + params'draftify.page']);

		pageobj.setMoveDestination(params'draftify.page']);

		pageobj.setMoveSuppressRedirect(params.draftifysredr);

		pageobj.setEditSummary('Draftifying following undeletion' + rfud.advert);

		pageobj.move(function onDraftifySuccess(e) {

			pageobj.getStatusElement().info('Done');

			rfud.removeDeletionTags(params'draftify.page']);

		}, function onDraftifyFailure(e) {

			var statelem = pageobj.getStatusElement();

			if (e.errorCode === 'articleexists') {

				Morebits.wiki.numberOfActionsLeft++; // hold dialog from closing //



				var skip_button = Morebits.htmlNode('button', 'Skip move');

				skip_button.addEventListener('click', function() {

					Morebits.wiki.numberOfActionsLeft--; // allow dialog to close //

					statelem.warn('skipped following name conflict');

				});



				var newDraftify = $('<input>').attr('type', 'text')[0];

				var new_button = $('<button>').text('OK').click(function() {

					Morebits.wiki.numberOfActionsLeft--;

					var newTitle = newDraftify.value;

					pageobj.setMoveDestination(newTitle);

					pageobj.setMoveSuppressRedirect(params.draftifysredr);

					pageobj.move(function() {

						statelem.info(['moved to ' + newTitle + ' instead. ',

							Morebits.htmlNode('span', 'Please update your response to reflect the new page name', 'red')]);

						rfud.removeDeletionTags(newTitle);

					});

				});

				statelem.warn([ 'A draft of that name already exists, enter new draft page name or skip ',

					newDraftify, new_button0], skip_button ]);

			}

		});

	}





	// REMOVE DELETION TAGS

	if (!params.userfy && !params.movetodraft && !params.draftify) {

		rfud.removeDeletionTags(pageName);

	}





	// ADD RESPONSE AT WP:RFUD

	rfud.addResponse();



	// ADD OLD XFD TO TALK PAGE IF PREVIOUSLY DELETED AT AFD

	if (!params.undeletetalk) {

		rfud.addOldAfd();

	}



};



// Called after rfud.removeDeletionTags

rfud.addF5tag = function() {

	if (!params.addF5) {

		return;

	}

	var pageobj = new Morebits.wiki.page(pageName, 'Adding {{di-orphaned fair use}}');

	pageobj.setPrependText('{{subst:di-orphaned fair use}}\n');

	pageobj.setEditSummary('Adding {{di-orpaned fair use}}' + rfud.advert);

	pageobj.setCreateOption('nocreate');

	pageobj.prepend();

};



rfud.getDeletionLog = function getDeletionLog() {

	// TODO: convert to use API

	return $.ajax(mw.util.getUrl('Special:Log', { type: 'delete', subtype: 'delete', page: pageName }));

};



rfud.addOldAfd = function addOldAfd() {

	rfud.getDeletionLog().then(function(html) {

		var afdLink = $(html).find('#mw-content-text ul .mw-logline-delete .comment a[href^="/wiki/Wikipedia:Articles_for_deletion"]')[0];

		if (!afdLink) {

			return;

		}



		var afdPage = afdLink.title;

		var startStatus = new Morebits.status('Adding {{Old AfD}} to talk page', 'Getting data', 'status');



		var resultPromise = new mw.Api().parse(new mw.Title(afdPage));

		var datePromise = new mw.Api().get({

			action: 'query',

			prop: 'revisions',

			titles: afdPage,

			rvprop: 'timestamp',

			rvlimit: '1',

			rvdir: 'newer'

		});



		$.when(datePromise, resultPromise).then(function(json, parsedPage) {

			var tagtext = '{{Old AfD|page=' + afdPage;

			if (json && json0 && json0].query && json0].query.pages) {

				var timestamp = Object.values(json0].query.pages)[0].revisions0].timestamp;

				var d = new Morebits.date(timestamp);

				var date = d.getUTCDate() + ' ' + d.getUTCMonthName() + ' ' + d.getUTCFullYear();

				tagtext += '|date=' + date;

			}

			if (parsedPage) {

				var boldedResult = $(parsedPage).find('b')[1].textContent;

				tagtext += "|result='''" + boldedResult + "'''";

			}

			tagtext += '}}\n';



			startStatus.unlink();

			var talkpage = new mw.Title(pageName).getTalkPage().toText();

			var pageobj = new Morebits.wiki.page(talkpage, 'Adding {{Old AfD}} to talk page');

			pageobj.setPrependText(tagtext);

			pageobj.setEditSummary('Adding {{Old AfD}} after undeletion' + rfud.advert);

			pageobj.prepend();



		});

	});

};



rfud.removeDeletionTags = function removeDeletionTags(currentPageName) {

	var pageobj = new Morebits.wiki.page(currentPageName, 'Removing deletion tags from page if any');



	pageobj.load(function(pageobj) {

		var pageText = pageobj.getPageText();

		var statelem = pageobj.getStatusElement();



		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-.*?|di-.*?|' +

					// 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 after undeletion' + rfud.advert);

			pageobj.save(function() {

				rfud.addF5tag();

			});

		} else {

			statelem.info('None found');

			rfud.addF5tag();

			rfud.makeDummyEdit(currentPageName);

		}



	});

};



rfud.makeDummyEdit = function(currentPageName) {

	if (mw.Title.newFromText(currentPageName).namespace === 118 ||

		(['{{UND|g13}}', '{{UND|afc}}', '{{UND|afc-ns}}'].indexOf(params.template) !== -1)

	) {

		var pageobj = new Morebits.wiki.page(currentPageName, 'Making dummy edit to reset G13 clock');

		pageobj.load(function(pageobj) {

			var currenttext = pageobj.getPageText();

			var newtext = currenttext.replace('\n', ' \n');

			if (newtext.replace(/\s*$/, '') === currenttext) { // XXX: Morebits doesn't offer a way to detect success "nochange" response returned by the API

				pageobj.getStatusElement().warn('Failed to save dummy edit. Please edit the page manually to reset the G13 clock');

				return;

			}

			pageobj.setPageText(newtext);

			pageobj.setEditSummary('Dummy edit to reset G13 clock after undeletion' + rfud.advert);

			pageobj.save();

		});

	}

};



rfud.addResponse = function rfudAddResponse() {



	var sectionNumber;

	try {

		var uri = new mw.Uri(rfud.$header_container.find('.mw-editsection a').attr('href'));

		sectionNumber = parseInt(uri.query.section);

	} catch (e) {}

	

	if (!sectionNumber || isNaN(sectionNumber)) {

		new Morebits.status('Saving response').warn('Unable to find section.');

		Morebits.status.printUserText(rfud.getResponseWikitext(true), "Your response is provided below, which you may save manually:");

		Morebits.wiki.numberOfActionsLeft++; // prevent dialog from closing //

		return;

	}



	var appendtext = rfud.getResponseWikitext();

	var editsummary = '/* ' + rfud.sectionName + ' */ ' + (params.response === 'accept' ? 'Accepting' : 'Declining') + ' request' + rfud.advert;



	var rfudpage = new Morebits.wiki.page('Wikipedia:Requests for undeletion', 'Saving response');

	rfudpage.setPageSection(sectionNumber);

	rfudpage.setAppendText(appendtext);

	rfudpage.setEditSummary(editsummary);

	rfudpage.setMaxConflictRetries(4);  // Account for admins responding to multiple requests simultaneously

	rfudpage.append(function onAppendSuccess(pageobj) {

		// Reload the section html

		var statelem = pageobj.getStatusElement();

		var reloadApi = new Morebits.wiki.api('Done, reloading section', {

			action: 'parse',

			page: 'Wikipedia:Requests for undeletion',

			section: sectionNumber

		}, function onReloadSuccess(apiobj) {

			var html = $(apiobj.responseXML).find('text').text().replace(/&lt;/g, '<').replace(/&gt;/g, '>');

			rfud.$header_container.nextUntil('.mw-heading.mw-heading2').remove();

			rfud.$header_container.replaceWith($(html));

			statelem.info('Done, section reloaded');

		}, statelem);

		reloadApi.post();

	});

};



// Add Accept/Decline button

$('li .sysop-show a').each(function(_, el) {



	el.after(

		' | ',

		$('<a>').text('Accept').attr('href', '#')

			.addClass('rfud-helper-button')

			.addClass('rfud-accept')

			.click(rfud.callback)[0],

		' | ',

		$('<a>').text('Decline').attr('href', '#')

			.addClass('rfud-helper-button')

			.addClass('rfud-decline')

			.click(rfud.callback)[0

	);



});





});



function showDeletedPagePreview() {

	var pagetitle = mw.config.get('wgRelevantPageName');

	var API = new mw.Api({

		ajax: { headers: { 'Api-User-Agent': 'w:en:User:SD0001/RFUD-helper.js' } },

		parameters: { formatversion: '2' }

	});

	API.get({

		"action": "query",

		"prop": "deletedrevisions",

		"titles": pagetitle,

		"drvprop": "content",

		"drvlimit": "1"

	}).then(function(json) {

		var wikitext = json.query.pages0].deletedrevisions0].content;

		wikitext = '=Last deleted version=\n' + wikitext;

		return API.post({

			"action": "parse",

			"title": pagetitle,

			"text": wikitext,

			"disableeditsection": "1",

			"prop": "text|categorieshtml"

		});

	}).then(function(json) {

		$('<div>').attr('id', 'rfud-helper-deleted-preview').html(

			json.parse.text + json.parse.categorieshtml

		).appendTo('#mw-content-text');



		var $anchor = $('.mw-undelete-pagetitle').length ?

			$('.mw-undelete-pagetitle') :

			$('.mw-undelete-subtitle');

		$anchor.append(

			$('<div>').css('float', 'right').append(

				$('<a>').attr('href', '#rfud-helper-deleted-preview').text('[Jump to preview of last revision]')

			)

		);

	});

}



})();



// </nowiki>