Board Thread:Support Requests - Getting Technical/@comment-10688548-20130202074623/@comment-5209426-20130203130846

I've had a go at this problem and came up a script for it. I make no assertions of quality about this code; it was experimental to begin with and I changed approaches 3 times which left everything rather messy but I'm pretty sure it works.

Notes: The script creates a giant table at. When you open the page, it will download the interwiki map and display the mapped entries in the table. When you hit the "start scan" button, it will proceed to download a page from every possible wiki [This is rate limited but it can still chew up 100% of 1 CPU core, and a crap ton of RAM. Chrome is recommended for this since Firefox has trouble letting RAM go]. The results are color coded: red=no wiki in that language exists, blue=a wiki exists but is not connected, green=a wiki is already connected. When the scan completes, a "hide irrelevant rows" button is added that will remove all the no-wiki-exists rows.

'''This must be placed in global.js to work. The script needs to load on every wiki in order to connect and communicate across domain names.'''

'		);

// Prefill table (function {		var content = '';		for (var x in langCodes) {			if (langCodes.hasOwnProperty(x)) {				content +=					' ' +						' ' + langCodes[x] + ' ' +						' ' + x + ' ' +						'??? ' +					' ';			}		}		$scanTable.find('tbody').append(content);	});

$content.append($topNotice, $scanTable);

// Change state of table rows when info is known function mark(langCode, mode, msg) { var $x = $scanTable.find('td[data-langcode="' + langCode + '"]') .css(styles[mode]) .html(msg || defaultMsg[mode]); if (mode === 'found' || mode === 'connected') { $x.attr('data-done', 'true'); }	}

// Look up the interwiki link table new mw.Api.get({		meta: 'siteinfo',		siprop: 'interwikimap',		sifilteriw: 'local'	}, {		ok: function(json) {			// Update the table			json = json.query.interwikimap;			for (var i = 0, l = json.length ; i < l ; ++i) {				if (!json[i].language) { continue; }				mark(json[i].prefix, 'connected', 'Connected');			}

// Enable scan $topNotice .find('button').click(function(ev) {					ev.preventDefault;					$topNotice.slideUp('fast');					runScan;				}).end .slideDown('fast'); },		err: function(textCode) { $topNotice .text('Could not access interwikimap for this wiki. Error: ' + textCode) .addClass('error').removeClass('confirm') .slideDown('fast'); }	});

// Create one iframe per sub-domain and wait for the site to load. // If it times out then it probably doesn't exist. // We rate limit this to avoid total insanity. function runScan { var map = {}; $(window).on('message.langscan', function(ev) {			var e = ev.originalEvent;			if (typeof(e.data) === 'string') {				var m = e.data.split('#');				if (m.length === 2 && map.hasOwnProperty(m[0])) {					map[m[0]](window.parseInt(m[1], 10));					delete map[m[0]];					ev.stopImmediatePropagation;				}			}		});

var jobs = $scanTable.find('td[data-langcode]').not('[data-done]').toArray, jobCount = (jobs.length < MAX_JOBS ? jobs.length : MAX_JOBS); for (var i = 0 ; i < jobCount ; ++i) { startJob(jobs.shift); }

function startJob(e) { var code = e.getAttribute('data-langcode'); mark(code, 'checking'); var $f = $('').prop({				src: '//' + code + '.' + window.location.host + '/wiki/LangScanLanding'			}).appendTo('body'); var timeout = window.setTimeout(function {				mark(code, 'failed', 'Timed out');				e.setAttribute('data-done', 'true');				$f.remove;				decJobCount;			}, IFRAME_TIMEOUT); $f.load(function {				map[code] = function(valid) {					window.clearTimeout(timeout);					if (valid) {						mark(code, 'found', 'Exists but not connected');					}					else {						mark(code, 'failed');					}					$f.remove;					decJobCount;				};				this.contentWindow.postMessage('langscan ' + code, '*');			}); }		function decJobCount { if (jobs.length) { startJob(jobs.shift); }			else if (--jobCount === 0) { // Last job cleans up				$('iframe.langscan-frame').remove; $topNotice .html(' Scan Completed. Hide Irrelevant Rows ') .slideDown('fast') .find('button').click(function(ev) {						ev.preventDefault;						$scanTable.find('td[data-langcode]').not('[data-done]').parent.toggle;					}); $(window).off('message.langscan'); }		}	}

})(window, jQuery, mediaWiki); }); }); }

// Enable cross-origin access between the scan page and the a designated landing page on the wiki // NOTE: Landing page must NOT be a Special page as those have X-FRAME-OPTIONS: DENY which blocks //	loading them inside IFRAMEs. The landing page is not visibly altered by what we are doing to //	it so it doesn't matter if it exists. switch(mediaWiki.config.get('wgPageName')) { case 'LangScanLanding': case 'Community_Central:Not_a_valid_Wikia': jQuery(window).on('message.langscan', function(ev) {		'use strict';		var e = ev.originalEvent;		if (typeof(e.data) === 'string' && e.data.substr(0, 8) === 'langscan') {			e.source.postMessage(e.data.substr(9) + '#' + (mediaWiki.config.get('wgDBname') !== 'wikia' ? 1 : 0), e.origin);			ev.stopImmediatePropagation;		}	}); }

You may need to be careful with this; I think Wikia's servers might have anti-DoS functions that don't like the scan very much. I kept getting logged out while testing which breaks the scan (since it needs to be loaded on the target wiki as well as the scan page to work). I reduced the  from 10 to 1 but you may be able to get away with 2 or 3 to speed it up a little.

Test pages:

Once you've added it to your global.js, try these to see if it works: