Aller au contenu

MediaWiki:Gadget-0xBlockMessage.js

Une page de Wikipédia, l'encyclopédie libre.
Ceci est une version archivée de cette page, en date du 24 juillet 2022 à 01:07 et modifiée en dernier par Od1n (discuter | contributions) (message d'erreur (et early return du script) en cas d'élément de markup n'étant plus trouvé, vu que le problème s'est produit récemment ; noter que cela implique de chercher les éléments lors de l'initialisation du script, et non plus dans l'event handler du submit). Elle peut contenir des erreurs, des inexactitudes ou des contenus vandalisés non présents dans la version actuelle.
Note : après avoir enregistré la page, vous devrez forcer le rechargement complet du cache de votre navigateur pour voir les changements.

Mozilla / Firefox / Konqueror / Safari : maintenez la touche Majuscule (Shift) en cliquant sur le bouton Actualiser (Reload) ou pressez Maj-Ctrl-R (Cmd-R sur Apple Mac) ;

Firefox (sur GNU/Linux) / Chrome / Internet Explorer / Opera : maintenez la touche Ctrl en cliquant sur le bouton Actualiser ou pressez Ctrl-F5.
/*
 * BlockMessage
 *
 * Permet d'ajouter un modèle notifiant le blocage d'un utilisateur en un clic,
 * une fois le blocage réussi.
 *
 * Auteur : [[User:0x010C]]
 * {{Projet:JavaScript/Script|BlockMessage}}
 */

// Customisation
var templatesList = {
	finite: [
		{
			label: "Bloqué",
			data: '{ "template": "Bloqué|$1|$2" }'
		}, {
			label: "Bloqué sans avertissement",
			data: '{ "template": "Bloqué sans avertissement|$1|$2" }'
		}, {
			label: "Insultes",
			data: '{ "template": "Insultes|$1|$2" }'
		}, {
			label: "IP partagée bloquée",
			data: '{ "template": "IP partagée bloquée|$1|$2" }'
		}, {
			label: "Vandale scolaire bloqué",
			data: '{ "template": "Vandale scolaire bloqué" }',
			'autoselect-time': '15 july 2018'
		}, {
			label: "Proxy",
			data: '{ "template": "Proxy|durée=$1|timestamp={{subst:'+'CURRENTTIMESTAMP}}", "default-subst": false }',
			'autoselect-reason': '[[Wikipédia:Pas de serveurs mandataires ouverts|Proxy ouvert]]'
		}, {
			label: "IP bloquée pour 3 jours",
			data: '{ "template": "Adresse IP bloquée pour trois jours|$3|$1|$2" }'
		},
	],
	infinite: [
		{
			label: "Compte bloqué indéfiniment",
			data: '{ "template": "Compte bloqué indéfiniment|$3", "default-clean": true }'
		}, {
			label: "Vandale bloqué indéfiniment",
			data: '{ "template": "Vandale bloqué indéfiniment", "default-clean": true }'
		}, {
			label: "Vandale bloqué indéfiniment sans avertissement",
			data: '{ "template": "Vandale bloqué indéfiniment sans avertissement", "default-clean": true }'
		}, {
			label: "Bot banni",
			data: '{ "template": "Bot banni" }'
		}, {
			label: "Utilisateur rémunéré bloqué",
			data: '{ "template": "Utilisateur rémunéré bloqué" }'
		},
	]
};

