User:Flewis/twinklearv.js

// If TwinkleConfig aint exist. if( typeof( TwinkleConfig ) == 'undefined' ) { TwinkleConfig = {}; }

/** TwinkleConfig.summaryAd (string) If ad should be added or not to summary, default TWINKLE */ if( typeof( TwinkleConfig.summaryAd ) == 'undefined' ) { TwinkleConfig.summaryAd = " using TW"; }

/** TwinkleConfig.markAIVReportAsMinor (boolean) Defines if a reports to AIV should be marked as minor, if false, default is applied as per preference. */ if( typeof( TwinkleConfig.markAIVReportAsMinor ) == 'undefined' ) { TwinkleConfig.markAIVReportAsMinor = true; }

/** TwinkleConfig.confirmUsernameToAIV (boolean) (deprecated) Defines if a username reports to AIV should be confirmed before sent. */ if( typeof( TwinkleConfig.confirmUsernameToAIV ) == 'undefined' ) { TwinkleConfig.confirmUsernameToAIV = true; }

/** TwinkleConfig.toolboxButtons (string) If id defined in this array, the button of the action is located inthe toolbox instead of in the actions bar. */ if( typeof( TwinkleConfig.toolboxButtons ) == 'undefined' ) { TwinkleConfig.toolboxButtons = []; }

function num2order( num ) { switch( num ) { case 1: return ''; case 2: return '2nd'; case 3: return '3rd'; default: return num + 'th'; } }

