User:Dentonius/scripts/GlobalRecentChanges.js

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)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
"use strict";
/* global mw, $ */

/**
 * GlobalRecentChanges
 * 
 * description: retrieves recent changes from multiple wikis
 * 
 * installation:
 *  If your wiki is not meta, insert the following in your common.js (e.g. edit User:MyUsername/common.js)
 *   importScript('meta:User:Dentonius/scripts/GlobalRecentChanges.js');
 * 
 *  If your wiki is meta, use the deprecated loader:
 *   mw.loader.load('//meta.wikimedia.org/w/index.php?title=User:Dentonius/scripts/GlobalRecentChanges.js&action=raw&ctype=text/javascript');
 * 
 * usage:
 *  On your page, place the following markup: 
 *    <div class="global-recent-changes"
 *           data-limit="100"
 *           data-wiktionary="en|de|ro|es|fr|ru|nl|it|el"
 *           data-rcnamespace="2|3|4|5">
 *    </div>
 * 
 * attributes:
 *  'data-limit' is a number from 1 to 500 and refers to the number of changes to retrieve from each server
 *  'data-wiktionary' contains the language identifier of the servers to check. (en = en.wiktionary.org)
 *  'data-rcnamespace' contains the namespace identifiers to check (see https://www.mediawiki.org/wiki/API:RecentChanges#API_documentation)
 * 
 */

window.GlobalRecentChanges = {};

window.GlobalRecentChanges.fetcher = function(globalrc)
{
    if (globalrc.queueIndex < globalrc.queue.length)
    {
        let queueIndex = globalrc.queueIndex;
        let elementIndex = globalrc.elementIndex;
        let params = globalrc.params;
        let source = globalrc.queue[queueIndex].source;
        let subdomain = globalrc.queue[queueIndex].subdomain;
        let PARTIAL_URL = "." + source + ".org/w/api.php?origin=*";
        Object.keys(params).forEach(function(key) {PARTIAL_URL += "&" + key + "=" + params[key];});
            
        let url = 'https://' + subdomain + PARTIAL_URL;
        console.log('[GlobalRecentChanges] elementIndex = ' + elementIndex + '; #' + (queueIndex+1) + ' of ' + globalrc.queue.length + ' ; fetching  ' + url);
        
        fetch(url)
            .then(function(response) {return response.json();})
            .then(function(response)
            {
                let recentchanges = response.query.recentchanges;
                for (let i = 0; i < recentchanges.length; ++i)
                {
                    if (recentchanges[i].parsedcomment !== undefined)
                        recentchanges[i].parsedcomment = recentchanges[i].parsedcomment.replace('href=\"/wiki', 'href=\"https://' + subdomain + '.' + source + '.org/wiki');
                    
                    recentchanges[i].source = source;
                    recentchanges[i].subdomain = subdomain;
                    recentchanges[i].url = 'https://' + subdomain + '.' + source + '.org/wiki/' + recentchanges[i].title;
                    recentchanges[i].urlDiff = 'https://' + subdomain + '.' + source + '.org/w/index.php?title=' + recentchanges[i].title + '&curid=' + 
                        recentchanges[i].pageid + '&diff=' + recentchanges[i].revid + '&oldid=' + recentchanges[i].old_revid;
                    recentchanges[i].urlUser = 'https://' + subdomain + '.' + source + '.org/wiki/User:' + recentchanges[i].user;
                }
                
                globalrc.recentchanges = globalrc.recentchanges.concat(recentchanges);
                globalrc.queueIndex++;
                window.GlobalRecentChanges.fetcher(globalrc);
                return;
            })
            .catch(function(error) {console.log(error);});
        return;
    }
    
    let recentchanges = globalrc.recentchanges;
    recentchanges.sort((a,b) => (a.timestamp > b.timestamp) ? 1 : ((b.timestamp > a.timestamp) ? -1 : 0));
    recentchanges.reverse();
    
    let buf = '<table>';
    let trBgA = '#fff';
    let trBgB = '#ddd';
    let trBg = trBgA;
    for (let i = 0; i < recentchanges.length; ++i)
    {
        buf += '<tr style="background-color: ' + trBg + ';">' + 
            '<td>' + recentchanges[i].timestamp  + ' &middot; ' +
            '<a href="' + recentchanges[i].urlDiff + '">diff</a> &middot; ' +
            '[' + recentchanges[i].subdomain + '.' + recentchanges[i].source + '] &middot; ' +
            '<a href="' + recentchanges[i].urlUser + '">' + recentchanges[i].user + '</a> &middot; ' +
            '<a href="' + recentchanges[i].url +  '">'+ recentchanges[i].title + '</a> &middot; ' + 
            recentchanges[i].parsedcomment + ' (' + recentchanges[i].type + ')</td>' +
            '</tr>';
        trBg = (trBg == trBgA) ? trBgB : trBgA;
    }
    buf += '</table>';
    
    $('.global-recent-changes:eq(' + globalrc.elementIndex + ' )').html(buf);
    console.log(globalrc);
    setTimeout(function() { window.GlobalRecentChanges.main(); }, 30000);
};

