User:AntiCompositeNumber/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:AntiCompositeNumber/PermissionOTRS. |
/** PermissionOTRS.js
* @description: Adds OTRS permission template via API. Other templates such as {OTRS 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
* @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 c = mw.config.get( [
'wgCategories',
'wgIsArticle',
'wgGlobalGroups',
'wgNamespaceNumber',
'wgPageName',
// 'wgRestrictionEdit',
'wgUserGroups',
'wgUserLanguage',
'wgUserName'
] ),
user = c.wgUserName,
page = c.wgPageName,
sLink = '[[WP:OTRS|OTRS]] ',
oChangeTag = 'PermissionOTRS',
ticket,
content,
// timestamp,
reason = '',
deferred = null,
editform = null,
received = false,
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: 'OTRS-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: 'OTRS jegy sikeresen hozzáadva.'
},
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.',
success: 'OTRS ticket successfully inserted.'
};
if ( c.wgNamespaceNumber !== 6 || $.inArray( 'autoconfirmed', c.wgUserGroups ) === -1 || !user ) {
return;
}
if ( !c.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( ' ', '_' ),
function ( revision ) {
var text = revision.content;
// if really open
if ( text && !/\{\{[Dd]elf\}\}\s*$/.test( text ) ) {
text += '\n* [[File:OTRS modern logo.svg|26px|link=|OTRS]] ' + ( received ?
'There is an OTRS email received for “' + page + '” but not processed yet, [[ticket:' + ticket + ']].' :
'I have just accepted permission for “' + page + '” under [[ticket:' + ticket + ']].' ); // and tagged it as such
return {
text: text + uSig + '~~~~\n', // nowiki
summary: 'OTRS 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( OTRS ) {
if ( !editform ) {
mw.notify( OTRS.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();
OTRS();
return deferred.promise();
} ).done( doneMsg ).fail( _apiFail );
} else {
content = editform.val();
return OTRS();
}
}
function _prompt( text, OTRS ) {
var OTRSfield = $( '#field-otrs' ), // there is already a ticket
name = 'OTRS',
$select,
type = 'errorbox',
noprompt = false, // whether we expect input
title = ( OTRS && OTRS.name ) ? OTRS.name : name;
// try pre-fill the ticket
if ( OTRSfield.length ) {
ticket = OTRSfield.attr( 'title' ).replace( /[^\n]+(\d{16})$/, '$1' );
} else if ( editform && /\{\{otrs[ _]received\|id=(\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( OTRS );
} else { // Try again
_prompt( '', OTRS );
}
}
} );
}
} );
}
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( /\{\{OTRS[ _-](pending|received)[^}\n]*\}\}\s?/ig, '' )
.replace( /\{\{[Nn]o[ _](OTRS[ _])?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)?|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: 'OTRS ' + 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 PermissionOTRS = function PermissionOTRS() {
_addPermission( '{{PermissionOTRS|id=' + ticket + '|user=' + user + '}}',
'permission added' );
},
OTRSreceived = function OTRSreceived() {
_addPermission(
'{{OTRS 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 dialogOTRS( e, OTRS ) {
e.preventDefault();
// Merge languages
// TODO: could be improved with mw.language.getFallbackLanguages
$.extend( true, i18n, i18n[ c.wgUserLanguage ] );
function chkuGrp( b ) {
if ( b ) {
_prompt( i18n.digit, OTRS );
} else {
mw.notify( i18n.noAuth, {
title: 'OTRS ' + i18n.fail + '!',
type: 'warn'
} );
}
}
mw.loader.using( [ 'mediawiki.api' ], function () {
if ( $.inArray( 'otrs-member', c.wgGlobalGroups ) > -1 || $.inArray( 'sysop', c.wgUserGroups ) > -1 ) {
chkuGrp( 1 );
} else { // Fallback?
new mw.Api().get( {
meta: 'globaluserinfo',
guiuser: user,
guiprop: 'groups'
} ).done( function ( r ) {
chkuGrp( ( $.inArray( 'otrs-member', r.query.globaluserinfo.groups ) > -1 ) );
} ).fail( function ( code, r ) {
_apiFail( code, r );
} );
}
} );
}
mw.loader.using( 'mediawiki.util', function () {
var bReceive,
bConfirm; // booleans; add link only if needed
$.each( c.wgCategories, function ( i, text ) {
if ( text && !( bReceive && bConfirm ) ) { // Check Cats
if ( /^Items with (ticket )?OTRS permission confirmed/.test( text ) ) {
bConfirm = bReceive = true;
} else if ( /^OTRS received/.test( text ) ) {
bReceive = true;
}
}
} );
if ( !bConfirm ) {
bConfirm = [ $( mw.util.addPortletLink( 'p-tb', '#', 'Permission OTRS' ) )
.on( 'click', function ( e ) {
received = 0;
dialogOTRS( e, PermissionOTRS );
} ) ];
if ( !bReceive ) {
bConfirm[ 1 ] = $( mw.util.addPortletLink( 'p-tb', '#', 'OTRS received' ) )
.on( 'click', function ( e ) {
received = 1;
dialogOTRS( e, OTRSreceived );
} );
}
$.each( bConfirm, function ( i, link ) {
link.find( 'a' ).css( 'color', '#D82' );
} );
}
} );
}( jQuery, mediaWiki ) );
// EOF </nowiki>