User:Xiplus/TwinkleGlobal/twinklearv.js
Appearance
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
// <nowiki>
(function($) {
/*
****************************************
*** twinklearv.js: ARV module
****************************************
* Mode of invocation: Tab ("GARV")
* Active on: Any page with relevant user name (userspace, contribs, etc.)
*/
TwinkleGlobal.arv = function twinklearv() {
var username = mw.config.get('wgRelevantUserName');
if (!username || username === mw.config.get('wgUserName')) {
return;
}
var disabledWikis = $.map(TwinkleGlobal.getPref('arvDisabledWikis'), function(el) {
return el.value.trim();
});
if (disabledWikis.indexOf(mw.config.get('wgDBname')) !== -1) {
return;
}
var title = MorebitsGlobal.ip.isIPOrTemp(username, true) ? 'Report IP to stewards' : 'Report user to stewards';
TwinkleGlobal.addPortletLink(function() {
TwinkleGlobal.arv.callback([username]);
}, 'GARV', 'twg-arv', title);
};
TwinkleGlobal.arv.usernames = [];
// Return: header, language, project
TwinkleGlobal.arv.getProject = function () {
switch (MorebitsGlobal.wikiFamily) {
case 'wikimedia':
switch (MorebitsGlobal.wikiLang) {
case 'commons':
return ['commons', 'commons', ''];
case 'meta':
return ['meta', 'meta', ''];
case 'species':
return ['species', 'species', ''];
case 'incubator':
return ['incubator', 'incubator', ''];
default:
return [MorebitsGlobal.wikiLang + '.wikimedia', MorebitsGlobal.wikiLang, 'wikimedia'];
}
case 'mediawiki':
return ['mediawiki.org', 'mw', ''];
case 'wikidata':
return ['wikidata', 'd', ''];
case 'wikipedia':
return [MorebitsGlobal.wikiLang + '.wikipedia', MorebitsGlobal.wikiLang, 'w'];
case 'wikibooks':
return [MorebitsGlobal.wikiLang + '.wikibooks', MorebitsGlobal.wikiLang, 'b'];
case 'wikiquote':
return [MorebitsGlobal.wikiLang + '.wikiquote', MorebitsGlobal.wikiLang, 'q'];
case 'wiktionary':
return [MorebitsGlobal.wikiLang + '.wiktionary', MorebitsGlobal.wikiLang, 'wikt'];
case 'wikinews':
return [MorebitsGlobal.wikiLang + '.wikinews', MorebitsGlobal.wikiLang, 'n'];
case 'wikisource':
return [MorebitsGlobal.wikiLang + '.wikisource', MorebitsGlobal.wikiLang, 's'];
case 'wikiversity':
return [MorebitsGlobal.wikiLang + '.wikiversity', MorebitsGlobal.wikiLang, 'v'];
case 'wikivoyage':
return [MorebitsGlobal.wikiLang + '.wikivoyage', MorebitsGlobal.wikiLang, 'voy'];
default:
return [MorebitsGlobal.wikiLang + '.' + MorebitsGlobal.wikiFamily, MorebitsGlobal.wikiLang, MorebitsGlobal.wikiFamily];
}
};
TwinkleGlobal.arv.callback = function (usernames, defaultCategory) {
TwinkleGlobal.arv.usernames = usernames;
var Window = new MorebitsGlobal.simpleWindow(600, 500);
Window.setTitle('Advance Reporting and Vetting'); // Backronym
Window.setScriptName('Twinkle');
Window.addFooterLink('Add custom reason', TwinkleGlobal.getPref('configPage'));
Window.addFooterLink('Suggest useful reasons', TwinkleGlobal.getPref('bugReportLink'));
var isIP = MorebitsGlobal.ip.isIPOrTemp(usernames[0], true);
if (isIP) {
Window.addFooterLink('Global blocks', 'm:Special:MyLanguage/Global blocks');
} else {
Window.addFooterLink('Global locks', 'm:Special:MyLanguage/Global locks');
}
// form initialise
var form = new MorebitsGlobal.quickForm(TwinkleGlobal.arv.callback.evaluate);
var categories = form.append({
type: 'select',
name: 'category',
label: 'Select report type: ',
event: TwinkleGlobal.arv.callback.changeCategory
});
categories.append({
type: 'option',
label: isIP ? 'Global block (m:SRG)' : 'Global lock (m:SRG)',
value: 'global',
selected: defaultCategory === 'global'
});
if (MorebitsGlobal.isGSWiki()) {
categories.append({
type: 'option',
label: 'Global sysops/Requests (m:GS/R)',
value: 'gsr',
selected: defaultCategory === 'gsr'
});
}
if (!isIP) {
categories.append({
type: 'option',
label: 'Checkuser (m:SRCU)',
value: 'srcu',
selected: defaultCategory === 'srcu'
});
}
form.append({
type: 'field',
label: 'Work area',
name: 'work_area'
});
form.append({ type: 'submit' });
form.append({
type: 'hidden',
name: 'uid',
value: usernames[0]
});
var result = form.render();
Window.setContent(result);
Window.display();
// We must init the
var evt = document.createEvent('Event');
evt.initEvent('change', true, true);
result.category.dispatchEvent(evt);
};
TwinkleGlobal.arv.callback.changeCategory = function (e) {
var value = e.target.value;
var root = e.target.form;
var old_area = MorebitsGlobal.quickForm.getElements(root, 'work_area')[0];
var work_area = null;
var username = TwinkleGlobal.arv.usernames[0];
switch (value) {
case 'global':
/* falls through */
default:
work_area = new MorebitsGlobal.quickForm.element({
type: 'field',
label: MorebitsGlobal.ip.isIPOrTemp(username, true)
? 'Request for global block' : 'Request for global lock',
name: 'work_area'
});
if (MorebitsGlobal.ip.isIPOrTemp(username, true)) {
work_area.append({
type: 'input',
name: 'header',
label: 'Header: Global block for ',
value: '[[Special:Contributions/' + username + '|' + username + ']]',
size: 50
});
work_area.append({
type: 'dyninput',
name: 'username',
label: 'IPs',
sublabel: 'IP: ',
tooltip: 'Without the User:-prefix',
min: 1,
size: 50
});
} else {
work_area.append({
type: 'input',
name: 'header',
label: 'Header: Global lock for ',
value: username,
className: 'mgfullwidth'
});
work_area.append({
type: 'dyninput',
name: 'username',
label: 'Usernames',
sublabel: 'Username: ',
tooltip: 'Without the User:-prefix',
min: TwinkleGlobal.arv.usernames.length,
size: 50
});
work_area.append({
type: 'checkbox',
list: [
{
label: 'Hide username',
tooltip: 'Check it if you do not want the name to be visible on this page',
name: 'hidename',
value: 'hidename',
event: TwinkleGlobal.arv.callback.changeHidename
}
]
});
}
work_area.append({
type: 'header',
label: 'Comment: '
});
work_area.append({
type: 'checkbox',
name: 'globaltype',
list: [
{
label: 'Long-term abuse',
value: 'Long-term abuse'
},
{
label: 'Cross-wiki abuse',
value: 'Cross-wiki abuse'
},
{
label: 'Abusive username',
value: 'Abusive username'
},
{
label: 'Spam / spambot',
value: 'Spam / spambot'
},
{
label: 'Compromised',
value: 'Compromised'
}
].concat(TwinkleGlobal.getPref('customSRGReasonList'))
});
work_area.append({
type: 'textarea',
name: 'reason'
});
work_area = work_area.render();
TwinkleGlobal.arv.usernames.forEach(function(username, index) {
$('input:text[name=username]', work_area).eq(index).val(username);
});
old_area.parentNode.replaceChild(work_area, old_area);
break;
case 'gsr':
work_area = new MorebitsGlobal.quickForm.element({
type: 'field',
label: 'Report user to Global sysops/Requests',
name: 'work_area'
});
work_area.append({
type: 'header',
label: 'Comment: '
});
work_area.append({
type: 'checkbox',
name: 'gsrtype',
list: [
{
label: 'Vandalism',
value: 'Vandalism'
},
{
label: 'Spam / spambot',
value: 'Spam / spambot'
}
].concat(TwinkleGlobal.getPref('customGARVGSRReasonList'))
});
work_area.append({
type: 'textarea',
name: 'reason'
});
work_area = work_area.render();
old_area.parentNode.replaceChild(work_area, old_area);
break;
case 'srcu':
work_area = new MorebitsGlobal.quickForm.element({
type: 'field',
label: 'Request for checkuser',
name: 'work_area'
});
var localCheckuser = [
/* Wikimedia */ 'metawiki', 'commonswiki', 'specieswiki', 'wikidatawiki',
/* Wikipedia L1 */ 'arwiki', 'bnwiki', 'cawiki', 'cswiki', 'dawiki', 'dewiki', 'enwiki', 'eswiki',
/* Wikipedia L2 */ 'fawiki', 'fiwiki', 'frwiki', 'hewiki', 'hrwiki', 'huwiki', 'idwiki', 'itwiki',
/* Wikipedia L3 */ 'jawiki', 'kowiki', 'mlwiki', 'nlwiki', 'plwiki', 'ptwiki', 'ruwiki', 'simplewiki',
/* Wikipedia L4 */ 'slwiki', 'srwiki', 'svwiki', 'thwiki', 'trwiki', 'ukwiki', 'viwiki',
/* Others */ 'enwikibooks', 'enwiktionary'
];
if (localCheckuser.indexOf(mw.config.get('wgDBname')) !== -1) {
work_area.append({
type: 'div',
label: 'The checkuser on this wiki should be locally handled, are you sure you want to request stewards\' help?',
style: 'color: red; font-weight: bold;'
});
}
// header mixed preview
work_area.append({
type: 'input',
name: 'header',
label: 'Header: ',
value: username + '@' + TwinkleGlobal.arv.getProject()[0],
size: 65
});
work_area.append({
type: 'input',
name: 'langcode',
label: 'Language code: ',
value: TwinkleGlobal.arv.getProject()[1]
});
work_area.append({
type: 'input',
name: 'project',
label: 'Project shortcut: ',
value: TwinkleGlobal.arv.getProject()[2]
});
work_area.append(
{
type: 'dyninput',
name: 'sockpuppet',
label: 'Users to compare',
sublabel: 'Username :',
tooltip: 'Usernames of suspected sockpuppets. Without the User:-prefix.',
min: Math.max(TwinkleGlobal.arv.usernames.length, 2),
max: 10
});
work_area.append({
type: 'input',
name: 'discussion',
label: 'Discussion: ',
tooltip: 'Local confirmation or policy',
size: 65
});
work_area.append({
type: 'textarea',
name: 'reason',
label: 'Reason',
tooltip: 'will add ~~~~'
});
work_area.append({
type: 'header',
label: 'Due to the impact of checkuser, please confirm you really want to request this checkuser and click the box below.'
});
work_area.append({
type: 'checkbox',
list: [
{
label: 'I confirm this request is beneficial for the community and I will take full responsibility for this request.',
name: 'disclaimer',
value: 'disclaimer'
}
]
});
work_area = work_area.render();
TwinkleGlobal.arv.usernames.forEach(function(username, index) {
$('input:text[name=sockpuppet]', work_area).eq(index).val(username);
});
old_area.parentNode.replaceChild(work_area, old_area);
break;
}
};
TwinkleGlobal.arv.callback.changeHidename = function(e) {
var checked = e.target.checked;
var form = e.target.form;
var username = TwinkleGlobal.arv.usernames[0];
if (checked) {
form.header.value = '';
} else {
form.header.value = username;
}
};
TwinkleGlobal.arv.callback.evaluate = function(e) {
var form = e.target;
var header, summary, reason, comment, types, statusIndicator, metaapi;
var uid = form.uid.value;
switch (form.category.value) {
case 'gsr':
reason = '';
comment = '';
if (form.reason) {
comment = form.reason.value;
}
types = form.getChecked('gsrtype');
if (!types.length && comment === '') {
alert('You must specify some reason');
return;
}
reason = '* Please block ';
if (MorebitsGlobal.interwikiPrefix !== null) {
reason += '{{LockHide|1=' + uid + '|2=' + MorebitsGlobal.interwikiPrefix + ':}}';
} else {
reason += 'https:' + mw.config.get('wgServer') + mw.util.getUrl('Special:Contributions/' + uid);
}
reason += ': ';
types = types.map(function(v) {
switch (v) {
default:
return v;
}
}).join('. ');
if (types) {
reason += types;
}
if (comment !== '') {
comment = comment.replace(/\r?\n/g, '\n:'); // indent newlines
reason += (types ? '. ' : '') + comment;
}
reason = reason.trim();
if (reason.search(/[.?!;]$/) === -1) {
reason += '.';
}
reason += ' ~~~~';
MorebitsGlobal.simpleWindow.setButtonsEnabled(false);
MorebitsGlobal.status.init(form);
statusIndicator = new MorebitsGlobal.status('Reporting to Global sysops/Requests', 'Fetching page...');
metaapi = TwinkleGlobal.getPref('metaApi');
metaapi.edit('Global sysops/Requests', function(revision) {
var text = revision.content.trim();
text += '\n' + reason;
return {
text: text,
summary: 'Reporting user' + TwinkleGlobal.getPref('summaryAd'),
assert: 'user'
};
}).then(function() {
statusIndicator.info('Done');
}, function(e) {
statusIndicator.error(e);
});
break;
case 'srcu':
var trust = form.disclaimer.checked;
if (!trust) {
alert('You should check the box after reading the text or you can not request');
return;
}
var headerVal = form.header.value.trim();
reason = form.reason.value.trim();
var sockpuppets = $.map($('input:text[name=sockpuppet]', form), function (o) {
return $(o).val() || null;
});
if (sockpuppets.length <= 1) {
alert('You must specify at least two usernames to compare');
return;
}
if (reason === '') {
alert('You must provide the reason to run this check');
return;
}
// build section title
header = '=== ' + headerVal + ' ===\n';
header += '{{CU request\n' +
' |status = \n' +
' |language code = ' + form.langcode.value + '\n' +
' |project shortcut = ' + form.project.value + '\n';
sockpuppets.forEach(function(v, i) {
header += ' |user name' + (i + 1) + ' = ' + v + '\n';
});
header += ' |discussion = ' + form.discussion.value + '\n' +
' |reason = ' + reason + ' ~~~~\n' +
'}}';
summary = 'Requesting checkuser for ' + headerVal;
MorebitsGlobal.simpleWindow.setButtonsEnabled(false);
MorebitsGlobal.status.init(form);
statusIndicator = new MorebitsGlobal.status('Reporting to Steward requests/Checkuser', 'Fetching page...');
metaapi = TwinkleGlobal.getPref('metaApi');
metaapi.edit('Steward requests/Checkuser', function(revision) {
var text = revision.content;
text = text.replace(/(== See also == <!-- DO NOT EDIT UNDER THIS LINE -->)/, function(m) {
return header + '\n\n' + m;
});
return {
text: text,
summary: summary + TwinkleGlobal.getPref('summaryAd'),
assert: 'user'
};
}).then(function() {
statusIndicator.info('Done. Remember to review your edits.');
}, function(e) {
statusIndicator.error(e);
});
break;
case 'global':
/* falls through */
default:
reason = '';
comment = '';
if (form.reason) {
comment = form.reason.value;
}
types = form.getChecked('globaltype');
if (!types.length && comment === '') {
alert('You must specify some reason');
return;
}
var usernames = $.map($('input:text[name=username]', form), function(o) {
return $(o).val() || null;
});
if (!usernames.length) {
alert('You must specify at least one ' + MorebitsGlobal.ip.isIPOrTemp(uid, true) ? 'IP' : 'user');
return;
}
if (MorebitsGlobal.ip.isIPOrTemp(uid, true)) {
header = '=== Global block ';
if (form.header.value.trim()) {
header += 'for ' + form.header.value.trim();
}
header += ' ===\n';
header += '{{Status}}\n';
usernames.forEach(function(v) {
header += '* {{Luxotool|' + v + '}}\n';
});
summary = 'Reporting [[Special:Contributions/' + usernames[0] + '|' + usernames[0] + ']]';
if (usernames.length > 1) {
summary += ' and ' + (usernames.length - 1) + ' other IP';
if (usernames.length > 2) {
summary += 's';
}
}
} else {
header = '=== Global lock ';
if (form.header.value.trim()) {
header += 'for ' + form.header.value.trim();
}
header += ' ===\n';
if (form.hidename && form.hidename.checked) {
summary = 'Reporting ' + (usernames.length > 1 ? usernames.length + ' accounts' : 'an account');
} else {
summary = 'Reporting [[Special:CentralAuth/' + usernames[0] + '|' + usernames[0] + ']]';
if (usernames.length > 1) {
summary += ' and ' + (usernames.length - 1) + ' other account';
if (usernames.length > 2) {
summary += 's';
}
}
}
header += '{{Status}}\n';
if (usernames.length === 1) {
header += '*{{LockHide|1=' + usernames[0];
if (form.hidename && form.hidename.checked) {
header += '|hidename=1';
}
header += '}}\n';
} else {
if (usernames.length > TwinkleGlobal.getPref('srgCollapseNumber')) {
header += '{{Collapse top|User list}}\n';
}
header += '{{MultiLock';
usernames.forEach(function(v, i) {
header += '|' + (i + 1) + '=' + v;
});
if (form.hidename && form.hidename.checked) {
header += '|hidename=1';
}
header += '}}\n';
if (usernames.length > TwinkleGlobal.getPref('srgCollapseNumber')) {
header += '{{Collapse bottom}}\n';
}
}
}
types = types.map(function(v) {
switch (v) {
default:
return v;
}
}).join('. ');
if (types) {
reason += types;
}
if (comment !== '') {
comment = comment.replace(/\r?\n/g, '\n:'); // indent newlines
reason += (types ? '. ' : '') + comment;
}
reason = reason.trim();
if (reason.search(/[.?!;]$/) === -1) {
reason += '.';
}
reason += ' ~~~~';
MorebitsGlobal.simpleWindow.setButtonsEnabled(false);
MorebitsGlobal.status.init(form);
statusIndicator = new MorebitsGlobal.status('Reporting to Steward requests/Global', 'Fetching page...');
metaapi = TwinkleGlobal.getPref('metaApi');
metaapi.edit('Steward requests/Global', function(revision) {
var text = revision.content;
if (new RegExp('{{\\s*([Ll]uxotool|[Ll]ock[Hh]ide|[Ll][Hh]|[Mm]ulti[Ll]ock)[^}]*?\\|\\s*(\\d+\\s*=\\s*)?' + RegExp.escape(usernames[0], true) + '\\s*(\\||}})').test(text)) {
return $.Deferred().reject('Report already present, will not add a new one');
}
if (MorebitsGlobal.ip.isIPOrTemp(uid, true)) {
text = text.replace(/\n+(== Requests for global \(un\)lock and \(un\)hiding == *\n)/, function(_, p1) {
return '\n\n' + header + reason + '\n\n' + p1;
});
} else {
text = text.replace(/\n+(== See also == *\n)/, function(_, p1) {
return '\n\n' + header + reason + '\n\n' + p1;
});
}
return {
text: text,
summary: summary + TwinkleGlobal.getPref('summaryAd'),
assert: 'user'
};
}).then(function() {
statusIndicator.info('Done');
}, function(e) {
statusIndicator.error(e);
var $srgLink = '<a target="_blank" href="/wiki/m:SRG">m:SRG</a>';
MorebitsGlobal.status.printUserText(header + reason, 'The comments you typed are provided below, in case you wish to manually post them under the existing report for this user at ' + $srgLink + ':');
});
break;
}
};
})(jQuery);
// </nowiki>