User:Novem Linguae/Scripts/DetectG4G5.js

//

/*

- Displays an alert if an article may be a CSD G4 (previous AFD) or CSD G5 (created by a sockpuppet)

- Useful for new page patrolling

- Only runs on pages that have not been marked as reviewed

  • /

// TODO: Code review. Is there a way to reduce the # of API queries?

class DetectG4G5 {

async execute() {

if ( !this.shouldRunOnThisPage() ) {

return;

}

const title = mw.config.get( 'wgPageName' ); // includes namespace, underscores instead of spaces

const pageID = mw.config.get( 'wgArticleId' );

if ( await this.isReviewed( pageID ) ) {

return;

}

if ( await this.afdExists( title ) && !await this.hasAFDTemplate( title ) ) {

const href = mw.config.get( 'wgArticlePath' ).replace( '$1', 'Wikipedia:Articles_for_deletion/' + title );

this.displayWarning( `CSD G4: There is an AFD page for this article. It may qualify for CSD G4.` );

}

const pageCreator = await this.getPageCreator( title );

if ( await this.isBlocked( pageCreator ) ) {

this.displayWarning( 'CSD G5: The creator of this page is blocked. This article may qualify for CSD G5.' );

}

if ( await this.isGloballyLocked( pageCreator ) ) {

this.displayWarning( 'CSD G5: The creator of this page is globally locked. This article may qualify for CSD G5.' );

}

}

async getWikicode( title ) {

if ( !mw.config.get( 'wgCurRevisionId' ) ) {

return '';

} // if page is deleted, return blank

let wikicode = '';

title = encodeURIComponent( title );

await $.ajax( {

url: 'https://en.wikipedia.org/w/api.php?action=parse&page=' + title + '&prop=wikitext&formatversion=2&format=json',

success: function ( result ) {

wikicode = result.parse.wikitext;

},

dataType: 'json',

async: false

} );

return wikicode;

}

async hasAFDTemplate( title ) {

const wikicode = await this.getWikicode( title );

return wikicode.indexOf( '{{Article for deletion' ) !== -1;

}

displayWarning( html ) {

$( '#contentSub' ).before( `

${ html }
` );

}

/**

* @param {number} pageID The page ID number. A positive number with no commas.

*/

async isReviewed( pageID ) {

const api = new mw.Api();

const response = await api.get( {

action: 'query',

format: 'json',

formatversion: '2',

prop: 'isreviewed',

pageids: pageID

} );

return response.query.pages[ 0 ].isreviewed;

}

async afdExists( title ) {

title = 'Wikipedia:Articles_for_deletion/' + title;

return await this.pageExists( title );

}

async pageExists( title ) {

const api = new mw.Api();

const response = await api.get( {

action: 'query',

format: 'json',

prop: 'revisions',

titles: title

} );

const exists = typeof response.query.pages[ '-1' ] === 'undefined';

return exists;

}

async isBlocked( username ) {

const api = new mw.Api();

const response = await api.get( {

action: 'query',

format: 'json',

list: 'users',

usprop: 'blockinfo',

ususers: username

} );

const isBlocked = typeof response.query.users[ 0 ].blockid !== 'undefined';

return isBlocked;

}

async isGloballyLocked( username ) {

const api = new mw.Api();

const response = await api.get( {

action: 'query',

list: 'globalallusers',

agulimit: '1',

agufrom: username,

aguto: username,

aguprop: 'lockinfo'

} );

const isLocked = response.query.globalallusers.length !== 0 && response.query.globalallusers[ 0 ].locked === '';

return isLocked;

}

getFirstValueInObject( obj ) {

return obj[ Object.keys( obj )[ 0 ] ];

}

async getPageCreator( title ) {

const api = new mw.Api();

const response = await api.get( {

action: 'query',

format: 'json',

prop: 'revisions',

titles: title,

rvlimit: '1',

rvdir: 'newer'

} );

const page = this.getFirstValueInObject( response.query.pages );

const pageCreator = page.revisions[ 0 ].user;

return pageCreator;

}

shouldRunOnThisPage() {

// don't run when not viewing articles

const action = mw.config.get( 'wgAction' );

if ( action !== 'view' ) {

return false;

}

// don't run when viewing diffs

const isDiff = mw.config.get( 'wgDiffNewId' );

if ( isDiff ) {

return false;

}

const isDeletedPage = ( !mw.config.get( 'wgCurRevisionId' ) );

if ( isDeletedPage ) {

return false;

}

// Only run in mainspace

const namespace = mw.config.get( 'wgNamespaceNumber' );

const title = mw.config.get( 'wgPageName' ); // includes namespace, underscores instead of spaces

if ( namespace !== 0 && title !== 'User:Novem_Linguae/sandbox' ) {

return false;

}

return true;

}

}

$( async () => {

await mw.loader.using( [ 'mediawiki.api' ], async () => {

await ( new DetectG4G5() ).execute();

} );

} );

//