yoohoo! hot sauce please

10:27, 7 September 2026 (UTC)

MediaWiki:Gadget-UserHighlighter.js

From 2swagg wiki
Revision as of 10:01, 7 September 2026 by JANNY (talk | contribs) (Created page with "→Markblocked and Highlight Usergroups: ( function ( $, mw ) { var mwConfig = mw.config.get( [ 'wgAction', 'wgArticlePath', 'wgDBname', 'wgNamespaceIds', 'wgScript', 'wgServer', 'wgUserLanguage' ] ); // Default fallback tooltip if none is defined var mbTooltip = window.mbTooltip || 'Blocked ($1) by $2: $3 ($4 ago)'; // Get all aliases for User: and Message_Wall: // NOTE: Namespace 3 (User_talk) has been removed so talk pages are not affected....")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigationJump to search

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.
/* Markblocked and Highlight Usergroups */

( function ( $, mw ) {

	var mwConfig = mw.config.get( [
		'wgAction',
		'wgArticlePath',
		'wgDBname',
		'wgNamespaceIds',
		'wgScript',
		'wgServer',
		'wgUserLanguage'
	] );

	// Default fallback tooltip if none is defined
	var mbTooltip = window.mbTooltip || 'Blocked ($1) by $2: $3 ($4 ago)';

	// Get all aliases for User: and Message_Wall:
	// NOTE: Namespace 3 (User_talk) has been removed so talk pages are not affected.
	var userNS = [];
	for ( var ns in mwConfig.wgNamespaceIds ) {
		if ( mwConfig.wgNamespaceIds[ ns ] === 2 || mwConfig.wgNamespaceIds[ ns ] === 1200 ) {
			userNS.push( mw.util.escapeRegExp(ns.replace( /_/g, ' ' )) + ':' );
		}
	}

	//RegExp for links
	var articleRX = new RegExp(
		'^(?:' + mwConfig.wgServer + ')?' +
		mwConfig.wgArticlePath.replace( '$1', '' ) + '([^?#]+)'
	);
	var scriptRX = new RegExp(
		'^(?:' + mwConfig.wgServer + ')?' +
		mwConfig.wgScript + '\\?title=([^#&]+)'
	);

	var userTitleRX, waitingCSS;

	//--------Init functions
	function init( specialContribs ) {
		userTitleRX = new RegExp( '^'
			+ '(' + userNS.join( '|' )
			+ '|' + specialContribs + '\\/|Special:Contributions\\/'
			+ ')'
			+ '([^\\/#]+)$', 'i' );

		// Added "a." prefix and "!important" to ensure it overrides standard wiki link colors
		mw.util.addCSS(
			'.mediawiki .user-blocked-partial {'  + ( window.mbPartialStyle || 'opacity: 1' ) + '}\n'
			+ '.mediawiki .user-blocked-temp {' + ( window.mbTempStyle || 'opacity: 0.7; text-decoration: line-through !important' ) + '}\n'
			+ '.mediawiki .user-blocked-indef {' + ( window.mbIndefStyle || 'opacity: 0.4; font-style: italic; text-decoration: line-through !important' ) + '}\n'
			+ '.mediawiki .user-blocked-tipbox {' + ( window.mbTipBoxStyle || 'font-size:85%; background:#FFFFF0; border:1px solid #FEA; padding:0 0.3em; color:#AAA' ) + '}\n'
		);

		waitingCSS = mw.util.addCSS( 'a.userlink {opacity:' + ( window.mbLoadingOpacity || 0.85 ) + '}' );
		waitingCSS.disabled = true;

		if ( window.mbNoAutoStart ) {
			$( function () {
				var portletLink = mw.util.addPortletLink( 'p-tb, .mytools', '#', 'Mark blocked users', 'ca-showblocks' );
				$( portletLink ).click( function( event ) {
					event.preventDefault();
					markBlocked();
				} );
			} );
		} else {
			markBlocked();
			mw.hook( 'wikipage.content' ).add( markBlocked );
		}

		window.ajaxCallAgain = window.ajaxCallAgain || [];
		window.ajaxCallAgain.push( markBlocked );
	}

	function initSpecialContribsString() {
		var promise = $.Deferred();
		var storageKey = 'MarkBlocked-specialcontribs_' + mwConfig.wgDBname;
		var specialContribs;
		try { specialContribs = localStorage.getItem( storageKey ); } catch ( ignore ) {}
		if ( specialContribs ) return promise.resolve( specialContribs );

		$.getJSON( mw.util.wikiScript( 'api' ) , {
			action: 'parse', format: 'json', prop: 'text',
			text: '<span class="contribs">[[Special:Contributions]]</span>',
			disablepp: '', maxage: 30 * 86400, smaxage: 30 * 86400
		} ).done( function ( data ) {
			var $parsed = $( data.parse.text['*'] );
			var specialContribs = $parsed.find( '.contribs > a' ).attr( 'title' );
			promise.resolve( specialContribs );
			try { localStorage.setItem( storageKey, specialContribs ); } catch ( ignore ) {}
		}).fail(function() {
			promise.resolve( 'Special:Contributions' ); // Fallback on failure
		});
		return promise;
	}

	//--------Main function
	function markBlocked( container ) {
		var contentLinks = ( container || mw.util.$content || $('#mw-content-text')).find( 'a' )
				.not( '.editsection > a, .mw-editsection > a' )
				.add( '#ca-nstab-user a, li[data-id="profile"] > a' );

		var userLinks = {};
		var url, rlUrl, ma, pgTitle, user;

		contentLinks.each( function( i, lnk ) {
			url = $( lnk ).attr( 'href' );
			rlUrl = $( lnk ).data( 'uncrawlableUrl' );
			if ( rlUrl ) url = atob( rlUrl );
			if ( !url || url.charAt( 0 ) !== '/' ) return;
			if ( $( lnk ).hasClass( 'userlink' ) ) return;
			
			if ( ma = articleRX.exec( url ) ) {
				pgTitle = ma[ 1 ];
			} else if ( ma = scriptRX.exec( url ) ) {
				pgTitle = ma[ 1 ];
			} else {
				return;
			}
			pgTitle = decodeURIComponent( pgTitle ).replace( /_/g, ' ' );
			user = userTitleRX.exec( pgTitle );
			if ( !user ) return;
			user = user[ 2 ];
			
			$( lnk ).addClass( 'userlink' );
			if ( !userLinks[ user ] ) userLinks[ user ] = [];
			userLinks[ user ].push (lnk );
		} );

		var users = [];
		for ( var u in userLinks ) users.push( u );
		if ( users.length === 0 ) return;

		var serverTime, apiRequests = 0;
		waitingCSS.disabled = false;
		
		while ( users.length > 0 ) {
			apiRequests++;
			var chunk = users.splice( 0, 50 ).join( '|' );
			$.post(
				mw.util.wikiScript( 'api' ) + '?format=json&action=query',
				{
					list: 'blocks|users',
					bklimit: 100,
					bkusers: chunk,
					bkprop: 'user|by|timestamp|expiry|reason|flags',
					ususers: chunk,
					usprop: 'groups'
				},
				markLinks
			);
		}

		//callback: receive data and mark links
		function markLinks( resp, status, xhr ) {
			serverTime = new Date( xhr.getResponseHeader('Date') );
			var list, blk, clss, blTime, tip, links, lnk, blPartial;
			
			if ( !resp || !resp.query ) return;
			
			// 1. Process user groups
			if ( resp.query.users ) {
				var groupHierarchy = ['bureaucrat', 'staff', 'bot', 'sysop', 'Helper', 'moderator'];
				for ( var j = 0; j < resp.query.users.length; j++ ) {
					var usr = resp.query.users[ j ];
					if ( !usr.groups ) continue;
					
					var appliedClass = '';
					for ( var g = 0; g < groupHierarchy.length; g++ ) {
						if ( usr.groups.indexOf( groupHierarchy[ g ] ) > -1 ) {
							appliedClass = 'user-group-' + groupHierarchy[ g ];
							break;
						}
					}
					
					if ( appliedClass ) {
						links = userLinks[ usr.name ];
						if ( links ) {
							for ( var k = 0; k < links.length; k++ ) {
								$( links[ k ] ).addClass( appliedClass );
							}
						}
					}
				}
			}

			// 2. Process blocks
			if ( resp.query.blocks ) {
				list = resp.query.blocks;
				for ( var i = 0; i < list.length; i++ ) {
					blk = list[ i ];
					blPartial = '';
					if ( /^in/.test( blk.expiry ) ) {
						clss = 'user-blocked-indef';
						blTime = blk.expiry;
					} else {
						clss = 'user-blocked-temp';
						blTime = inHours ( parseTS( blk.expiry ) - parseTS( blk.timestamp ) );
					}
					if ('partial' in blk) {
						clss = 'user-blocked-partial';
						blPartial = ' partial';
					} 
					tip = mbTooltip
						.replace( '$1', blTime )
						.replace( '$2', blk.by )
						.replace( '$3', blk.reason )
						.replace( '$4', inHours ( serverTime - parseTS( blk.timestamp ) ) );
					links = userLinks[ blk.user ];
					if ( links ) {
						for ( var k = 0; k < links.length; k++ ) {
							lnk = $( links[ k ] ).addClass( clss );
							if ( window.mbTipBox ) {
								$( '<span class=user-blocked-tipbox>#</span>' ).attr( 'title', tip ).insertBefore( lnk );
							} else {
								lnk.attr( 'title', (lnk.attr( 'title' ) || '') + '; ' + tip );
							}
						}
					}
				}
			}

			if ( --apiRequests === 0 ) {
				waitingCSS.disabled = true;
				$( '#ca-showblocks' ).remove();
			}
		}
	}

	//--------AUX functions
	function parseTS( ts ) {
		var m = ts.replace( /\D/g, '' ).match( /(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/ );
		return new Date ( Date.UTC( m[ 1 ], m[ 2 ] - 1, m[ 3 ], m[ 4 ], m[ 5 ], m[ 6 ] ) );
	}

	function inHours( ms ) {
		var mm = Math.floor( ms / 60000 );
		if ( !mm ) return Math.floor( ms / 1000 ) + 's';
		var hh = Math.floor( mm / 60 );
		mm = mm % 60;
		var dd = Math.floor( hh / 24 );
		hh = hh % 24;
		if ( dd ) return dd + ( dd < 10 ? '.' + zz( hh ) : '' ) + 'd';
		return hh + ':' + zz( mm );
	}

	function zz( v ) {
		if ( v <= 9 ) v = '0' + v;
		return v;
	}

	//start on some pages
	switch ( mwConfig.wgAction ) {
		case 'edit':
		case 'submit':
		case 'delete':
			break;
		default:
			$.when(
				initSpecialContribsString(),
				mw.loader.using( 'mediawiki.util' )
			).done( init );
	}

}( jQuery, mediaWiki ) );