User:SD0001/RFUD-helper.js

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.childNodes[1].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();
	}
	rfud.$header_element = $header_div.find('h2');
	rfud.sectionName = rfud.$header_element.children(".mw-headline")[0].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 = userMatch[1].replace(/_/g, ' ');
		} else {
			rfud.requestingUser = null;
		}
	} else {
		rfud.requestingUser = null;
	}
	
	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')
		});
	}
	// 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.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'
		});

		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_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'
	});
	
	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) {
		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), "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; }
		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'].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_button[0], 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_button[0], 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 && json[0] && json[0].query && json[0].query.pages) {
				var timestamp = Object.values(json[0].query.pages)[0].revisions[0].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_element.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_element.parent().nextUntil('.mw-heading.mw-heading2').remove();
			rfud.$header_element.parent().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.pages[0].deletedrevisions[0].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>