// Script to respond to edit filter false positive reports
// Based on [[User:DannyS712/EFFPRH/sandbox.js]]
// <nowiki>
$(() => {
const EFFPRH = {
config: {
debug: false
},
responseOptions: [
{ data: 'none', label: 'None' },
{ data: 'nofilterstriggered', label: 'No filters triggered' },
{ data: 'done', label: 'Done (no change to filter)' },
{ data: 'defm', label: 'Done (may need a change to filter)' },
{ data: 'notdone', label: 'Not Done (filter working properly)' },
{ data: 'ndefm', label: 'Not Done (may need a change to filter)' },
{ data: 'redlink', label: 'Not Done (notable people)' },
{ data: 'alreadydone', label: 'Already Done' },
{ data: 'denied', label: 'Decline (edits are vandalism)' },
{ data: 'checking', label: 'Checking' },
{ data: 'blocked', label: 'User blocked' },
{ data: 'talk', label: 'Request on article talk page' },
{ data: 'fixed', label: 'Fixed filter' },
{ data: 'question', label: 'Question' },
{ data: 'note', label: 'Note' },
{ data: 'private', label: 'Private filter' },
{ data: 'pin', label: 'Pin' },
{ data: 'moot', label: 'Moot (filter working properly)' },
{ data: 'mootefm', label: 'Moot (may need a change to filter)' }
],
responseSummaryMap: {
none: '',
nofilterstriggered: 'No filters triggered',
done: 'Done; no change to filter',
defm: 'Done; may need a change to filter',
notdone: 'Not done; filter working properly',
ndefm: 'Not done; may need a change to filter',
redlink: 'Not done; notable people lists and similar are only meant for [[WP:WTAF|people who already have articles about them]]',
alreadydone: 'Already done',
denied: 'Decline; edits are vandalism',
checking: 'Checking',
blocked: 'User is blocked',
talk: 'Please request on article talk page',
fixed: 'Fixed filter',
question: 'Question',
note: 'Note',
private: 'Private filter',
pin: 'Pin',
moot: 'Moot; filter working properly',
mootefm: 'Moot; may need a change to filter'
},
init() {
const allowedPages = [
'Wikipedia:Edit filter/False positives/Reports',
'User:DannyS712/EFFPRH/sandbox'
];
const currentPage = mw.config.get('wgPageName').replace(/_/g, ' ');
if (!allowedPages.includes(currentPage)) return;
mw.loader.using(['oojs-ui', 'mediawiki.util', 'mediawiki.api'], this.run.bind(this));
},
run() {
this.addStyle();
$('div.mw-heading h2').each((_, heading) => {
const editLinks = $(heading).parent().find('.mw-editsection');
const sectionNum = this.getSectionNumber(editLinks);
if (sectionNum !== -1) {
const nextSection = $(heading).parent().next('section');
if (nextSection.length > 0) {
nextSection.prepend($('<div>').attr('id', `script-EFFPRH-${sectionNum}`));
} else {
$(heading).parent().after($('<div>').attr('id', `script-EFFPRH-${sectionNum}`));
}
this.addHandlerLink(editLinks, $(heading).text(), sectionNum);
}
});
},
addStyle() {
mw.util.addCSS(`
.script-EFFPRH-handler { background-color: #f5f5f5; border: 1px solid #ccc; margin: 10px 0; padding: 10px; border-radius: 5px; }
.script-EFFPRH-handler td { vertical-align: middle; padding: 5px; }
.script-EFFPRH-handler ul { margin: 10px 0 10px 2em; padding: 0; list-style-position: inside; }
.script-EFFPRH-preview { background-color: white; }
.oo-ui-dropdownWidget .oo-ui-dropdownWidget-handle { min-width: 220px; }
`);
},
getSectionNumber(editLinks) {
const editSectionUrl = editLinks.find('a:first').attr('href');
const sectionMatch = editSectionUrl && editSectionUrl.match(/§ion=(\d+)(?:$|&)/);
return sectionMatch ? parseInt(sectionMatch[1]) : -1;
},
addHandlerLink(editLinks, reporterName, sectionNum) {
const handlerLink = $('<a>').attr('id', `script-EFFPRH-launch-${sectionNum}`).text('Review report');
handlerLink.click((e) => {
e.stopPropagation();
if (!handlerLink.hasClass('script-EFFPRH-disabled')) {
handlerLink.addClass('script-EFFPRH-disabled');
this.showHandler(reporterName, sectionNum);
}
});
editLinks.children().last().before(' | ', handlerLink);
},
showHandler(reporterName, sectionNum) {
$(`#script-EFFPRH-${sectionNum}`).empty();
let selectedResponse = 'none';
let commentValue = '';
let showPreview = false;
let haveSubmitted = false;
let editMade = false;
let editError = false;
const $container = $('<div>').addClass('script-EFFPRH-handler');
$container.append($('<p>').text(`Responding to report by ${reporterName}.`));
let $debugP, updateDebug;
if (EFFPRH.config.debug) {
$debugP = $('<p>');
$container.append($debugP);
updateDebug = function() {
$debugP.text(
`Section ${sectionNum}, selected response: ${selectedResponse}, comment: ${commentValue}.`
);
};
updateDebug();
}
const $table = $('<table>');
const dropdown = new OO.ui.DropdownWidget({
label: 'Response to report',
menu: {
items: EFFPRH.responseOptions.map(opt =>
new OO.ui.MenuOptionWidget({ data: opt.data, label: opt.label })
)
}
});
dropdown.getMenu().selectItemByData('none');
const $dropdownRow = $('<tr>')
.append($('<td>').append($('<label>').text('Action:')))
.append($('<td>').append(dropdown.$element));
$table.append($dropdownRow);
const textInput = new OO.ui.TextInputWidget({
placeholder: 'Optional comment'
});
const $commentRow = $('<tr>')
.append($('<td>').append($('<label>').text('Comment:')))
.append($('<td>').append(textInput.$element));
$table.append($commentRow);
$container.append($table);
const $statusUl = $('<ul>').css('margin', 0).hide();
const $liSubmitting = $('<li>').text('Submitting...');
const $liSuccess = $('<li>').html(`Success! <a href="#"><strong>Reload the page</strong></a></li>`);
const $liError = $('<li>').text('Uh-oh, something went wrong. Please check the console for details.');
$statusUl.append($liSubmitting).append($liSuccess.hide()).append($liError.hide());
$container.append($statusUl);
const submitBtn = new OO.ui.ButtonWidget({
label: 'Submit',
flags: ['progressive'],
disabled: true
});
const cancelBtn = new OO.ui.ButtonWidget({
label: 'Cancel',
flags: ['destructive']
});
const previewToggleBtn = new OO.ui.ToggleButtonWidget({
label: 'Show preview',
disabled: true
});
const $btnRow = $('<div>').css('margin', '10px 0')
.append(submitBtn.$element)
.append(cancelBtn.$element)
.append(previewToggleBtn.$element);
$container.append($btnRow);
const $previewArea = $('<div>').addClass('script-EFFPRH-preview').hide();
$container.append($previewArea);
$(`#script-EFFPRH-${sectionNum}`).append($container);
function getResponseWikiText() {
return `: {{EFFP|${selectedResponse}}} ${commentValue} – ~~~~`;
}
function updatePreview() {
$previewArea.empty();
if (showPreview && selectedResponse !== 'none') {
$previewArea.append('<hr>');
$previewArea.append($('<div>').text('Loading preview...'));
new mw.Api().get({
action: 'parse',
formatversion: 2,
title: mw.config.get('wgPageName'),
text: getResponseWikiText(),
prop: 'text|wikitext',
pst: true,
disablelimitreport: true,
disableeditsection: true,
sectionpreview: true
}).then(function (res) {
if (res && res.parse && res.parse.text) {
$previewArea.empty().append('<hr>').append(
$('<div>').html(res.parse.text)
);
} else {
$previewArea.empty().append('<hr>').append(
$('<div>').text('Error loading preview.')
);
}
});
}
$previewArea.toggle(showPreview && selectedResponse !== 'none');
}
function updateCanSubmit() {
const canSubmit = !haveSubmitted && selectedResponse !== 'none';
submitBtn.setDisabled(!canSubmit);
previewToggleBtn.setDisabled(!canSubmit);
}
dropdown.getMenu().on('choose', function (item) {
selectedResponse = item.getData();
updateCanSubmit();
previewToggleBtn.setLabel(showPreview ? 'Hide preview' : 'Show preview');
updatePreview();
if (EFFPRH.config.debug) updateDebug();
});
textInput.on('change', function (val) {
commentValue = val;
updatePreview();
if (EFFPRH.config.debug) updateDebug();
});
previewToggleBtn.on('change', function (on) {
showPreview = on;
previewToggleBtn.setLabel(showPreview ? 'Hide preview' : 'Show preview');
updatePreview();
});
submitBtn.on('click', function () {
haveSubmitted = true;
updateCanSubmit();
$statusUl.show();
$liSubmitting.show();
$liSuccess.hide();
$liError.hide();
EFFPRH.respondToReport(
reporterName,
sectionNum,
getResponseWikiText(),
selectedResponse
).then(
function () {
editMade = true;
$liSubmitting.hide();
$liSuccess.show();
$liSuccess.find('a').on('click', function (e) {
e.preventDefault();
___location.assign(`${mw.util.getUrl(mw.config.get('wgPageName'))}#${reporterName}`);
___location.reload();
});
},
function () {
editError = true;
$liSubmitting.hide();
$liError.show();
}
);
});
cancelBtn.on('click', function () {
$(`#script-EFFPRH-${sectionNum}`).empty();
$(`#script-EFFPRH-launch-${sectionNum}`).removeClass('script-EFFPRH-disabled');
});
updateCanSubmit();
},
respondToReport(reporterName, sectionNum, responseWikiText, selectedResponse) {
return new Promise((resolve, reject) => {
const wikitextToAdd = `\n${responseWikiText}`;
let respText = EFFPRH.responseSummaryMap[selectedResponse] || selectedResponse;
if (!respText) {
respText = 'Response to false positive report';
}
const editParams = {
action: 'edit',
title: mw.config.get('wgPageName'),
section: sectionNum,
summary: `/* ${reporterName} */ ${respText} ([[User:DreamRimmer/EFFPRH|EFFPRH.js]])`,
appendtext: wikitextToAdd,
token: mw.user.tokens.get('csrfToken')
};
new mw.Api().postWithEditToken(editParams).then(resolve, reject);
});
}
};
EFFPRH.init();
});
// </nowiki>