window.GlobalRecentChanges.main = function ()
{
    if (!$('.global-recent-changes').length)
    {
        console.log('[GlobalRecentChanges] global-recent-changes container not found.');
        return;
    }
    
    let containers = $('.global-recent-changes');
    if (containers === undefined)
    {
        console.log('[GlobalRecentChanges] could not retrieve the global-recent-changes container(s) using jQuery.');
        return;
    }
    
    containers.each(function(elementIndex)
    {
        let e = $(this);
        if (e === undefined)
        {
            console.log('[GlobalRecentChanges] global-recent-changes[' + elementIndex + '] is undefined.');
            return;
        }
        
        let limit = e.attr('data-limit');
        let wikimedia = e.attr('data-wikimedia');
        let wikipedia = e.attr('data-wikipedia');
        let wiktionary = e.attr('data-wiktionary');
        let rcnamespace = e.attr('data-rcnamespace');
        let params =
            {
                action: "query",
                list: "recentchanges",
                rcprop: "timestamp|title|ids|sizes|flags|user|parsedcomment|comment",
                rclimit: limit,
                rcnamespace: rcnamespace,
                format: "json"
            };
        
        if (limit === undefined)
            limit = 0;
        if (wikimedia === undefined)
            wikimedia = '';
        if (wikipedia === undefined)
            wikipedia = '';
        if (wiktionary === undefined)
            wiktionary = '';
        if (rcnamespace === undefined)
            rcnamespace = '';
        
        if (limit <= 0)
        {
            console.log('[GlobalRecentChanges] please set the data-limit attribute tag in your global-recent-changes container with a positive number.');
            return;
        }
        
        wikimedia = wikimedia.split("|");
        wikipedia = wikipedia.split("|");
        wiktionary = wiktionary.split("|");
        
        let globalrc = [[]];
        globalrc.elementIndex = elementIndex;
        globalrc.params = params;
        globalrc.queue = [];
        globalrc.queueIndex = 0;
        globalrc.recentchanges = [];
        
        if (wikimedia[0].length > 0)
            for (let i = 0; i < wikimedia.length; ++i)
            {
                globalrc.queue[globalrc.queue.length] = {source: 'wikimedia', subdomain: wikimedia[i]};
            }
        if (wikipedia[0].length > 0)
            for (let i = 0; i < wikipedia.length; ++i)
            {
                globalrc.queue[globalrc.queue.length] = {source: 'wikipedia', subdomain: wikipedia[i]};
            }
        if (wiktionary[0].length > 0)
            for (let i = 0; i < wiktionary.length; ++i)
            {
                globalrc.queue[globalrc.queue.length] = {source: 'wiktionary', subdomain: wiktionary[i]};
            }
        
        window.GlobalRecentChanges.fetcher(globalrc);
        
    });
};

if (mw.config.get('wgAction') == "view")
	$(window.GlobalRecentChanges.main);