// I18n
var blockMessageMessages = {
	'en': {
		'blockmessage-default-header': 'Block user',
		'blockmessage-success-header': 'Block succeeded',
		'blockmessage-form-legend': 'Notify the user of the block',
		'blockmessage-username-label': 'Username',
		'blockmessage-template-label': 'Template',
		'blockmessage-expiry-label': 'Duration',
		'blockmessage-subst-label': 'Substitute the template',
		'blockmessage-clean-label': 'Clear the talk page before putting the template',
		'blockmessage-extra-label': 'Add a custom message under the template',
		'blockmessage-extraTextareaLabel': '(be careful, the signature is no longer automatically added)',
		'blockmessage-submit-label': 'Notify',
		'blockmessage-message-summary': 'Block',
		'blockmessage-message-tags': '0xBlockMessage',
		'blockmessage-section-title': 'Block',
		'blockmessage-successnotif': 'The message has been correctly added to the talk page.',
		'blockmessage-time-label': 'Duration',
		'blockmessage-unit-label': 'Unit',
		'blockmessage-hour': 'hour',
		'blockmessage-hours': 'hours',
		'blockmessage-day': 'day',
		'blockmessage-days': 'days',
		'blockmessage-week': 'week',
		'blockmessage-weeks': 'weeks',
		'blockmessage-month': 'month',
		'blockmessage-months': 'months',
		'blockmessage-year': 'year',
		'blockmessage-years': 'years',
		'blockmessage-markup-element-not-found': 'Gadget 0xBlockMessage: markup element not found',
	},
	'fr': {
		'blockmessage-default-header' : 'Bloquer l’utilisateur',
		'blockmessage-success-header' : 'Blocage réussi',
		'blockmessage-form-legend': 'Avertir du blocage',
		'blockmessage-username-label': 'Utilisateur',
		'blockmessage-template-label': 'Modèle',
		'blockmessage-expiry-label': 'Expiration',
		'blockmessage-subst-label': 'Substituer le modèle',
		'blockmessage-clean-label': 'Effacer la PdD avant de mettre le modèle',
		'blockmessage-extra-label': 'Rajouter un message sous le modèle',
		'blockmessage-extraTextareaLabel': '(attention, la signature n\'est plus apposée automatiquement)',
		'blockmessage-submit-label': 'Avertir',
		'blockmessage-message-summary': 'Blocage',
		'blockmessage-message-tags': '0xBlockMessage',
		'blockmessage-section-title': 'Blocage',
		'blockmessage-successnotif': 'La pose du message a réussi',
		'blockmessage-time-label': 'Durée',
		'blockmessage-unit-label': 'Unité',
		'blockmessage-hour': 'heure',
		'blockmessage-hours': 'heures',
		'blockmessage-day': 'jour',
		'blockmessage-days': 'jours',
		'blockmessage-week': 'semaine',
		'blockmessage-weeks': 'semaines',
		'blockmessage-month': 'mois',
		'blockmessage-months': 'mois',
		'blockmessage-year': 'année',
		'blockmessage-years': 'années',
		'blockmessage-markup-element-not-found': 'Gadget 0xBlockMessage : élément de markup non trouvé',
	}
};

mw.messages.set( blockMessageMessages[ 'en' ] );
var lang = mw.config.get( 'wgUserLanguage' );
if ( lang !== 'en' && lang in blockMessageMessages ) {
	mw.messages.set( blockMessageMessages[ lang ] );
}

var blockMessageUnits = [
	{ en: 'hour', data: mw.msg( 'blockmessage-hour' ), label: mw.msg( 'blockmessage-hour' ) },
	{ en: 'hours', data: mw.msg( 'blockmessage-hours' ), label: mw.msg( 'blockmessage-hours' ) },
	{ en: 'day', data: mw.msg( 'blockmessage-day' ), label: mw.msg( 'blockmessage-day' ) },
	{ en: 'days', data: mw.msg( 'blockmessage-days' ), label: mw.msg( 'blockmessage-days' ) },
	{ en: 'week', data: mw.msg( 'blockmessage-week' ), label: mw.msg( 'blockmessage-week' ) },
	{ en: 'weeks', data: mw.msg( 'blockmessage-weeks' ), label: mw.msg( 'blockmessage-weeks' ) },
	{ en: 'month', data: mw.msg( 'blockmessage-month' ), label: mw.msg( 'blockmessage-month' ) },
	{ en: 'months', data: mw.msg( 'blockmessage-months' ), label: mw.msg( 'blockmessage-months' ) },
	{ en: 'year', data: mw.msg( 'blockmessage-year' ), label: mw.msg( 'blockmessage-year' ) },
	{ en: 'years', data: mw.msg( 'blockmessage-years' ), label: mw.msg( 'blockmessage-years' ) }
];



// Load the script only on the Block special page
if ( mw.config.get( 'wgCanonicalNamespace' ) === 'Special' && mw.config.get( 'wgCanonicalSpecialPageName' ) === 'Block' ) {

	mw.loader.using( [ 'mediawiki.cookie', 'mediawiki.util', 'oojs-ui' ], function () {
		$( function ( $ ) {

			// On the Block page
			if ( $( '#firstHeading' ).html() === mw.msg( 'blockmessage-default-header' ) ) {
					var $expirySelect = $( '#mw-input-wpExpiry select' );
					var $expiryOther = $( 'input[name="wpExpiry-other"]' );
					var $reasonSelect = $( '#mw-input-wpReason select' );
					var $reasonOther = $( 'input[name="wpReason-other"]' );

				if (!$expirySelect.length || !$expiryOther.length || !$reasonSelect.length || !$reasonOther.length) {
					mw.notify( mw.msg( 'blockmessage-markup-element-not-found' ), { type: 'error', autoHide: false } );
					return;
				}

				$( 'form.mw-htmlform' ).submit( function ( event ) {
					if ( $expirySelect.val() === 'other' ) {
						mw.cookie.set( 'blockmessage-expiry', $expiryOther.val() );
					}
					else {
						mw.cookie.set( 'blockmessage-expiry', $expirySelect.val() );
					}

					if ( $reasonSelect.val() === 'other' ) {
						mw.cookie.set( 'blockmessage-reason', $reasonOther.val() );
					}
					else if ( $( 'input[name="wpReason-other"]' ).val() !== '' ) {
						mw.cookie.set( 'blockmessage-reason', $reasonSelect.val() + ' : ' + $reasonOther.val() );
					}
					else {
						mw.cookie.set( 'blockmessage-reason', $reasonSelect.val() );
					}
				} );
			}

			// When the user has successfully blocked someone.
			// wgRelevantUserName may be null for IP ranges.
			else if ( $( '#firstHeading' ).html() === mw.msg( 'blockmessage-success-header' ) &&
			          mw.cookie.get( 'blockmessage-expiry' ) !== null &&
			          mw.config.get( 'wgRelevantUserName' ) !== null ) {
				window.blockMessage = new BlockMessage( mw.config.get( 'wgRelevantUserName' ), mw.cookie.get( 'blockmessage-reason' ), mw.cookie.get( 'blockmessage-expiry' ) );
			}

		} );
	} );
}

/**
 * @class BlockMessage
 * @constructor
 * @private
 * @param {String} targetUser
 * @param {String} reason
 * @param {String} duration
 */
var BlockMessage = function (targetUser, reason, duration) {
	this.targetUser = targetUser;
	this.reason = reason;
	this.duration = duration;

	this.usernameInput;
	this.templateDropdownInput;
	this.expiryInput;
	this.substCheckboxInput;
	this.cleanCheckboxInput;
	this.extraCheckboxInput;
	this.extraTextarea;
	this.submitInput;

	this.expiryField;
	this.extraTextareaField;
	this.form;


	// Initialize the form
	this.createWidgets();
	this.addEventHandlers();
	this.initializeWidgets();

	// Add the form to the page once all is ready
	$( '#mw-content-text' ).append( this.form.$element );
};

/**
 * Create all the OOjs-ui widgets and organise them into a field layout
 */
BlockMessage.prototype.createWidgets = function () {
	this.usernameInput = new OO.ui.TextInputWidget( {
		name: 'username',
		disabled: 'disabled'
	} );
	this.templateDropdownInput = new OO.ui.DropdownInputWidget();
	this.expiryInput = new mw.widgets.SelectWithInputWidget( {
		or: false,
		dropdowninput: {
			label: mw.msg( 'blockmessage-unit-label' ),
			options: blockMessageUnits,
		},
		textinput: {
			placeholder: mw.msg( 'blockmessage-time-label' )
		}
	} );
	this.substCheckboxInput = new OO.ui.CheckboxInputWidget( {
		name: '',
		selected: true
	} );
	this.cleanCheckboxInput = new OO.ui.CheckboxInputWidget( {
		name: '',
		selected: false
	} );
	this.extraCheckboxInput = new OO.ui.CheckboxInputWidget( {
		name: '',
		selected: false
	} );
	this.extraTextarea = new OO.ui.MultilineTextInputWidget( {
		rows: 10,
		autosize: true,
	} );
	this.submitInput = new OO.ui.ButtonInputWidget( {
		type: 'submit',
		label: mw.msg( 'blockmessage-submit-label' ),
		flags: [ 'primary', 'destructive' ],
	} );

	this.expiryField = new OO.ui.FieldLayout( this.expiryInput, {
		align: 'top',
		label: mw.msg( 'blockmessage-expiry-label' )
	} );
	this.extraTextareaField = new OO.ui.FieldLayout( this.extraTextarea, {
		align: 'top',
		label: $( '<small>' ).text( mw.msg( 'blockmessage-extraTextareaLabel' ) )
	} );

	this.form = new OO.ui.FieldsetLayout( {
		id: 'demo-section-formLayout',
		label: mw.msg( 'blockmessage-form-legend' ),
		items: [
			new OO.ui.FieldLayout( this.usernameInput, {
				align: 'top',
				label: mw.msg( 'blockmessage-username-label' )
			} ),
			new OO.ui.FieldLayout( this.templateDropdownInput, {
				align: 'top',
				label: mw.msg( 'blockmessage-template-label' )
			} ),
			this.expiryField,
			new OO.ui.FieldLayout( this.substCheckboxInput, {
				align: 'inline',
				label: mw.msg( 'blockmessage-subst-label' )
			} ),
			new OO.ui.FieldLayout( this.cleanCheckboxInput, {
				align: 'inline',
				label: mw.msg( 'blockmessage-clean-label' )
			} ),
			new OO.ui.FieldLayout( this.extraCheckboxInput, {
				align: 'inline',
				label: mw.msg( 'blockmessage-extra-label' )
			} ),
			this.extraTextareaField,
			new OO.ui.FieldLayout( this.submitInput )
		]
	} );
};

/**
 * Add some handlers to the widgets to manage the post-submit stage
 * and to enhance the user experience
 */
