User:Technical 13/SandBox/UpdateMailingList.js

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.
/*<nowiki>
Mailing list member updating script
 
Testcases:
    [[User:Technical 13/SandBox/MLsand]]
 
    // Once above is stable
    [[Wikipedia:WikiProject Userboxes/Members]]
    [[Wikipedia:WikiProject Maine/members]]
    [[:Category:MassMessage delivery lists]]
*/
var pageid = mw.config.get( 'wgArticleId' );
//mlmInfo[ mw.config.get( 'wgPageName' ) ] = { blocked: false, extras: '', joined: false, lastactive: false, notarget: true, status: 'self', type: 'page' };
 
function getEditors() {
    console.log( 'Getting editors' );
    return new mw.Api().get( {
        action: 'query',
        pageids: pageid,
        prop: 'revisions',
        rvlimit: 'max',
        rvprop: [ 'timestamp', 'user' ],
        rawcontinue: ''
    } ).then( function( mlRevisions ) {
        var thisUser, mlmInfo = {};
        for ( var u in mlRevisions.query.pages[ pageid ].revisions ) {
            thisUser = mlRevisions.query.pages[ pageid ].revisions[ u ].user;
            mlmInfo[ thisUser ] = {    
                blocked: false,
                extras: '',
                groups: [],
                joined: new Date( mlRevisions.query.pages[ pageid ].revisions[ u ].timestamp ).getTime(),
                lastactive: false,
                notarget: false,
                status: 'edited',
                type: 'user'
            };
        }
 
        return mlmInfo;
    } );
}
 