$( twinklearv ); function twinklearv{ var username;

if ( wgNamespaceNumber == 3 || wgNamespaceNumber == 2 || ( wgNamespaceNumber == -1 && wgTitle == "Contributions" )){

// If we are on the contributions page, need to parse some then if( wgNamespaceNumber == -1 && wgTitle == "Contributions" ) { username = document.evaluate( 'substring-after(//div[@id="contentSub"]//a[@title="Special:Log"][last]/@href, "user=")', document, null, XPathResult.STRING_TYPE, null).stringValue; } else { username = wgTitle.split( '/' )[0].replace( /\"/, "\\\""); // only first part before any slashes }

if( !username ) { // Something is fishy, there was no user? lets about everything throw "given username was " + username + " and thus makes no sense."; }

var name = isIPAddress( username ) ? 'Report IP' : 'Report'; var title = isIPAddress( username ) ? 'Report IP to Administators' : 'Report user to Administrators'; if (twinkleConfigExists) {			mw.util.addPortletLink( 'p-cactions', "javascript:twinklearv.callback(\"" + username + "\")", "arv", "tw-arv", name, title ); }		else {			mw.util.addPortletLink('p-cactions', 'javascript:alert("Your account is too new to use Twinkle.");', 'arv', 'tw-arv', name, title); }	} }

twinklearv.callback = function twinklearvCallback( uid ) { if( uid == wgUserName ){ alert( 'You don\'t want to report yourself, do you?' ); return; }

var Window = new SimpleWindow( 600, 400 ); Window.setTitle( "Advance Reporting and Vetting" ); //Backronym

var form = new QuickForm( twinklearv.callback.evaluate ); var categories = form.append( {			type: 'select',			name: 'category',			label: 'Select wanted type of report: ',			event: twinklearv.callback.change_category		} ); categories.append( {			type: 'option',			label: 'Vandalism',			value: 'aiv'		} ); categories.append( {			type: 'option',			label: 'Username',			value: 'username'		} ); categories.append( {			type: 'option',			label: 'Sockpuppeter',			value: 'sock'		} );

form.append( {			type: 'field',			label:'Work area',			name: 'work_area'		} ); form.append( {			type: 'hidden',			name: 'uid',			value: uid		} ); var result = form.render; Window.setContent( result ); Window.display;

// We must init the var evt = document.createEvent( "Event" ); evt.initEvent( 'change', true, true ); result.category.dispatchEvent( evt );

}

twinklearv.callback.change_category = function twinklearvCallbackChangeCategory(e) { var value = e.target.value; var root = e.target.form; var old_area; for( var i = 0; i < root.childNodes.length; ++i ) { var node = root.childNodes[i]; if( 			node instanceof Element &&			node.getAttribute( 'name' ) == 'work_area' 		) { old_area = node; break; }	}	var work_area = null;

switch( value ) { default: case 'aiv': work_area = new QuickForm.element( { 				type: 'field',				label: 'Report user for vandalism',				name: 'work_area'			} ); work_area.append( {				type: 'input',				name: 'page',				label: 'Primary linked page: ',				tooltip: 'Leave blank for no linked page in report',				value: QueryString.exists( 'vanarticle' ) ? QueryString.get( 'vanarticle' ) : ,				event: function(e) {					var value = e.target.value;					var root = e.target.form;					if( value ==  ) {						root.badid.disabled = root.goodid.disabled = true;					} else {						root.badid.disabled = false;						root.goodid.disabled = root.badid.value == '';					}				}			} ); work_area.append( {				type: 'input',				name: 'badid',				label: 'Revision ID for target page when vandalised: ',				tooltip: 'Leave blank for no diff link',				value: QueryString.exists( 'vanarticlerevid' ) ? QueryString.get( 'vanarticlerevid' ) : ,				disabled: !QueryString.exists( 'vanarticle' ),				event: function(e) {					var value = e.target.value;					var root = e.target.form;					root.goodid.disabled = value == ;				}			} ); work_area.append( {				type: 'input',				name: 'goodid',				label: 'Last good revision ID before vandalism of target page: ',				tooltip: 'Leave blank for diff link to previous revision',				value: QueryString.exists( 'vanarticlegoodrevid' ) ? QueryString.get( 'vanarticlegoodrevid' ) : '',				disabled: !QueryString.exists( 'vanarticle' ) || QueryString.exists( 'vanarticlerevid' )			} ); work_area.append( {				type: 'checkbox',				name: 'arvtype',				list: [					{ 						label: 'Vandalism after final warning given',						value: 'final'					},					{ 						label: 'Vandalism after recent release of block',						value: 'postblock'					},					{ 						label: 'Evidently vandalism only account',						value: 'vandalonly',						disabled: isIPAddress( root.uid.value )					},					{ 						label: 'Account is evidently a spambot or a compromised account',						value: 'spambot'					}				]			} ); work_area.append( {				type: 'textarea',				name: 'reason',				label: 'Comment: '			} ); work_area.append( { type:'submit' } ); work_area = work_area.render; old_area.parentNode.replaceChild( work_area, old_area ); break; case 'username': work_area = new QuickForm.element( { 				type: 'field',				label: 'Report username violation',				name: 'work_area'			} ); var types = work_area.append( {				type: 'field',				label: 'Type of violation',				tooltip: 'A valid report must include at least one of following types'			} );

types.append ( { 				type:'header', 				label:'Confusing usernames',				tooltip: 'Confusing usernames that make it unduly difficult to identify users by their username'			} ); types.append( {				type: 'checkbox',				name: 'arvtype',				list: [					{ 						label: 'Confusing username',						value: 'confusing',						tooltip: 'Confusing usernames make it unnecessarily difficult to identify contributors'					},					{						label: 'Misleading username',						value: 'misleading',						tooltip: 'Misleading usernames imply relevant, misleading things about the user, such as falsely conveying authority or impersonating another user.'					},					{ 						label: 'Promotional username',						value: 'promotional',						tooltip: 'Promotional usernames are used to promote a group or company on Wikipedia.'					},					{ 						label: 'Offensive username',						value: 'offensive',						tooltip: 'Offensive usernames make harmonious editing difficult or impossible.'					},					{ 						label: 'Disruptive username',						value: 'disruptive',						tooltip: 'Disruptive usernames that disrupt or misuse Wikipedia, or imply an intent to do so' }				]			} );		work_area.append( { type: 'textarea', name: 'reason', label: 'Comment:' } );		work_area.append( { type:'submit' } );		work_area = work_area.render;		old_area.parentNode.replaceChild( work_area, old_area );		break;

case 'sock': work_area = new QuickForm.element( { 				type: 'field',				label: 'Report suspected sockpuppeter',				name: 'work_area'			} ); work_area.append(			{				type: 'dyninput',				name: 'sockpuppet',				label: 'Sockpuppets',				sublabel: 'Sock: ',				tooltip: 'The username of the sockpuppet without the User:-prefix',				min: 2			}		); work_area.append( {				type: 'textarea',				label: 'Evidence:',				name: 'evidence'			} ); work_area.append( { type:'submit' } ); work_area = work_area.render; old_area.parentNode.replaceChild( work_area, old_area ); break; } }

twinklearv.callbacks = { aiv: function( self ) { uid = self.params.uid; reason = self.params.reason; var form = self.responseXML.getElementById('editform');

if( !form ) { self.statelem.error( 'Failed to retrieve edit form.' ); return; }		var text = form.wpTextbox1.value;

var re = new RegExp( "\\{\\{\\s*(?:(?:[Ii][Pp])?[Vv]andal|[Uu]serlinks)\\s*\\|\\s*(?:1=)?\\s*" + RegExp.escape( uid, true ) + "\\s*\\}\\}" );

var myArr; if( ( myArr = re.exec( text ) ) ) { self.statelem.info( 'Report already present, will not add a new one' ); return; }		self.statelem.status( 'Adding new report...' ); var postData = { 'wpMinoredit': TwinkleConfig.markAIVReportAsMinor ? '' : form.wpMinoredit.checked ? '' : undefined, 'wpWatchthis': form.wpWatchthis.checked ? '' : undefined, 'wpStarttime': form.wpStarttime.value, 'wpEdittime': form.wpEdittime.value, 'wpAutoSummary': form.wpAutoSummary.value, 'wpEditToken': form.wpEditToken.value, 'wpSummary': 'Reporting ' + uid + '.'+ TwinkleConfig.summaryAd, 'wpTextbox1': text + '*\{\{' + ( isIPAddress( uid ) ? 'IPvandal' : 'vandal' ) + '|' + (/\=/.test( uid ) ? '1=' :  ) + uid + '\}\} - ' + reason + ' ' +  };

self.post( postData ); },	username: function( self ) { uid = self.params.uid; reason = self.params.reason; var form = self.responseXML.getElementById('editform');

if( !form ) { self.statelem.error( 'Failed to retrieve edit form.' ); return; }		var text = form.wpTextbox1.value;

self.statelem.status( 'Adding new report...' ); var postData = { 'wpMinoredit': form.wpMinoredit.checked ? '' : undefined, 'wpWatchthis': form.wpWatchthis.checked ? '' : undefined, 'wpStarttime': form.wpStarttime.value, 'wpEdittime': form.wpEdittime.value, 'wpAutoSummary': form.wpAutoSummary.value, 'wpEditToken': form.wpEditToken.value, 'wpSummary': 'Reporting ' + uid + '.'+ TwinkleConfig.summaryAd, 'wpTextbox1': text.replace( /-->/, "-->\n" + reason.replace( '\$', "$$$$" ) ) };		self.post( postData ); },	sock: { main: function( self ) { var xmlDoc = self.responseXML; var titles = xmlDoc.evaluate( '//allpages/p/@title', xmlDoc, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null );

var number = 0; for( var i = 0; i < titles.snapshotLength; ++i ) { var title = titles.snapshotItem(i).value; title = title.replace( /(first|second|third|fourth|fifth|sixth|seventh|eighth|ninth|tenth|eleventh)/, function(v) {						return {							'first': '1st',							'second': '2nd',							'third': '3rd',							'fourth': '4th',							'fifth': '5th',							'sixth': '6th',							'seventh': '7th',							'eighth': '8th',							'ninth': '9th',							'tenth': '10th',							'eleventh': '11th'						}[v];					} ); var n = /\(\s*(\d+)(?:(?:th|nd|rd|st) nom(?:ination)?)?\s*\)\s*$/.exec( title ); if( n && n[1] > number ) { number = n[1]; } else if( number == 0 ) { number = 1; }			}

if( number == 0 ) { self.params.numbering = self.params.number = ''; numbering = number = ''; } else { self.params.number = num2order( parseInt( number ) + 1); self.params.numbering = ' (' + self.params.number + ' nomination)'; }			self.statelem.info( 'next in order is Suspected sock puppets/' + self.params.uid + self.params.numbering + '');

var query = { 'title': 'Wikipedia:Suspected sock puppets/' + self.params.uid + self.params.numbering, 'action': 'submit' };

var wikipedia_wiki = new Wikipedia.wiki( 'Creating discussion page', query, twinklearv.callbacks.sock.discussionPage ); wikipedia_wiki.params = self.params; wikipedia_wiki.get;

var query = { 'title': 'Wikipedia:Suspected sock puppets', 'section': 3, 'action': 'submit' };

var wikipedia_wiki = new Wikipedia.wiki( 'Linking report to open cases', query, twinklearv.callbacks.sock.openCases ); wikipedia_wiki.params = self.params; wikipedia_wiki.get;

var query = { 'title': 'User talk:' + self.params.uid, 'action': 'submit' };

var wikipedia_wiki = new Wikipedia.wiki( 'Notifying suspected sockpuppeter', query, twinklearv.callbacks.sock.notifySock ); wikipedia_wiki.params = self.params; wikipedia_wiki.get;

var query = { 'title': 'User:' + self.params.uid, 'action': 'submit' };

var wikipedia_wiki = new Wikipedia.wiki( 'Tag suspected sockpuppeter', query, twinklearv.callbacks.sock.tagSockpuppeter ); wikipedia_wiki.params = self.params; wikipedia_wiki.get;

var statusIndicator1 = new Status('Tagging suspected sockpuppets', '0%'); var statusIndicator2 = new Status('Notifying suspected sockpuppets', '0%');

var total = self.params.sockpuppets.length * 2;

var onsuccess = function( self ) { var obj = self.params.obj; var total = self.params.total; var now = parseInt( 100 * ++(self.params.current)/total ) + '%'; obj.update( now ); self.statelem.unlink; if( self.params.current >= total ) { obj.info( now + ' (completed)' ); Wikipedia.removeCheckpoint; }			}			var onloaded = onsuccess;

var onloading = function( self ) {}

Wikipedia.addCheckpoint;

var params1 = clone( self.params ); params1.total = total; params1.obj = statusIndicator1; params1.current =  0;

var params2 = clone( self.params ); params2.total = total; params2.obj = statusIndicator2; params2.current =  0;

var socks = self.params.sockpuppets; for( var i = 0; i < socks.length; ++i ) { var query = { 'title': 'User:' + socks[i], 'action': 'submit' };				var wikipedia_wiki = new Wikipedia.wiki( "Tagging of " + socks[i], query, twinklearv.callbacks.sock.tagSockpuppet ); wikipedia_wiki.params = params1; wikipedia_wiki.onloaded = onloaded; wikipedia_wiki.onsuccess = onsuccess; wikipedia_wiki.get; var query = { 'title': 'User talk:' + socks[i], 'action': 'submit' };				var wikipedia_wiki = new Wikipedia.wiki( "Notification for " + socks[i], query, twinklearv.callbacks.sock.notifySock ); wikipedia_wiki.params = params2; wikipedia_wiki.onloaded = onloaded; wikipedia_wiki.onsuccess = onsuccess; wikipedia_wiki.get;

}		},		discussionPage: function( self ) { var form = self.responseXML.getElementById('editform'); var text = "===User:" + self.params.uid + "===\n" + ";Suspected sockpuppeteer\n" + ":\{\{user5|" + self.params.uid + "\}\}\n\n" + ";Suspected sockpuppets\n" + self.params.sockpuppets.map( function(v) { return ":\{\{user5|" + v + "\}\}" } ).join( "\n" ) + "\n\n" + ";Report submission by\n" + "\~\~\~\~\n\n" + ";Evidence\n" + self.params.evidence + "\n\n" + ";Comments\n\n\n" + ";Conclusions\n\n\n" + "\n \n";

var postData = { 'wpMinoredit': form.wpMinoredit.checked ? '' : undefined, 'wpWatchthis': form.wpWatchthis.checked ? '' : undefined, 'wpStarttime': form.wpStarttime.value, 'wpEdittime': form.wpEdittime.value, 'wpAutoSummary': form.wpAutoSummary.value, 'wpEditToken': form.wpEditToken.value, 'wpSummary': "Creating report for User:" + self.params.uid + '.' + TwinkleConfig.summaryAd, 'wpTextbox1': text };			self.post( postData ); },		openCases: function( self ) { var form = self.responseXML.getElementById('editform'); text = form.wpTextbox1.value.replace( //, "$1\n\{\{Wikipedia:Suspected sock puppets/" + self.params.uid + self.params.numbering + "\}\}"); var postData = { 'wpMinoredit': form.wpMinoredit.checked ? '' : undefined, 'wpWatchthis': form.wpWatchthis.checked ? '' : undefined, 'wpStarttime': form.wpStarttime.value, 'wpEdittime': form.wpEdittime.value, 'wpAutoSummary': form.wpAutoSummary.value, 'wpEditToken': form.wpEditToken.value, 'wpSummary': "Adding report for User:" + self.params.uid + '.' + TwinkleConfig.summaryAd, 'wpTextbox1': text };

self.post( postData ); },		tagSockpuppeter: function( self ) { var form = self.responseXML.getElementById('editform'); var text = form.wpTextbox1.value; if( /\{\{sockpuppeteer.*?\}\}/.exec( text ) ) { // already marked as a sock, just ignore then self.onsuccess( self ); Wikipedia.actionCompleted; return; }			var postData = { 'wpMinoredit': form.wpMinoredit.checked ? '' : undefined, 'wpWatchthis': form.wpWatchthis.checked ? '' : undefined, 'wpStarttime': form.wpStarttime.value, 'wpEdittime': form.wpEdittime.value, 'wpAutoSummary': form.wpAutoSummary.value, 'wpEditToken': form.wpEditToken.value, 'wpSummary': "Adding suspected sockpuppeter tag." + TwinkleConfig.summaryAd, 'wpTextbox1': "\{\{sockpuppeteer\}\}\n" + text };

self.post( postData ); },		tagSockpuppet: function( self ) { var form = self.responseXML.getElementById('editform'); var text = form.wpTextbox1.value; if( /\{\{sockpuppet.*?\}\}/.exec( text ) ) { // already marked as a sock, just ignore then self.onsuccess( self ); Wikipedia.actionCompleted; return; }			var postData = { 'wpMinoredit': form.wpMinoredit.checked ? '' : undefined, 'wpWatchthis': form.wpWatchthis.checked ? '' : undefined, 'wpStarttime': form.wpStarttime.value, 'wpEdittime': form.wpEdittime.value, 'wpAutoSummary': form.wpAutoSummary.value, 'wpEditToken': form.wpEditToken.value, 'wpSummary': "Adding suspected sockpuppet tag for suspected sockpuppeter User:" + self.params.uid + '.' + TwinkleConfig.summaryAd, 'wpTextbox1': "\{\{subst:sockpuppet|1=" + self.params.uid + "\}\}\n" + text };

self.post( postData ); },

notifySock: function( self ) { var form = self.responseXML.getElementById('editform'); text = form.wpTextbox1.value; var postData = { 'wpMinoredit': form.wpMinoredit.checked ? '' : undefined, 'wpWatchthis': form.wpWatchthis.checked ? '' : undefined, 'wpStarttime': form.wpStarttime.value, 'wpEdittime': form.wpEdittime.value, 'wpAutoSummary': form.wpAutoSummary.value, 'wpEditToken': form.wpEditToken.value, 'wpSummary': "Notifying about suspicion of sockpuppetering." + TwinkleConfig.summaryAd, 'wpTextbox1': text + "\n\{\{subst:socksuspectnotice|1=" + self.params.uid + self.params.numbering + "\}\} \~\~\~\~" };

self.post( postData ); }	} }

twinklearv.callback.evaluate = function(e) { var form = e.target; var reason = ""; if( form.reason ) { comment = form.reason.value; }	var uid = form.uid.value; switch( form.category.value ) { default: case 'aiv': var types = form.getChecked( 'arvtype' ); if( types.length == 0 && comment == '' ) { alert( 'You must specify some reason' ); return; }

types = types.map( function(v) {				switch(v) {				case 'final':					return 'vandalism after final warning';					break;				case 'postblock':					return 'vandalism after recent release of block';					break;				case 'spambot':					return 'account is evidently a spambot or a compromised account';					break;				case 'vandalonly':					return 'actions evidently indicate a vandalism only account';					break;				}			} ).join( ', ' );

if( form.page.value != '' ) { reason += 'On Category):/i, ':$1:' ) + '';

if( form.badid.value != '' ) { var query = { 'title': form.page.value, 'diff': form.badid.value, 'oldid': form.goodid.value };				reason += ' ([' + mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + QueryString.create( query ) + ' diff])'; }			reason += ';'; }

if( types ) { reason += " " + types; }		if (comment != '' ) { reason += ". " + comment + '.'; }		Status.init( form );

var query = { 'title': 'Wikipedia:Administrator intervention against vandalism', 'action': 'submit', 'section': 1 };		wikipedia_wiki = new Wikipedia.wiki( 'Processing AIV request', query, twinklearv.callbacks.aiv ); wikipedia_wiki.params = { reason:reason, uid:uid }; wikipedia_wiki.get; break; case 'username': var types = form.getChecked( 'arvtype' ); if( types.length == 0 ) { alert( 'You must specify at least one breached violation' ); return; }		types = types.map( function( v ) { return v.toLowerCaseFirstChar; } );

if( types.length <= 2 ) { types = types.join( ' and ' ); } else { types = [ types.slice( 0, -1 ).join( ', ' ), types.slice( -1 ) ].join( ', and ' ); }		var article = 'a'; if( /aeiouwyh/.test( types[0] ) ) { // non 100% correct, but whatever inlcuding 'h' for Cockney article = 'an'; }		reason = "*\{\{user-uaa|1=" + uid + "\}\} &mdash; Violation of username policy because it's " + article + " " + types + " username; "; if (comment != '' ) { reason += "" + comment.toUpperCaseFirstChar + ". "; }		reason += "\~\~\~\~"; Status.init( form );

var query = { 'title': 'Wikipedia:Usernames for administrator attention', 'action': 'submit', 'section': 1 };

wikipedia_wiki = new Wikipedia.wiki( 'Processing UAA request', query, twinklearv.callbacks.username ); wikipedia_wiki.params = { reason:reason, uid:uid }; wikipedia_wiki.get; break; case 'sock': var sockpuppets = form.getTexts( 'sockpuppet' ); var evidence = form.evidence.value; Status.init( form );

var query = { 'action': 'query', 'list': 'allpages', 'apprefix': 'Suspected sock puppets/' + uid, 'apnamespace': 4, 'apfilterredir': 'nonredirects', 'aplimit': userIsInGroup( 'sysop' ) ? 5000 : 500		};

var wikipedia_api = new Wikipedia.api( 'Quering allpages', query, twinklearv.callbacks.sock.main ); wikipedia_api.params = { uid:uid, sockpuppets:sockpuppets, evidence:evidence }; wikipedia_api.post; } }