BlockMessage.prototype.addEventHandlers = function () {
	var self = this;

	// Launch the postMessage method when the user submit the form
	this.submitInput.on( 'click', function () {
		self.submitInput.setDisabled(true);
		self.postMessage();
	} );

	// Auto (un)check the checkboxes when the user change the selected template
	this.templateDropdownInput.on( 'change', function (value) {
		value = JSON.parse(value);
		if ( value.hasOwnProperty( 'default-subst' ) ) {
			self.substCheckboxInput.setSelected( value[ 'default-subst' ] );
		}
		if ( value.hasOwnProperty( 'default-clean' ) ) {
			self.cleanCheckboxInput.setSelected( value[ 'default-clean' ] );
		}
	} );

	// Display or hide the extra textarea when the user (un)check the extra checkbox
	this.extraCheckboxInput.on( 'change', function ( checked ) {
		self.extraTextareaField.toggle( checked );
	} );
};

/**
 * Populate and adapt parameters from the widgets
 */
BlockMessage.prototype.initializeWidgets = function () {
	var templates;
	if ( this.duration === 'infinite' ) {
		// Hide the expiry field when the duration is infinite (it's irrelevant)
		this.expiryField.toggle( false );
		templates = templatesList.infinite;
	}
	else {
		templates = templatesList.finite;

		// Parse the expiry parameter and populate the expiration fields
		if ( this.duration !== null ) {
			var splitedDuration = this.duration.split( ' ' );
			if ( splitedDuration.length === 2 && !isNaN( splitedDuration[ 0 ] ) ) {
				for ( var i=0; i<blockMessageUnits.length; i++) {
					if ( splitedDuration[ 1 ] === blockMessageUnits[ i ].en ) {
						this.expiryInput.dropdowninput.setValue( blockMessageUnits[ i ].data );
						this.expiryInput.textinput.setValue( splitedDuration[ 0 ] );
						this.expiryField.toggle( false );
						break;
					}
				}
			}
		}
	}

	// Populate the template dropdown with the appropriate templates names
	this.templateDropdownInput.setOptions( templates );

	// Autoselect a template depending of the reasons or the duration
	for ( var i=0; i<templates.length; i++ ) {
		if ( 'autoselect-reason' in templates[ i ] ) {
			if ( templates[ i ][ 'autoselect-reason' ] === this.reason ) {
				this.templateDropdownInput.setValue( templates[ i ].data );
				break;
			}
		}
		if ( 'autoselect-duration' in templates[ i ] ) {
			if ( templates[ i ][ 'autoselect-duration' ] === this.duration ) {
				this.templateDropdownInput.setValue( templates[ i ].data );
				break;
			}
		}
	}

	// Fill the username field with the username of the blocked user
	this.usernameInput.setValue( this.targetUser );

	// By default, hide the extra textarea
	this.extraTextareaField.toggle( false );
};

/**
 * Use the datas set in the form to prepare and post a blocking notification
 * to the target user's talk page.
 * Called when the user click on the submit button.
 */
BlockMessage.prototype.postMessage = function () {
	var subst = '';
	if ( this.substCheckboxInput.isSelected() ) {
		subst = 'subst:';
	}
	var extra = ' ~~' + '~~';
	if ( this.extraCheckboxInput.isSelected() ) {
		extra = '\n\n' + this.extraTextarea.getValue();
	}

	// Prepare the template
	var template = JSON.parse( this.templateDropdownInput.getValue() ).template;
	template = template.replace( '$1', this.expiryInput.textinput.getValue() );
	template = template.replace( '$2', this.expiryInput.dropdowninput.getValue() );
	template = template.replace( '$3', this.reason );

	// Prepare the payload which will be send to the API
	var data = {
		action: 'edit',
		title: 'User talk:' + this.targetUser,
		text: '{{' + subst + template + '}}' + extra,
		summary: mw.msg( 'blockmessage-message-summary' ),
		tags: mw.msg( 'blockmessage-message-tags' ),
	};
	if ( ! this.cleanCheckboxInput.isSelected() ) {
		data.section = "new";
		data.sectiontitle = mw.msg( 'blockmessage-section-title' );
	}

	// Send the payload
	new mw.Api().postWithToken( 'csrf', data ).then( this.onMessagePosted.bind( this ) );
};

BlockMessage.prototype.onMessagePosted = function ( data ) {
	// Display a visual information to the admin to confirm that the talk page has been edited
	mw.notify( mw.msg( 'blockmessage-successnotif' ) );

	// Clean the cookies
	mw.cookie.set( 'blockmessage-expiry', null );
	mw.cookie.set( 'blockmessage-reason', null );

	// Redirect the admin to the target's talk page after a short delay
	var self = this;
	setTimeout( function () {
		document.location.href = mw.util.getUrl( 'User talk:' + self.targetUser + '#footer' );
	}, 750 );
};