function parseList( mlmInfo ) {
    console.log( 'Parsing list' );
    return new mw.Api().get( {
        action: 'query',
        pageids: pageid,
        prop: 'revisions',
        rvprop: 'content',
        rawcontinue: ''
    } ).then( function( mlContents ) {
        var mlPage = mlContents.query.pages[ pageid ].revisions[ 0 ][ '*' ] + '\n';
        var tArray = mlPage.match( /\{\{Mailing list member\|(.*?)\n/gi );
        $.each( tArray, function( index, template ) {
            var extras = template.replace( /\{\{Mailing list member\|(.*?)\}\}/i, '' ).replace( /[\r\n]/g, '' );
            if ( extras === undefined && extras === null ) {
                extras = '';
            }
            template = template.replace( /\{\{Mailing list member/i, '' ).replace( /\}\}/, '|' );
            var page = template.match( /\| *page *= *(.*?)\|/i );
            if ( page !== undefined && page !== null ) {
                page = page[ 1 ];
            }
            var user = template.match( /\| *user *= *(.*?)\|/i );
            if ( user !== undefined && user !== null ) {
                user = user[ 1 ];
            } else {
                user = mlmInfo[ user ].user;
            }
            var blocked = template.match( /\| *blocked *= *(.*?)\|/i );
            if ( blocked !== undefined && blocked !== null ) {
                blocked = new Date( blocked[ 1 ] ).getTime();
            } else {
                blocked = false;
            }
            var joined = template.match( /\| *joined *= *(.*?)\|/i );
            if ( joined !== undefined && joined !== null ) {
                joined = new Date( joined[ 1 ] ).getTime();
            } else {
                joined = false;
            }
            var lastactive = template.match( /\| *lastactive *= *(.*?)\|/i );
            if ( lastactive !== undefined && lastactive !== null ) {
                lastactive = new Date( lastactive[ 1 ] ).getTime();
            } else {
                lastactive = false;
            }
            var notarget = template.match( /\| *notarget *= *(.*?)\|/i );
            if ( notarget !== undefined && notarget !== null ) {
                notarget = notarget[ 1 ];
            } else {
                notarget = false;
            }
            if ( user !== undefined && user !== null && mlmInfo.hasOwnProperty( user ) ) {
                /* confirmed user */// Is a user that has edited the page and is still on the list
                if ( blocked !== undefined && blocked !== null && blocked < mlmInfo[ user ].blocked ) {
                    mlmInfo[ user ].blocked = blocked;
                }
                if ( extras !== undefined && extras !== null ) {
                    mlmInfo[ user ].extras = extras;
                }
                if ( joined !== undefined && joined !== null && joined < mlmInfo[ user ].joined ) {
                    mlmInfo[ user ].joined = joined;
                }
                if ( lastactive !== undefined && lastactive !== null && lastactive < mlmInfo[ user ].lastactive ) {
                    mlmInfo[ user ].lastactive = lastactive;
                }
                if ( notarget !== undefined && notarget !== null ) {
                    mlmInfo[ user ].notarget = notarget;
                }
                mlmInfo[ user ].status = 'confirmed';
            } else if ( page !== undefined && page !== null ) {
                /* listed page */// Is a page instead of a user.
                if ( extras !== undefined && extras !== null ) {
                    mlmInfo[ user ].extras = extras;
                }
                mlmInfo[ page ].status = 'listed';
                mlmInfo[ page ].type = 'page';
            } else {
                /* listed user */// Is a user that is listed but hasn't edited the page.
                mlmInfo[ user ] = {
                    blocked: blocked,
                    extras: extras,
                    groups: [],
                    joined: joined,
                    lastactive: lastactive,
                    notarget: notarget,
                    status: 'listed',
                    type: 'user'
                };
            }
        } );
 
        return mlmInfo;
    } );
}
 
function userInfo( mlmInfo ) {
    console.log( 'Updating user information' );
    var promises = [];
    var userList = [];
    $.each( mlmInfo, function( aUser ) {
        userList.push( aUser );
    }
    var offset = 0;
    while ( offset <= userList.length ) {
        $.each( mlmInfo.slice( offset, offset + 20 ), function ( i ) {
            thisUser = userList[ offset + i ];
            console.log( 'Updating information for: ' + thisUser );
            if ( mlmInfo[ thisUser ].type === 'user' ) {
                promises.push(
                    new mw.Api().get( {
                        action: 'query',
                        list: [ 'logevents', 'usercontribs', 'users' ],
                        leprop: 'timestamp',
                        ucprop: 'timestamp',
                        usprop: [ 'blockinfo', 'groups' ],
                        lelimit: 1,
                        uclimit: 1,
                        leuser: thisUser,
                        ucuser: thisUser,
                        ususers: thisUser,
                        rawcontinue: ''
                    } ).then( function( mlmUserInfo ) {
                        if ( mlmUserInfo.query.users[ 0 ].blockid ) {
                            var isBlockedExpiry = mlmUserInfo.query.users[ 0 ].blockexpiry;
                            if ( isBlockedExpiry === 'infinity' || new Date( isBlockedExpiry ) > Date.now() ) {
                                mlmInfo[ thisUser ].blocked = new Date( mlmUserInfo.query.users[ 0 ].blockedtimestamp ).getTime();// They're blocked
                            }
                        }
                        mlmInfo[ thisUser ].groups = mlmUserInfo.query.users[ 0 ].groups;
                        for ( var le in mlmUserInfo.query.logevents ) {
                            var lastLogged = new Date( mlmUserInfo.query.logevents[ le ].timestamp ).getTime();
                            if ( lastLogged > mlmInfo[ thisUser ].lastactive ) {
                                mlmInfo[ thisUser ].lastactive = lastLogged;// The last time they performed a [[Help:Log|logged]] action.
                            }
                        }
                        for ( var uc in mlmUserInfo.query.usercontribs ) {
                            var lastEdit = new Date( mlmUserInfo.query.usercontribs[ uc ].timestamp ).getTime();
                            if ( lastEdit > mlmInfo[ thisUser ].lastactive ) {
                                mlmInfo[ thisUser ].lastactive = lastEdit;// The last time they edited a page
                            }
                        }
                        if ( mlmUserInfo.query.users[ 0 ].invalid || $.inArray( 'user', mlmUserInfo.query.users[ 0 ].groups ) === -1 ) {
                            mlmInfo[ thisUser ].notarget = true;// They're not a user and can't get mass mailings.
                            mlmInfo[ thisUser ].type = 'IP';
                        }
                        if ( $.inArray( 'bot', mlmUserInfo.query.users[ 0 ].groups ) > -1 ) {
                            mlmInfo[ thisUser ].notarget = true;// They're a bot and don't want mass mailings.
                            mlmInfo[ thisUser ].type = 'bot';
                        }
                        return $.Deferred().resolve();
                    } )
                );
            } else if ( mlmInfo[ thisUser ].type === 'page' ) {
                if ( mlmInfo[ thisUser ].joined === false ) {
                    promises.push(
                        new mw.Api().get( {
                            action: 'query',
                            pageids: pageid,
                            prop: 'revisions',
                            rvprop: 'timestamp',
                            rvdir: 'newer',
                            rvlimit: 1,
                            rawcontinue: ''
                        } ).then( function( mlmPageInfo ) {
                            mlmInfo[ thisUser ].joined = new Date( mlmPageInfo.query.pages[ pageid ].revisions[ 0 ].timestamp );
                            return $.Deferred().resolve();
                        } )
                    );
                }
                promises.push(
                    new mw.Api().get( {
                        action: 'query',
                        pageids: pageid,
                        prop: 'revisions',
                        rvprop: 'timestamp',
                        rvlimit: 1,
                        rawcontinue: ''
                    } ).then( function( mlmPageInfo ) {
                        mlmInfo[ thisUser ].lastactive = new Date( mlmPageInfo.query.pages[ pageid ].revisions[ 0 ].timestamp );
                        return $.Deferred().resolve();
                    } )
                );
            } else {
                console.warn( 'Skipping %s because it is of type: %s', thisUser, mlmInfo[ thisUser ].type );
            }
        } );
        offset += 20;
    }
 
    return $.when.apply( $, promises ).then( function () {
        return mlmInfo;
    } );
}
 
getEditors().then( function ( mlmInfo ) {
    return parseList( mlmInfo );
} ).then( function ( mlmInfo ) {
    return userInfo( mlmInfo );
} ).done( function ( mlmInfo ) {
    /* show result */
    console.info( mlmInfo );
} );
//</nowiki>