MediaWiki:Gadget-PermissionOTRS.js
Jump to navigation
Jump to search
Note: After saving, you have to bypass your browser's cache to see the changes. Internet Explorer: press Ctrl-F5, Mozilla: hold down Shift while clicking Reload (or press Ctrl-Shift-R), Opera/Konqueror: press F5, Safari: hold down Shift Alt while clicking Reload, Chrome: hold down Shift while clicking Reload.
This user script seems to have a documentation page at MediaWiki: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 = '[[COM: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(
'Commons: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 [[Commons: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>