User:SD0001/RFUD-helper.js
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', '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();
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_element[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 url = new URL(rfud.$header_container.find('.mw-editsection a').attr('href'));
sectionNumber = parseInt(url.searchParams.get('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(/</g, '<').replace(/>/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.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>