User:Tanbiruzzaman/Gadget-PermissionOTRS.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:Tanbiruzzaman/Gadget-PermissionOTRS. |
/** PermissionOTRS.js
* @description: Adds VRTS permission template via API. Other templates such as {VRTS pending} will be removed.
* @revision: 23:07, 16 August 2018 (UTC)
* @source: https://commons.wikimedia.org/wiki/MediaWiki:Gadget-PermissionOTRS.js
* @license: under the terms of the MIT license
* @authors:
* Maintainer: [[User:Perhelion]]
* Created by Bryan Tong Minh
* Amended by [[:de:User:DerHexer]], [[User:Guandalug]], DieBuche, [[User:Steinsplitter]], [[User:Rillke]]
* Rewritten by Perhelion, Fordította: :hu:User:Bencemac
* Structured Data on Commons support added by [[User:Majavah]]
* @required modules: mediawiki.util, oojs-ui-core, oojs-ui-windows, mediawiki.api
* <nowiki>
*/
/* eslint indent:["error","tab",{"outerIIFEBody":0}] */
/* eslint no-underscore-dangle:0 */
/* global mediaWiki, jQuery, OO */
/* jshint curly:false, scripturl:true, forin:false */
( function ( $, mw ) {
'use strict';
var conf = mw.config.get( [
'wgCategories',
'wgIsArticle',
'wgGlobalGroups',
'wgNamespaceNumber',
'wgPageName',
// 'wgRestrictionEdit',
'wgUserGroups',
'wgUserLanguage',
'wgUserName',
'wgArticleId',
] ),
user = conf.wgUserName,
page = conf.wgPageName,
sLink = '[[WP:Volunteer Response Team|VRTS]] ',
oChangeTag = 'PermissionOTRS',
ticket,
content,
// timestamp,
reason = '',
deferred = null,
editform = null,
received = false,
ticketWikidataPropertyNumber = 'P6305',
i18n = {
de: {
apiErrorCode: 'Fehler bei der Verarbeitung der Anfrage.\n\t API-Fehlercode: %CODE%\n\n\tBitte versuche es erneut.',
confirmDR: 'Melde dies beim Löschantrag?',
digit: 'Ticket-ID (16-stellige Nummer):',
Done: 'Fertig!',
emptyResponse: 'Eine leere Antwort vom Server erhalten.',
// Error: 'Fehler!',
fail: 'fehlgeschlagen',
gotContent: 'Inhalt der Seite erhalten…',
// INVALIDID: 'INVALIDE ID',
invalidId: 'Es muss eine gültige 16-stellige Ticket-Nummer eingeben werden.',
noAuth: 'Du bist für diese Funktion nicht berechtigt!',
noFound: 'Keine passende Stelle zum Einfügen der Vorlage gefunden! Bitte von Hand hinzufügen.',
process: '…Anfrage zur Kennzeichnung mit Ticket#: %TICKET%',
Processing: 'Verarbeitung …',
reason: 'Gib eine Begründung?',
sameTicket: 'Gleiches Ticket bereits hinzugefügt.',
success: 'VRTS-Ticket erfolgreich eingefügt.'
},
hu: {
apiErrorCode: 'Hiba lépett fel a művelet végrehajtása során.\n\t API-hibakód:%CODE%\n\n\tKérlek, próbáld újra!',
digit: 'Ticket ID (16 jegyű szám):',
Done: 'Kész!',
emptyResponse: 'Üres válasz érkezett a szervertől.',
Error: 'Hiba!',
fail: 'hiba',
gotContent: 'Az oldal tartalmának betöltése…',
invalidId: 'Adj meg egy érvényes 16 számjegyű számot.',
noAuth: 'Nincs jogosultságod a művelet végrehajtásához!',
noFound: 'Nem található megfelelő hely a sablon beillesztésére. Írd be kézzel.',
process: 'Az összekapcsolás a(z) %TICKET% számú jeggyel elkezdődött',
Processing: 'Folyamatban…',
sameTicket: 'A jegy már szerepel az oldalon.',
success: 'VRTS jegy sikeresen hozzáadva.'
},
pl: {
apiErrorCode: 'Wysŧąpił błąd podczas dodawania szablonu z biletem VRTS.\n\t API-error-code: %CODE%\n\n\tProszę spróbować ponownie.',
confirmDR: 'Powiadamić dyskusję o kasowaniu pliku?',
digit: 'Numer biletu VRTS (16-cyfrowy):',
Done: 'Gotowe!',
emptyResponse: 'Otrzymano pustą odpowiedź z serwera.',
Error: 'Błąd!',
fail: 'błąd',
gotContent: 'Mam zawartość strony…',
INVALIDID: 'NIEPRAWIDŁOWY NUMER',
invalidId: 'Musisz podać poprawny 16-cyfrowy numer biletu.',
noAuth: 'Nie masz uprawnień do tej funkcji!',
noFound: 'Nie znaleziono odpowiedniego miejsca na dodanie szablonu! Dodaj ręcznie. ',
process: '…szablon z biletem VRTS Nr: %TICKET%',
Processing: 'Dodaję…',
reason: 'Podać powód?',
sameTicket: 'Ten sam bilet już dodano.',
sdcAdding: 'Dodaję deklarację SDC ...',
sdcAdded: 'Deklaracja SDC została dodana, kontynuuję z dodawaniem szablonu',
success: 'Bilet VRTS został pomyślnie wstawiony.'
},
vi: { // Translation by [[User:Tryvix1509]]
apiErrorCode: 'Có lỗi khi xử lý yêu cầu. Vui lòng thử lại.\n\t Mã lỗi API: %CODE%',
confirmDR: 'Đề nghị xóa tập tin này?',
digit: 'Nhập ID thẻ (gồm 16 chữ số):',
Done: 'Xong!',
emptyResponse: 'Máy chủ đã trả về phản hồi rỗng.',
Error: 'Lỗi!',
fail: 'thất bại',
gotContent: 'Đang lấy nội dung trang…',
INVALIDID: 'ID THẺ KHÔNG HỢP LỆ',
invalidId: 'Bạn phải nhập số thẻ hợp lệ có 16 chữ số.',
noAuth: 'Bạn không có quyền thực hiện tác vụ này!',
noFound: 'Không tìm thấy vị trí phù hợp để chèn bản mẫu! Xin hãy tự thêm vào thủ công. ',
process: '…đang yêu cầu gắn thẻ Ticket#: %TICKET%',
Processing: 'Đang xử lý…',
reason: 'Cung cấp lý do?',
sameTicket: 'Thẻ này đã được thêm vào rồi.',
sdcAdding: 'Đang thêm tuyên bố cho Dữ liệu có cấu trúc ...',
sdcAdded: 'Đã thêm tuyên bố cho Dữ liệu có cấu trúc, đang lưu trang',
success: 'Thẻ VRTS đã được chèn vào tập tin.'
},
apiErrorCode: 'There was an error processing your request.\n\t API-error-code: %CODE%\n\n\tPlease try again.',
confirmDR: 'Report this to the deletion request?',
digit: 'Ticket ID (16 digit number):',
Done: 'Done!',
emptyResponse: 'Got an empty response from the server.',
Error: 'Error!',
fail: 'fail',
gotContent: 'Got page contents…',
INVALIDID: 'INVALID ID',
invalidId: 'You must enter a valid 16-digit ticket number.',
noAuth: 'You are not authorized for this function!',
noFound: 'No suitable place found to insert the template! Please add by hand.',
process: '…request to tag with Ticket#: %TICKET%',
Processing: 'Processing…',
reason: 'Give a reason?',
sameTicket: 'Same ticket already added.',
sdcAdding: 'Adding SDC claim...',
sdcAdded: 'SDC claim saved, continuing with saving the page',
success: 'VRTS ticket successfully inserted.'
};
if ( conf.wgNamespaceNumber !== 6 || $.inArray( 'autoconfirmed', conf.wgUserGroups ) === -1 || !user ) {
return;
}
if ( !conf.wgIsArticle ) {
editform = $( '#wpTextbox1' );
}
function _apiFail( code, r ) {
if ( code === 'http' ) {
r = 'HTTP error: ' + r.textStatus;
} else if ( code === 'ok-but-empty' ) {
r = i18n.emptyResponse;
} else {
r = 'API ' + i18n.fail + ': ' + code;
}
mw.log.warn( r );
mw.notify( i18n.apiErrorCode.replace( '%CODE%', code ), {
title: i18n.Error,
autoHide: 0,
type: 'error'
} );
}
function doDoneMsg() {
mw.notify( i18n.success, {
title: i18n.Done
} ).done( function () {
// true if not edit-mode
if ( deferred ) { location.reload(); }
} );
}
function addHintOnDR( lastMatch ) {
mw.loader.using( 'user.options', function () {
var uSig = ( mw.user.options.get( 'fancysig' ) && mw.user.options.get( 'nickname' ).search( /^[ ']*\[\[/ ) ) ?
' ' : ' --',
DR = /subpage ?= ?([^|]+)\|/.exec( lastMatch );
DR = ( DR && ( DR = DR[ 1 ] ) ) || page;
new mw.Api().edit(
'WP:Deletion_requests/' + DR.replace( / /g, '_' ),
function ( revision ) {
var text = revision.content;
// if really open
if ( text && !/\{\{[Dd]elf\}\}\s*$/.test( text ) ) {
text += '\n* [[File:Permission logo 2021.svg|26px|link=|VRTS]] ' + ( received ?
'There is an VRTS email received for “' + page.replace( /_/g, ' ' ) + '” but not processed yet, [[ticket:' + ticket + ']].' :
'I have just accepted permission for “' + page.replace( /_/g, ' ' ) + '” under [[ticket:' + ticket + ']].' ); // and tagged it as such
return {
text: text + uSig + '~~~~\n', // nowiki
summary: 'VRTS ticket received',
watchlist: 'preferences',
assert: 'user',
notminor: 1
};
} else {
mw.notify( 'Deletion request already closed.', {
title: 'Notification failed ',
type: 'warn'
} );
return $.Deferred().fail();
}
} )
.done( function () {
mw.notify( 'Notification successfully added.', {
title: 'Notify on deletion request'
} ).done( function () {
doDoneMsg();
} );
} ).fail( _apiFail );
} );
}
function doneMsg() {
// Add message on possible DR
if ( /\{\{[Dd]elete[^}\n]*\}\}/.test( content ) ) {
var match = RegExp.lastMatch;
OO.ui.confirm( i18n.confirmDR ).done( function ( confirmed ) {
if ( confirmed ) {
addHintOnDR( match );
} else { doDoneMsg(); }
} );
} else { doDoneMsg(); }
}
function _getPage( VRTS ) {
if ( !editform ) {
mw.notify( VRTS.name + ': ' + i18n.process.replace( /%TICKET%/, ticket ), {
title: i18n.Processing
} );
new mw.Api().edit(
page,
function ( revision ) {
mw.notify( i18n.gotContent, {
title: i18n.Processing
} );
content = revision.content;
// timestamp = revision.timestamp;
deferred = $.Deferred();
VRTS();
return deferred.promise();
} ).done( doneMsg ).fail( _apiFail );
} else {
content = editform.val();
return VRTS();
}
}
function _prompt( text, VRTS ) {
var VRTSfield = $( '#field-vrts' ), // there is already a ticket
name = 'VRTS',
$select,
type = 'mw-message-box mw-message-box-error',
noprompt = false, // whether we expect input
title = ( VRTS && VRTS.name ) ? VRTS.name : name;
// try pre-fill the ticket
if ( VRTSfield.length ) {
ticket = VRTSfield.attr( 'title' ).replace( /[^\n]+(\d{16})$/, '$1' );
} else if ( editform && /\{\{permission[ _]received\|id=(\d{16})+[^}\n]*\}\}/i.test( editform.val() ) ) {
ticket = RegExp.$1;
} else if ( editform && /\{\{permission[ _]received\|year=\d{4}\|month=\w+\|day=\d{1,2}\|1=(\d{16})[^}\n]*\}\}/i.test( editform.val() ) ) {
ticket = RegExp.$1;
}
if ( !text ) {
if ( received ) {
$select = 1;
}
title = i18n.INVALIDID;
text = i18n.invalidId;
} else if ( text === 'FAIL' ) {
title = text;
text = i18n.noFound;
noprompt = 1;
} else {
type = '';
}
if ( type ) {
text = $( '<span>' )
.addClass( type )
.text( text );
} else if ( received ) {
// Reason checkbox
$select = 1;
}
mw.loader.using( [ 'oojs-ui-core', 'oojs-ui-windows' ], function () {
/* Code taken from oojs-ui-windows #OO-ui-method-prompt */
function OOuiPrompt( text, options ) {
var instance,
manager = OO.ui.getWindowManager(),
textInput = new OO.ui.TextInputWidget( ( options && options.textInput ) || {} ),
textField = new OO.ui.FieldLayout( textInput, {
align: 'top',
label: text
} ),
dropDown,
checkbox = options.textInput.checkbox,
fieldset = [ textField ];
if ( checkbox ) {
dropDown = new OO.ui.DropdownInputWidget( {
id: name + 'combo',
// label: '',
disabled: true,
options: [
{ data: 'a', label: 'processing' },
{ data: 'b', label: 'licence' },
{ data: 'c', label: 'email' }
]
} );
checkbox = new OO.ui.CheckboxInputWidget( {
id: name + 'reason'
} ).on( 'change', function () {
reason = dropDown.isDisabled();
dropDown.setDisabled( !reason );
// $select.toggle();
} );
checkbox = new OO.ui.FieldLayout( checkbox, { label: i18n.reason, align: 'inline' } );
$select = dropDown.$element;
fieldset.push( checkbox );
fieldset.push( dropDown );
}
fieldset = new OO.ui.FieldsetLayout( {/* label: 'Checkbox'*/} )
.addItems( fieldset );
instance = manager.openWindow( 'message', $.extend( {
title: textInput.title,
message: fieldset.$element
}, options ) );
instance.opened.then( function () {
textInput.on( 'enter', function () {
manager.getCurrentWindow().close( { action: 'accept' } );
} );
textInput.focus();
} );
return instance.closed.then( function ( data ) {
return data && data.action === 'accept' ? textInput.getValue() : null;
} );
}
if ( noprompt ) {
OO.ui.alert( text );
} else {
new OOuiPrompt( text, {
textInput: {
title: title,
maxLength: 23, // For possible pre-phrase "Ticket#"
validate: /^\s*(Ticket)?#?\d{16}\s*$/,
checkbox: !!$select,
value: ticket
}
} ).done( function ( result ) {
ticket = $.trim( result ).replace( /^(Ticket)?#?/, '' ); // clean up input
reason = ( reason && typeof $select === 'object' ) ? $select.find( 'option:selected' ).text() : '';
if ( ticket ) { // Check ticket validity
if ( /^\d{16}$/.test( ticket ) ) {
_getPage( VRTS );
} else { // Try again
_prompt( '', VRTS );
}
}
} );
}
} );
}
function _savePage( summary ) {
if ( deferred ) {
deferred.resolve( {
text: content,
summary: summary,
watchlist: 'preferences',
tags: oChangeTag,
notminor: 1
} );
} else { // In edit-mode
$( '#wpMinoredit' ).prop( 'checked', 0 );
editform.val( content );
$( '#wpSummary' ).val( function ( i, v ) {
return $.trim( v.replace( summary, '' ) + ' ' + summary );
} );
doneMsg();
}
}
function _cleanUp( text ) {
// ToDo: maybe here could be loaded another general cleanup module!?
return $.trim( text
.replace( /== ?Summary ?==/, '=={{int:filedesc}}==' )
.replace( /== ?Licensing ?==/, '=={{int:license-header}}==' )
.replace( /\{\{(Permission)[ _-](pending|received)[^}\n]*\}\}\s?/ig, '' )
.replace( /\{\{[Nn]o[ _](VRTS[ _])?permission[^}\n]*\}\}\s*/g, '\n' )
.replace( /<(!--|nowiki>)\s*\{\{([Pp]ermission[ _]?)?OTRS ?\| ?id= ?\d+\s*[^}\n]*\}\}\s*(--|<\/nowiki)>\s?/g, '' )
// Remove problem since tags (X-To-DR string)
.replace( /\{\{\s*[Nn]o[ _](source|permission|license)([ _]since)?\s*(\|[^}\n]+)?\}\}\s?/g, '' )
// Remove Copyvio (X-To-DR string)
.replace( /\{\{\s*(Copyviol?|Copyright(?!ed)|Copyrighted(?! free use)|Screenshot|Icon|Logo|Logo-Germany|(?:Non-free video |DVD )?Cover|Db-f9|db-copyvio|Vio(?:lation)?)\s*(\|[^\n]+|[^}\n]*)\}\}\s?/i, '' )
// Remove Speedy (X-To-DR string)
.replace( /\{\{\s*(Speedy(?:[ -]?delet(?:e|ion))?|Speedilydelete|Noncommercial|Nonderivative|löschen|db|spd|qd|Sdelete|SLA|Spdel|Ek|Destruir)\s*(\|[^\n]+|[^}\n]*)\}\}\s?/i, '' )
.replace( /\{\{\s*SD\s*(\|[^\n]+|[^}\n]*)\}\}\s?/, '' ) ); // Remove SD (not Sd)
}
function _addPermission( template, summary ) {
var text = _cleanUp( content ),
textBefore = text,
regP = /( )*\|\s*[Pp]ermission( )*=\s*([^\n]*\n)/,
regA = /( )*\|\s*[Aa]uthor( )*=\s*[^\n]*\n/g; // fallback position, if no permission parameter
if ( !regP.test( text ) ) {
if ( !regA.test( text ) ) {
return _prompt( 'FAIL' );
}
var l = regA.lastIndex,
s1 = RegExp.$1 || '', // leading whitespaces as indent?
s2 = ( RegExp.$2 ) ? ' ' : '', // whitespace on parameter?
sr = text.substr( l ).search( /^\s*(\||\}\})/m ); // try to got at template end
if ( sr >= 0 ) {
sr += l; // insert to the end of information template
text = text.substr( 0, sr ) + s1 + '|permission' + s2 + '=' + s2 + template + '\n' + text.substr( sr );
} else {
return _prompt( 'FAIL' );
}
} else {
if ( text.indexOf( template ) > 0 ) {
return mw.notify( i18n.sameTicket, {
title: 'VRTS ' + i18n.fail + '…',
type: 'warn'
} );
}
text = text.replace( regP, '$1|permission$2=$2' + template + '\n$3' );
}
if ( textBefore === text ) {
return _prompt( 'FAIL' );
}
content = text;
_savePage( sLink + summary );
}
var PermissionVRTS = function PermissionVRTS() {
mw.notify( i18n.sdcAdding, {
title: i18n.Processing
} );
var entityId = 'M' + conf.wgArticleId,
guidGenerator = new wikibase.utilities.ClaimGuidGenerator( entityId ),
guid = guidGenerator.newGuid(),
claim = JSON.stringify( {
type: 'statement',
id: guid,
rank: 'normal',
mainsnak: {
snaktype: 'value',
property: ticketWikidataPropertyNumber,
datatype: 'external-id',
datavalue: {
type: 'string',
value: ticket,
},
},
} );
new mw.Api().postWithEditToken( {
action: 'wbsetclaim',
id: entityId,
claim: claim,
summary: 'add [[COM:Volunteer Response Team|VRTS]] ticket number as an [[WP:Structured data|SDC]] claim',
assert: 'user',
tags: oChangeTag,
} )
.done( function () {
mw.notify( i18n.sdcAdded, {
title: i18n.Processing
} );
_addPermission( '{{PermissionTicket|id=' + ticket + '|user=' + user + '}}', 'permission added' );
})
.fail( _apiFail );
},
VRTSreceived = function VRTSreceived() {
_addPermission(
'{{Permission received|id=' + ticket +
'|year={{subst:' +
'#time:Y}}|month={{subst:' +
'#time:F}}|day={{subst:' +
'#time:j}}' + ( reason ? '|reason=' + reason : '' ) +
'|user=' + user + '}}',
'email received but not processed yet' );
};
function dialogVRTS( e, VRTS ) {
e.preventDefault();
// Merge languages
// TODO: could be improved with mw.language.getFallbackLanguages
$.extend( true, i18n, i18n[ conf.wgUserLanguage ] );
function chkuGrp( b ) {
if ( b ) {
_prompt( i18n.digit, VRTS );
} else {
mw.notify( i18n.noAuth, {
title: 'VRTS ' + i18n.fail + '!',
type: 'warn'
} );
}
}
mw.loader.using( [ 'mediawiki.api' ], function () {
if ( $.inArray( 'vrt-permissions', conf.wgGlobalGroups ) > -1 || $.inArray( 'sysop', conf.wgUserGroups ) > -1 ) {
chkuGrp( 1 );
} else { // Fallback?
new mw.Api().get( {
meta: 'globaluserinfo',
guiuser: user,
guiprop: 'groups'
} ).done( function ( r ) {
chkuGrp( ( $.inArray( 'vrt-permissions', r.query.globaluserinfo.groups ) > -1 ) );
} ).fail( function ( code, r ) {
_apiFail( code, r );
} );
}
} );
}
mw.loader.using( [ 'mediawiki.util', 'wikibase.utilities.ClaimGuidGenerator' ], function () {
var bReceive,
bConfirm; // booleans; add link only if needed
$.each( conf.wgCategories, function ( i, text ) {
if ( text && !( bReceive && bConfirm ) ) { // Check Cats
if ( /^Items with (ticket )?VRTS permission confirmed/.test( text ) ) {
bConfirm = bReceive = true;
} else if ( /^Permission received/.test( text ) ) {
bReceive = true;
}
}
} );
if ( !bConfirm ) {
bConfirm = [ $( mw.util.addPortletLink( 'p-tb', '#', 'Permission VRTS' ) )
.on( 'click', function ( e ) {
received = 0;
dialogVRTS( e, PermissionVRTS );
} ) ];
if ( !bReceive ) {
bConfirm[ 1 ] = $( mw.util.addPortletLink( 'p-tb', '#', 'VRTS received' ) )
.on( 'click', function ( e ) {
received = 1;
dialogVRTS( e, VRTSreceived );
} );
}
$.each( bConfirm, function ( i, link ) {
link.find( 'a' ).css( 'color', '#D82' );
} );
}
} );
}( jQuery, mediaWiki ) );
// EOF </nowiki>