Skip to content

Instantly share code, notes, and snippets.

@he7d3r
Last active August 29, 2015 14:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save he7d3r/f503e056f77fd0fd1a90 to your computer and use it in GitHub Desktop.
Save he7d3r/f503e056f77fd0fd1a90 to your computer and use it in GitHub Desktop.
WMGrep
// Based on https://meta.wikimedia.org/wiki/User:Krinkle/Tools/Global_SUL.js?oldid=10130488
/**
* This script provides an extra Special-page action called "WMGrep" which
* allows searching over all WMF wikis.
* After enabling the script, the tool is accessible from [[Special:BlankPage/wmgrep]].
*
* @source meta.wikimedia.org/wiki/User:Krinkle/Tools/Global_SUL
* @revision 4 (2014-10-08)
* @stats [[File:Krinkle_Global_SUL.js]]
*/
(function ($, mw) {
/**
* Iterate over all SiteMatrix wikis.
* @source www.mediawiki.org/wiki/User:Krinkle/Snippets/Iterate_SiteMatrix_in_JavaScript
* @revision 5 (2012-01-29)
* @example
* <code>
* var it = new mw.siteMatrix.Iterator({
* centralApiPath: mw.util.wikiScript('api'),
* // iterator {Iterator}
* // wikiObj {Object}: contains 'url', 'dbname' and maybe 'private'
* // iterationNr {Number}: starting at 0
* // listLength {Number}: length of list iteration array
* onIteration: function (iterator, wikiObj, iterationNr, listLength) {
* iterator.next();
* },
* onComplete: function (iterator, wikiObj, listLength) {
*
* }
* });
* it.start();
* </code>
*
* @param options {Object}
* - centralApiPath string: Path to api of a wiki that has the SiteMatrix installed
* - onIteration function: callback for action on each wiki
*/
if (mw.siteMatrix === undefined) {
mw.siteMatrix = {};
}
mw.siteMatrix.Iterator = function Iterate(options) {
var i, current, list, instance = this;
if (!options.centralApiPath || !options.onIteration) {
throw new Error('Invalid arguments');
}
if (!(this instanceof mw.siteMatrix.Iterator)) {
throw new TypeError('Illegal function call');
}
instance.start = function start() {
if (i !== undefined) {
throw new Error('Cannot start twice');
}
$.getJSON(options.centralApiPath + '?format=json&action=sitematrix&callback=?', function (data) {
i = 0;
list = [];
if (!data || !data.sitematrix) {
return;
}
$.each(data.sitematrix, function (key, value) {
var group, wi;
if (key === 'count') return;
group = key === 'specials' ? value : value.site;
if ($.isArray(group) && group.length) {
for (wi = 0; wi < group.length; wi += 1) {
// Only public wikis
if (group[wi]/*reserved_word*/['private'] === undefined && group[wi].closed === undefined && group[wi].fishbowl === undefined) {
list.push(group[wi]);
}
}
}
});
instance.next();
});
};
instance.next = function next() {
if (i < list.length) {
current = list[i];
options.onIteration(instance, current, i, list.length);
i += 1;
} else {
options.onComplete(instance, current, list.length);
}
};
return instance;
};
function initWmGrep() {
var $content, $fieldset, $subtitle, $table,
$status, $btnStart, $progress, $done, $log,
searchTerm;
$content = $('#bodyContent').empty();
$fieldset = $('<fieldset>');
$subtitle = $('<div id="contentSub"></div>');
$table = $(
'<table class="wikitable" style="width: 100%;"><tbody>'
+ '<tr><th>Status</th><th>Progress</th></tr>'
+ '<tr>'
+ '<td id="mw-wmgrep-status" style="width: 80%;">Ready for action! <button id="mw-wmgrep-start">Start</button></td>'
+ '<td style="vertical-align: top;"><span id="mw-wmgrep-progress">0%</span>'
+ '<span id="mw-wmgrep-done" style="float: right;"></span>'
+ '</td>'
+ '</tr>'
+ '<tr>'
+ '<td colspan="2" id="mw-wmgrep-log" style="padding-top: 1em;"><ul></ul></td>'
+ '</tr></tbody></table>'
);
$status = $table.find('#mw-wmgrep-status');
$btnStart = $table.find('#mw-wmgrep-start');
$log = $table.find('#mw-wmgrep-log > ul');
$progress = $table.find('#mw-wmgrep-progress');
$done = $table.find('#mw-wmgrep-done');
function doUpdate(msg, iterationNr, listLength) {
$status.text(msg);
$log.prepend('<li>' + new Date().toString().replace(/^\w+ /, '').replace(/:[^:]+$/, '') + ': ' + mw.html.escape(msg) + '</li>');
if (iterationNr && listLength) {
$progress.text((Math.round(((iterationNr) / listLength) * 100 * 10) / 10) + '%');
$done.text('(' + iterationNr + '/' + listLength + ' wikis)');
}
}
// function getGlobalAccountInfo(ok, err) {
// $.ajax({
// url: mw.util.wikiScript('api'),
// dataType: 'json',
// data: {
// format: 'json',
// action: 'query',
// meta: 'globaluserinfo',
// guiuser: mw.user.getName(),
// guiprop: 'merged|unattached'
// },
// success: function (data) {
// if (data && data.query && data.query.globaluserinfo) {
// ok(data.query.globaluserinfo);
// } else {
// err();
// }
// },
// error: err
// });
// }
// Build front-end
$('#firstHeading').text('WMGrep');
document.title = 'WMGrep - ' + mw.config.get('wgSiteName');
$fieldset
.text('Check all public Wikimedia wikis for pages containing a search term.')
.prepend($('<legend>').text('Search WMF wikis'))
.append($table);
// Bind events
$btnStart.click(function (e) {
var iterator, found = [];
searchTerm = prompt( 'Search for:', 'wikiGetlink' );
if (!searchTerm) {
return;
}
$(this).remove();
doUpdate('Initializing...');
iterator = new mw.siteMatrix.Iterator({
centralApiPath: mw.util.wikiScript('api'),
onIteration: function (instance, wikiObj, iterationNr, listLength) {
var url, hostname;
// All WMF wikis support https, but canonical is still 'http'
// convert API absolute urls to relative urls so that
// users of this gadget can be on either http or https and it works
url = wikiObj.url.replace(/^https?:/, '');
hostname = url.replace(/^\/\/?/, '');
doUpdate(hostname + ': searching...', iterationNr, listLength);
$.ajax({
url: wikiObj.url + mw.util.wikiScript('api'),
dataType: 'jsonp',
data: {
format: 'json',
action: 'query',
list: 'search',
srsearch: searchTerm,
srnamespace: 8,
srwhat: 'text',
srinfo: 'totalhits|suggestion',
srprop: 'size|wordcount|timestamp|snippet|titlesnippet'+
'|redirecttitle|redirectsnippet|sectiontitle'+
'|sectionsnippet|isfilematch|categorysnippet'
}
})
.done(function (data) {
if (data && data.query && data.query.search) {
$.each(data.query.search, function (i, obj) {
var url = 'https://' + hostname + '/wiki/' + obj.title;
found.push( url );
doUpdate( url );
// <code>obj.snippet</code>
});
}
instance.next();
})
.fail( instance.next );
},
onComplete: function (instance, wikiObj, listLength) {
doUpdate('Finished.', listLength, listLength);
$status.html('Found ' + found.length + ' results.');
if (found.length > 0) {
$status.append('<ul><li>' + found.join('</li><li>') + '</li></ul>');
}
}
});
found = [];
doUpdate('Loading wiki SiteMatrix...');
iterator.start();
});
// Output
$content.append($subtitle, $fieldset);
}
// Enqueue init
if (mw.config.get('wgCanonicalSpecialPageName') === 'Blankpage' && mw.config.get('wgTitle').indexOf('/wmgrep') > 2) {
mw.loader.using('mediawiki.util', initWmGrep);
}
}(jQuery, mediaWiki));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment