Jump to content

User:FlightTime/Strike-blocked.js

From Wikipedia, the free encyclopedia
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
//If you add this script to your skin.js, it will mark all linked blocked users with a strikethrough, and mark all linked indefinitely blocked users with italics and a strikethrough.
//
// Installation Method 1:
// Add the following line to your skin.js
// importScript('User:FlightTime/Mark-blocked.js'); // Linkback: [[User:FlightTime/Mark-blocked.js]]
// 
// Installation Method 2:
// Just copy and paste the un-commented part of this page
//

function markBlocked( container ) {
	var ipv6Regex = /^((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\3)::|:\b|$))|(?!\2\3)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})$/i;

	// Collect all the links in the page's content
	var contentLinks = $( container ).find( 'a' );

	var mbTooltip =  window.mbTooltip || '; blocked ($1) by $2: $3 ($4 ago)';

	// Get all aliases for user: & user_talk:
	var userNS = [];
	for ( var ns in mw.config.get( 'wgNamespaceIds' ) ) {
		if ( mw.config.get( 'wgNamespaceIds' )[ns] == 2 || mw.config.get( 'wgNamespaceIds' )[ns] == 3 ) {
			userNS.push( mw.util.escapeRegExp(ns.replace( /_/g, ' ' )) + ':' );
		}
	}

	// Let wikis that are importing this script specify the local alias of Special:Contributions
	if ( window.markblocked_contributions === undefined ) {
		window.markblocked_contributions = 'Special:Contributions';
	}
	// RegExp for all titles that are  User:| User_talk: | Special:Contributions/ (for userscripts)
	var userTitleRX = new RegExp( '^(' + userNS.join( '|' ) + '|' + window.markblocked_contributions + '\\/)+([^\\/#]+)$', 'i' );

	// RegExp for links
	// articleRX also matches external links in order to support the noping template
	var articleRX = new RegExp( mw.config.get( 'wgArticlePath' ).replace('$1', '') + '([^#]+)' );
	var scriptRX =  new RegExp( '^' + mw.config.get( 'wgScript' ) + '\\?title=([^#&]+)' );

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


	// Find all "user" links and save them in userLinks : { 'users': [<link1>, <link2>, ...], 'user2': [<link3>, <link3>, ...], ... }
	contentLinks.each( function( i, lnk ) {
		if( $( lnk ).hasClass("mw-changeslist-date") || $( lnk ).parent("span").hasClass("mw-history-undo") || $(lnk).parent("span").hasClass("mw-rollback-link") )
		{
			return;
		}
		url = $( lnk ).attr( 'href' );
		if ( !url ) {
			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];
		if( ipv6Regex.test(user) ) user = user.toUpperCase();
		$( lnk ).addClass( 'userlink' );
		if ( !userLinks[user] ) {
			userLinks[user] = [];
		}
		userLinks[user].push (lnk );
	} );


	// Convert users into array
	var users = [];
	for ( var u in userLinks ) {
		users.push( u );
	}
	if ( users.length === 0 ) {
		return;
	}

	// API request
	var serverTime, apiRequests = 0;
	container.addClass( 'markblocked-loading' );
	while ( users.length > 0 ) {
		apiRequests++;
		$.post( 
			mw.util.wikiScript( 'api' ) + '?format=json&action=query',
			{
				list: 'blocks',
				bklimit: 100,
				bkusers: users.splice( 0, 50 ).join( '|' ),
				bkprop: 'user|by|timestamp|expiry|reason|restrictions'
				// no need for 'id|flags'
			},
			markLinks
		);
	}

	return; // the end


	// Callback: receive data and mark links
	function markLinks( resp, status, xhr ) {

		serverTime = new Date( xhr.getResponseHeader('Date') );
		var list, blk, tip, links, lnk;
		if ( !resp || !( list = resp.query ) || !( list = list.blocks ) ) {
			return;
		}

		for ( var i = 0; i < list.length; i++ ) {
			blk = list[i];
			var partial = blk.restrictions && !Array.isArray(blk.restrictions); //Partial block
			if ( /^in/.test( blk.expiry ) ) {
				clss = partial ? 'user-blocked-partial' : 'user-blocked-indef';
				blTime = blk.expiry;
			} else {
				clss = partial ? 'user-blocked-partial' : 'user-blocked-temp';
				blTime = inHours ( parseTS( blk.expiry ) - parseTS( blk.timestamp ) );
			}
			tip = mbTooltip;
			if (partial) {
				tip = tip.replace( 'blocked', 'partially blocked' );
			}
			tip = tip.replace( '$1', blTime )
				.replace( '$2', blk.by )
				.replace( '$3', blk.reason )
				.replace( '$4', inHours ( serverTime - parseTS( blk.timestamp ) ) );
			links = userLinks[blk.user];
			for ( var k = 0; links && k < links.length; k++ ) {
				lnk = $( links[k] );
				lnk = lnk.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 ) { // last response
			container.removeClass( 'markblocked-loading' );
			$( '#ca-showblocks' ).parent().remove(); // remove added portlet link
		}

	}


	// --------AUX functions

	// 20081226220605  or  2008-01-26T06:34:19Z   -> date
	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 ) { // milliseconds -> "2:30" or 5,06d or 21d
		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 ) { // 6 -> '06'
		if ( v <= 9 ) {
			v = '0' + v;
		}
		return v;
	}
}// -- end of main function

// Start on some pages
switch ( mw.config.get( 'wgAction' ) ) {
	case 'edit':
	case 'submit':
		break;
	default: // 'view', 'history', 'purge', ...
		var maybeAutostart = $.Deferred();
		if ( window.mbNoAutoStart ) {
			var portletLink = mw.util.addPortletLink( 'p-cactions', '', 'XX', 'ca-showblocks' );
			$( portletLink ).click( function ( e ) {
				e.preventDefault();
				maybeAutostart.resolve();
			} );
		} else {
			maybeAutostart.resolve();
		}

		$.when( $.ready, mw.loader.using( 'mediawiki.util' ), maybeAutostart ).then( function() {
			var firstTime = true;

			mw.hook( 'wikipage.content' ).add( function ( container ) {
				// On the first call after initial page load, container is mw.util.$content

				// Used to limit mainspace activity to just the diff definitions
				if ( mw.config.get( 'wgAction' ) === 'view' && mw.config.get( 'wgNamespaceNumber' ) === 0 ) {
					container = container.find( '.diff-title' );
				}

				if ( firstTime ) {
					firstTime = false;

					// On page load, also update the namespace tab
					container = container.add( '#ca-nstab-user' );

					mw.util.addCSS('\
						.markblocked-loading a.userlink {opacity:' + ( window.mbLoadingOpacity || 0.85 ) + '}\
						a.user-blocked-temp {'   + ( window.mbTempStyle || 'opacity: 0.7; text-decoration: line-through' ) + '}\
						a.user-blocked-indef {'  + ( window.mbIndefStyle || 'opacity: 0.4; font-style: italic; text-decoration: line-through' ) + '}\
						a.user-blocked-partial {'  + ( window.mbPartialStyle || 'text-decoration: underline; text-decoration-style: dotted' ) + '}\
						.user-blocked-tipbox {' + ( window.mbTipBoxStyle || 'font-size:smaller; background:#FFFFF0; border:1px solid #FEA; padding:0 0.3em; color:#AAA' ) + '}\
					');
				}

				markBlocked( container );
			} );
		} );
}