User:Novem Linguae/Scripts/FFUHelper.js
Appearance
Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump. This code will be executed when previewing this page. |
Documentation for this user script can be added at User:Novem Linguae/Scripts/FFUHelper. |
/*** FFU Helper ***/
// User script to close and respond to FFU request
// Documentation at [[en:w:User:BrandonXLF/FFUHelper]]
// By [[en:w:User:BrandonXLF]]
// <syntaxhighlight lang=javascript>
mw.hook('wikipage.content').add(function($content) {
if (mw.config.get('wgPageName') !== 'Wikipedia:Files_for_upload') return;
var i = 0,
active = '',
activeSection = -1,
// Template data (TOP TEMPLATE, BOTTOM TEMPLATE, TEMPLATE, DESCRIPTION, PARAMETER 1, PARAMETER 2, TALK TEMPLATE)
data = {
accept: [
['{{su' + 'bst:ffu a}}', '{{su' + 'bst:ffu b}}', '{{su' + 'bst:ffu|a|file=$1}} $2', 'If the file has been uploaded.', 'File', 'Comment', '{{su' + 'bst:ffu talk|file=$1|section=SECTION}}']
],
decline: [
['{{su' + 'bst:ffu d}}', '{{su' + 'bst:ffu b}}', '{{su' + 'bst:ffu|d}} $1', 'If the request has been declined.', 'Comment', '', '{{su' + 'bst:ffu talk|d|section=SECTION}}'],
['{{su' + 'bst:ffu d}}', '{{su' + 'bst:ffu b}}', '{{su' + 'bst:ffu|blankreq}}', 'If the requesting editor did not fill in the necessary fields.', '', '', '{{su' + 'bst:ffu talk|d|section=SECTION}}'],
['{{su' + 'bst:ffu d}}', '{{su' + 'bst:ffu b}}', '{{su' + 'bst:ffu|permission}}', 'If permission has not been granted to use the file.', '{{su' + 'bst:ffu talk|d|section=SECTION}}'],
['{{su' + 'bst:ffu d}}', '{{su' + 'bst:ffu b}}', '{{su' + 'bst:ffu|copyrighted}}', 'If the file is copyrighted, and not available under the given license.', '', '', '{{su' + 'bst:ffu talk|d|section=SECTION}}'],
['{{su' + 'bst:ffu d}}', '{{su' + 'bst:ffu b}}', '{{su' + 'bst:ffu|corrupt}}', 'If the file is not loading properly or is malformed.', '', '', '{{su' + 'bst:ffu talk|d|section=SECTION}}'],
['{{su' + 'bst:ffu d}}', '{{su' + 'bst:ffu b}}', '{{su' + 'bst:ffu|blank}}', 'If the file is blank.', '', '', '{{su' + 'bst:ffu talk|d|section=SECTION}}'],
['{{su' + 'bst:ffu d}}', '{{su' + 'bst:ffu b}}', '{{su' + 'bst:ffu|quality}}', 'If the file is too low-quality to use in an article.', '', '', '{{su' + 'bst:ffu talk|d|section=SECTION}}'],
['{{su' + 'bst:ffu d}}', '{{su' + 'bst:ffu b}}', '{{su' + 'bst:ffu|redundant|file=$1}}', 'If a very similar file already exists.', 'File', '', '{{su' + 'bst:ffu talk|d|section=SECTION}}'],
['{{su' + 'bst:ffu d}}', '{{su' + 'bst:ffu b}}', '{{su' + 'bst:ffu|useless}}', 'If there is no reason to have such an file on Wikipedia.', '', '', '{{su' + 'bst:ffu talk|d|section=SECTION}}'],
['{{su' + 'bst:ffu d}}', '{{su' + 'bst:ffu b}}', '{{su' + 'bst:ffu|nonsense}}', 'If the file is too strange to be used. This is not the same as corrupt above.', '', '', '{{su' + 'bst:ffu talk|d|section=SECTION}}'],
['{{su' + 'bst:ffu d}}', '{{su' + 'bst:ffu b}}', '{{su' + 'bst:ffu|blp}}', 'If the file is a BLP violation.', '', '', '{{su' + 'bst:ffu talk|d|section=SECTION}}'],
['{{su' + 'bst:ffu d}}', '{{su' + 'bst:ffu b}}', '{{su' + 'bst:ffu|advert}}', 'If the file is spam or advertising.', '', '', '{{su' + 'bst:ffu talk|d|section=SECTION}}'],
['{{su' + 'bst:ffu d}}', '{{su' + 'bst:ffu b}}', '{{su' + 'bst:ffu|van}}', 'Plain, pure vandalism files. This is not the same as nonsense, because vandal requests are usually made in bad faith.', '', '', '{{su' + 'bst:ffu talk|d|section=SECTION}}'],
['{{su' + 'bst:ffu d}}', '{{su' + 'bst:ffu b}}', '{{su' + 'bst:ffu|afce}}', 'For submissions that were on hold pending a draft\'s review at AfCwhere the draft has not been reviewed due to the backlog. This decline should only be used after a 7-day hold.', '', '', '{{su' + 'bst:ffu talk|d|section=SECTION}}'],
['{{su' + 'bst:ffu d}}', '{{su' + 'bst:ffu b}}', '{{su' + 'bst:ffu|afcd|page=$1}}', 'For submissions that were on hold pending a draft\'s acceptance at AfC which was declined.', 'Draft', '', '{{su' + 'bst:ffu talk|d|section=SECTION}}'],
['{{su' + 'bst:ffu d}}', '{{su' + 'bst:ffu b}}', '{{su' + 'bst:ffu|afdd|page=$1|afd location=$2}}', 'For submissions that were on hold pending an AfD outcome, which was delete.', 'Page', '', 'AFD location', '{{su' + 'bst:ffu talk|d|section=SECTION}}'],
['{{su' + 'bst:ffu d}}', '{{su' + 'bst:ffu b}}', '{{su' + 'bst:ffu|csdd|page=$1}}', ' For submissions where the associated article has been deleted under CSD.', 'Page', '', '{{su' + 'bst:ffu talk|d|section=SECTION}}']
],
comment: [
['{{su' + 'bst:ffu h}}', '', '{{su' + 'bst:ffu|c}} $1', 'Add a comment.', 'Comment', '', '{{su' + 'bst:ffu talk|c|section=SECTION}}'],
['{{su' + 'bst:ffu h}}', '', '{{su' + 'bst:ffu|l}}', 'If no (link to a) license has been given.', '', '', '{{su' + 'bst:ffu talk|c|section=SECTION}}'],
['{{su' + 'bst:ffu h}}', '', '{{su' + 'bst:ffu|flickr}}', 'For copyrighted Flickr files, where it could be assumed, that the request was made by the owner of the Flickr account.', '', '', '{{su' + 'bst:ffu talk|c|section=SECTION}}'],
['{{su' + 'bst:ffu h}}', '', '{{su' + 'bst:ffu|commons}}', 'Asks the user to upload the file to Wikimedia Commons.', '', '', '{{su' + 'bst:ffu talk|c|section=SECTION}}'],
['{{su' + 'bst:ffu h}}', '', '{{su' + 'bst:ffu|rat}}', 'Asks the user to complete a non-free use rationale for the file, if none has been provided, and the file meets the Non-free content guideline.', '', '', '{{su' + 'bst:ffu talk|c|section=SECTION}}'],
['{{su' + 'bst:ffu h}}', '', '{{su' + 'bst:ffu|nourl}}', 'If the request lacks an url to the file, but it indicates a presence of an offline source.', '', '', '{{su' + 'bst:ffu talk|h|section=SECTION}}'],
['{{su' + 'bst:ffu h}}', '', '{{su' + 'bst:ffu|fixurl}}', 'If the request contains a url that does not work.', '', '', '{{su' + 'bst:ffu talk|h|section=SECTION}}'],
['{{su' + 'bst:ffu h}}', '', '{{su' + 'bst:ffu|h}}', 'Places a request on hold while a reviewer awaits a permission confirmation.', '', '', '{{su' + 'bst:ffu talk|h|section=SECTION}}'],
['{{su' + 'bst:ffu h}}', '', '{{su' + 'bst:ffu|afd|page=$1|afd location=$2}}', 'Places a request on hold if a non-free image is to be used in an article, which is at AfD.', 'Page', 'AfD Location', '{{su' + 'bst:ffu talk|h|section=SECTION}}'],
['{{su' + 'bst:ffu h}}', '', '{{su' + 'bst:ffu|afc|page=$1}}', 'Places a request on hold if a non-free image is to be used in an article, which is awaiting review at AFC.', 'Page', '', '{{su' + 'bst:ffu talk|afc|section=SECTION}}']
],
};
// Select comment template
function select(el, arr, i, name) {
var label = $('<label style="display:block;">')
.append($('<input type="radio" data-arraypos="' + i + '" name="' + name + '"></input>').click(function() {
$('#ffuparameter1' + name +', #ffuparameter2' + name).remove();
$('#' + name).attr('id', '');
$(this).attr('id', name);
if (arr[i][5]) {
$(el.find('label')[i])
.after($('<span id="ffuparameter2' + name + '" style="margin-left:2em;display:block;">')
.append('2: ')
.append($('<input style="border:none;border-bottom:1px solid #555;padding:2px;" type="text" placeholder="' + arr[i][5] + '"></input>'))
);
}
if (arr[i][4]) {
$(el.find('label')[i])
.after($('<span id="ffuparameter1' + name + '" style="margin-left:2em;display:block;">')
.append('1: ')
.append($('<input style="border:none;border-bottom:1px solid #555;padding:2px;" type="text" placeholder="' + arr[i][4] + '"></input>'))
);
}
}))
.append(arr[i][2].replace(/\|section=SECTION/g, '').replace(/\|[a-z0-9A-Z _-]+=\$[0-9]/g, '').replace(/ \$[0-9]/g, '') + ' - <i>' + arr[i][3] + '</i>');
el.append(label);
return label;
}
// Start user interface
function clickui(e) {
var type = $(e.target).text(),
section = parseInt(e.target.parentNode.getAttribute('data-section')),
secname = $(e.target).closest('h2').find('.mw-headline').attr('id');
e.preventDefault();
$('#ffuhelper').remove();
if (active == type && activeSection == section) {
active = '';
return;
}
active = type;
activeSection = section;
var user = '',
element = $(e.target).closest('h2').next();
while (user === '' && element[0]) {
user = element.find('a[href*="Special:Contributions"], a[href*="User:"]').attr('href') || '';
element = element.next();
}
user = (user.match(/.*(?:user:|User:|\/)(.*)$/) || ['', ''])[1];
user = (user.match(/(.*?)&.*/) || ['', ''])[1] || user;
$(this).closest('h2').after($('<p id="ffuhelper" style="border:1px solid ' + {comment: 'grey', decline: 'red', accept: 'green'}[type] + ';border-radius:4px;padding:4px 0.5em;"></p>')
.append('<span style="font-size:125%;font-weight:bold;">FFU Helper - ' + type.charAt(0).toUpperCase() + type.slice(1) + '</span><br>')
.append($('<div style="margin-left:5px;">').append(function() {
for (i = 0; i < data[type].length; i++) {
var label = select($(this), data[type], i, type);
if (i === 0) label.children().first().click();
}
return '';
}))
.append('<hr style="margin:0.5em;">')
.append(type == 'comment' ? ('<div style="margin-left:5px;"><label><input type="checkbox" id="ffutoptemplate" checked>Add 7 day hold notice</input></label></div>') : '')
.append('<div style="margin-left:5px;"><label><input type="checkbox" id="ffunotify" checked>Notify user: </input></label><input style="border:none;border-bottom:1px solid #555;padding:2px;" placeholder="User" value="' + user + '" id="ffuuser"></div>')
.append($('<div style="margin:4px 0 0 -4px;">')
// Save changes
.append($('<button style="margin:4px;">Save</button>').click(function() {
if (!$('#' + type).attr('data-arraypos')) return;
$.get(mw.config.get('wgScript'), {
title: mw.config.get('wgPageName'),
action: 'raw',
section: section
}).done(function(r) {
r = r + '\n:' + data[type][$('#' + type).attr('data-arraypos')][2].replace(/\$1/, $('#ffuparameter1' + type + ' input').val() || '').replace(/\$2/, $('#ffuparameter2' + type + ' input').val() || '') + '~~' + '~~';
if ($('#ffutoptemplate').prop('checked') !== false && data[type][$('#' + type).attr('data-arraypos')][0]) {
if (type == 'comment') {
r = r.replace(/{{(?:Template:|)[Ff]fu h\|.*?}}/g, '');
r = r.replace(/-->\n/, '-->');
r = r.replace(/-->\n+/, '-->');
r = r.replace(/\n+<!--/, '<!--');
} else {
r = r.replace(/(<!-- \[\[User:DoNotArchiveUntil\]\].*[\n\r]*)/, '');
}
r = r.replace(/(==.*==)\n*/, '$1\n' + data[type][$('#' + type).attr('data-arraypos')][0] + '\n');
}
if (data[type][$('#' + type).attr('data-arraypos')][1]) {
r = r + '\n' + data[type][$('#' + type).attr('data-arraypos')][1];
}
var c = 0,
s = $('#ffunotify').prop('checked') && $('#ffuuser').val() ? 2 : 1;
function updatePage() {
c++;
if (c === s) {
mw.notify('Updating page...');
$.get(mw.config.get('wgScriptPath') + '/api.php', {
action: 'parse',
page: mw.config.get('wgPageName'),
prop: 'text|categorieshtml',
format: 'json'
}).done(function(r) {
var contentText = $('#mw-content-text'),
catLinks = $('#catlinks');
contentText.find('.mw-parser-output').replaceWith(r.parse.text['*']);
mw.hook('wikipage.content').fire(contentText);
catLinks.replaceWith(r.parse.categorieshtml['*']);
mw.hook('wikipage.categories').fire(catLinks);
mw.notify('Page updated.');
});
}
}
mw.notify('Editing FFU request...');
$.post(mw.config.get('wgScriptPath') + '/api.php', {
action: 'edit',
section: section,
text: r,
title: mw.config.get('wgPageName'),
token: mw.user.tokens.get('csrfToken'),
summary: ((type.charAt(0).toUpperCase() + type.slice(1)) + 'ed').replace('ee', 'e').replace('Commented', 'Commented on') + ' request using [[en:w:User:BrandonXLF/FFUHelper|FFU Helper]]'
}).done(function() {
mw.notify('Finished editing FFU request.');
updatePage();
});
if ($('#ffunotify').prop('checked') && $('#ffuuser').val()) {
mw.notify('Posting on user talk page...');
$.post(mw.config.get('wgScriptPath') + '/api.php', {
action: 'edit',
appendtext: '\n\n' + data[type][$('#' + type).attr('data-arraypos')][6].replace(/\$1/, $('#ffuparameter1' + type + ' input').val() || '').replace(/\$2/, $('#ffuparameter2' + type + ' input').val() || '').replace('SECTION', secname.replace(/_/g, ' ') || '') + '~~' + '~~',
title: 'User talk:' + $('#ffuuser').val(),
token: mw.user.tokens.get('csrfToken'),
summary: 'Notifying about [[WP:FFU|FFU]] request using [[en:w:User:BrandonXLF/FFUHelper|FFU Helper]]'
}).done(function() {
mw.notify('Finished positing on user talk page.');
updatePage();
});
} else if ($('#ffunotify').prop('checked')) {
mw.notify('No username given to notify.');
}
});
}))
// Abort changes
.append($('<button style="margin:4px;">Cancel</button>').click(function() {
$('#ffuhelper').remove();
active = 0;
}))
)
.append(
'<span style="display:block;margin-top:4px;">[' +
'<a href="https://en.wikipedia.org/wiki/Wikipedia:Files_for_upload/Reviewer_instructions">Reviewer instructions</a>' +
' • <a href="https://commons.wikimedia.org/wiki/Special:UploadWizard">Commons</a>' +
' (<a href="https://commons.wikimedia.org/wiki/Special:Upload">plain</a>)' +
' • <a href="' + mw.config.get('wgScript') + '?title=Wikipedia:File_Upload_Wizard&withJS=MediaWiki:FileUploadWizard.js">Local</a>' +
' (<a href="' + mw.config.get('wgScript') + '?title=Special:Upload">plain</a>)' +
' • <a href="https://en.wikipedia.org/wiki/User:BrandonXLF/FFUHelper">FFU Helper</a>' +
']</span>'
)
);
}
// Add links to sections
$content.find('.mw-parser-output h2').each(function() {
let $el = $('[href*="title="][href*="section="]', this);
let href = $el.attr('href');
if ( href === undefined ) {
return;
}
var section = /[?&]v?e?section=T?-?(\d*)/.exec(href)[1];
if ($(this).next().hasClass('navbox')) {
$(this).find('span.mw-editsection').after('<span class="mw-editsection" style="background:#ADFF2F;">[closed]</span>');
return;
}
$(this).find('span.mw-editsection')
.after(
$('<span style="background:yellow;" data-section="' + section + '" class="mw-editsection"></span>')
.append('[')
.append($('<a href="#' + $(this).closest('h2').find('.mw-headline').attr('id') + '">comment</a>').click(clickui))
.append(']')
)
.after(
$('<span style="background:yellow;" data-section="' + section + '" class="mw-editsection"></span>')
.append('[')
.append($('<a href="#' + $(this).closest('h2').find('.mw-headline').attr('id') + '">decline</a>').click(clickui))
.append(']')
)
.after(
$('<span style="background:yellow;" data-section="' + section + '" class="mw-editsection"></span>')
.append('[')
.append($('<a href="#' + $(this).closest('h2').find('.mw-headline').attr('id') + '">accept</a>').click(clickui))
.append(']')
);
});
});
// </syntaxhighlight>