Jump to content

User:Timotab/twinklearv.js

From Wikipedia, the free encyclopedia
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
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>
// If TwinkleConfig aint exist.
if( typeof( TwinkleConfig ) == 'undefined' ) {
	TwinkleConfig = {};
}
 
/**
 TwinkleConfig.summaryAd (string)
 If ad should be added or not to summary, default [[WP:TWINKLE|TWINKLE]]
 */
if( typeof( TwinkleConfig.summaryAd ) == 'undefined' ) {
	TwinkleConfig.summaryAd = " using [[WP:TWINKLE|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 getChecked( nodelist ) {
	if( !( nodelist instanceof NodeList ) ) {
		throw nodelist + " not instance of NodeList";
	}
	var result = [];
	for(var i in nodelist ) {
		if( nodelist[i].checked ) {
			result.push( nodelist[i].value );
		}
	}
	return result;
}
 
function getTexts( nodelist ) {
	if ( nodelist instanceof HTMLInputElement ) {
		return [ nodelist.value ];
	}
	if( !( nodelist instanceof NodeList ) ) {
		throw nodelist + " not instance of NodeList";
	}
	var result = [];
	for(var i in nodelist ) {
		if( nodelist[i].type == 'text' && nodelist[i].value != '' ) {
			result.push( nodelist[i].value );
		}
	}
	return result;
}
 
function num2order( num ) {
	switch( num ) {
	case 1: return '';
	case 2: return '2nd';
	case 3: return '3rd';
	default: return num + 'th';
	}
}
 
addOnloadHook( 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.getElementById( 'contentSub' ).getElementsByTagName( 'a' )[0].getAttribute('title').split(':')[1];
		} 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';
 
		mw.util.addPortletLink( 'p-cactions', "javascript:twinklearv.callback(\"" + username + "\")", "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: 'Sockpuppet',
			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 in root.childNodes ) {
		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'
					},
					{ 
						label: 'Account is evidently a spambot or a compromized 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: 'Usernames that closely resemble the name of another Wikipedia user and may cause confusion',
						value: 'closely resembles the name of another wikipedia user and may cause confusion'
					},
					{
						label: 'Usernames that confusingly refer to a Wikipedia process, namespace, or toolbar item',
						value: 'confusingly refers to a Wikipedia process, namespace or toolbar item'
					},
					{
						label: 'Usernames that consist of a lengthy or apparently random sequence of characters',
						value: 'consists of a lengthy or apparently random sequence of characters',
						tooltip: 'E.g. "aaaaaaaaaaaa" or "ghfjkghdfjgkdhfjkg"'
					},
					{
						label: 'Usernames that are extremely lengthy',
						value: 'is extremely lengthy',
						tooltip: 'E.g. "Super Ultra Mege Bob of Waverly Drive from Mars146366"' 
					}
				]
			} );
 
		types.append ( { 
				type:'header', 
				label:'Misleading usernames',
				tooltip: 'Misleading usernames that imply relevant, misleading things about the user'
			} );
		types.append( {
				type: 'checkbox',
				name: 'arvtype',
				list: [
					{
						label: 'Usernames that imply the user is an admin or other official figure on Wikipedia, or of the Wikimedia foundation',
						value: 'implies that the user is an admin or other official figure on Wikipedia, or of the Wikimedia foundation'
					},
					{
						label: 'Usernames that match the name of a well-known living or recently deceased person',
						value: 'matches the name of a well-known living or recently deceased person',
						tooltip: 'Unless user verifiably is that person. Wikipedians with articles is a list of such users.'
					},
					{
						label: 'Usernames that imply an automated account',
						value: 'implies an automated account',
						tooltip: 'Such as names containing "robot", "bot", or a variation thereof. Such usernames are reserved for bot accounts'
					}
				]
			} );
 
		types.append ( { 
				type:'header', 
				label:'Disruptive usernames',
				tooltip: 'Disruptive usernames that disrupt or misuse Wikipedia, or imply an intent to do so'
			} );
		types.append( {
				type: 'checkbox',
				name: 'arvtype',
				list: [
					{
						label: 'Usernames that are similar to those used by known vandals',
						value: 'is similar to those used by known vandals'
					},
					{
						label: 'Usernames that are attacks on specific users',
						value: 'is an attack on an specific user'
					},
					{
						label: 'Usernames that contain personal information about people',
						value: 'contains personal information about people',
						tooltip: 'Such as a telephone number or street address'
					},
					{
						label: 'Usernames that allude to hacking, trolling, vandalism, legal threats, or computer viruses',
						value: 'alludes to hacking, trolling, vandalism, legal threats, or computer viruses'
					},
					{
						label: 'Usernames that include profanity, or obscenities, or references to genitalia or sexual slang',
						value: 'includes profanities, obscenities, or references to genitalias or sexual slangs'
					}
				]
			} );
 
		types.append ( { 
				type:'header', 
				label:'Promotional usernames',
				tooltip: 'Promotional usernames that attempt to promote a group or company on Wikipedia'
			} );
		types.append( {
				type: 'checkbox',
				name: 'arvtype',
				list: [
					{
						label: 'Usernames that match the name of a company or group',
						value: 'matches the name of a company or group',
						tooltip: 'Especially if the user promotes it'
					},
					{
						label: 'E-mail addresses or web page addresses are generally considered likely to be promotional',
						value: 'resembles e-mail addresses or web page addresses and is likely to be promotional',
						tooltip: 'Note that for a long time, email addresses were not prohibited. Usernames created before January 1, 2007 that are email addresses are grandfathered under this policy and are not prohibited'
					}
				]
			} );
 
		types.append ( { 
				type:'header', 
				label:'Offensive usernames',
				tooltip: 'Offensive usernames that may make harmonious editing difficult or impossible'
			} );
		types.append( {
				type: 'checkbox',
				name: 'arvtype',
				list: [
					{
						label: 'Usernames that promote a controversial or potentially inflammatory point of view',
						value: 'promotes a controversial or potentially inflammatory point of view'
					},
					{
						label: 'Usernames that are defamatory or insulting to other people or groups',
						value: 'is defamatory or insulting to other people or groups'
					},
					{
						label: 'Usernames that invoke the name of a religious figure or religion in a distasteful, disrespectful, or provocative way, or promote one religion over another',
						value: 'invokes the name of a religious figure/religion in a distasteful, disrespectful, or provocative way, or promotes one religion over another',
						tooltip: 'Note that simple expressions of faith are allowed unless they are disruptive, but are discouraged'
					},
					{
						label: 'Usernames that refer to real-world violent actions',
						value: 'refers to a violent real-world action'
					},
					{
						label: 'Usernames that refer or include allusions to racism, sexism, hate speech, et cetera',
						value: 'refers or includes allusions to racism, sexism, hate speech, et cetera'
					},
					{
						label: 'Usernames that refer to a medical condition or disability, especially in a belittling way',
						value: 'refers to a medical condition or disability'
					},
					{
						label: 'Usernames that include slurs, or references to reproductive or excretory bodily functions',
						value: 'includes slurs or references to reproductive/excretory bodily functions'
					}
				]
			} );
		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'
			} );
		var sock_area = work_area.append( { type:'div' } );
		sock_area.append( {
				type: 'button',
				label: 'More socks',
				name: 'more_socks_button',
				event: function (e){
					var area = e.target.parentNode.parentNode;
					var new_node = new QuickForm.element( {
							type: 'input',
							label: 'Sockpuppet: ',
							name: 'sockpuppet'
						} );
					if( area.childNodes.length > 1 ) {
						new_node.append( {
								type: 'button',
								label: 'remove',
								event: function (e){
									var node_to_remove = e.target.parentNode.parentNode;
									node_to_remove.parentNode.removeChild( node_to_remove );
								}
							} );
					}
					area.insertBefore( new_node.render(), area.lastChild );
				}
			} );
 
		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 );
 
		var evt = document.createEvent( "MouseEvent" );
		evt.initEvent( 'click', true, true );
		work_area.form.more_socks_button.dispatchEvent( evt );
		break;
	}
}
 
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 = getChecked( form.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 directly after release of block';
					break;
				case 'spambot':
					return 'account is evidently a spambot or a compromized account';
					break;
				case 'vandalonly':
					return 'actions evidently indicate a vandalism only account';
					break;
				}
			} ).join( ', ' );
 
 
		if( form.page.value != '' ) {
			reason += 'On [[' + form.page.value.replace( /^(Image|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 );
 
		Status.status( "Grabbing AIV page" );
		var xmlhttp = sajax_init_object();
		xmlhttp.query = {
			'title': 'Wikipedia:Administrator intervention against vandalism',
			'action': 'submit',
			'section': 1
		};
		xmlhttp.params = { reason:reason, uid:uid };
 
		xmlhttp.overrideMimeType('text/xml');
		xmlhttp.open( 'GET' , mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + QueryString.create( xmlhttp.query ), true);
		xmlhttp.onload = function() {
			uid = this.params.uid;
			reason = this.params.reason;
			var form = this.responseXML.getElementById('editform');
 
			if( !form ) {
				Status.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 ) ) ) {
				Status.info( 'Report already present, will not add a new one' );
				return;
			}
			Status.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 [[Special:Contributions/' + uid + '|' + uid + ']].'+ TwinkleConfig.summaryAd,
				'wpTextbox1': text + '*{{' + ( isIPAddress( uid ) ? 'IPvandal' : 'vandal' ) + '|' + (/\=/.test( uid ) ? '1=' : '' ) + uid + '}} - ' + reason + ' ~~' + '~~'
			};
			var xmlhttp = sajax_init_object();
			xmlhttp.overrideMimeType('text/xml');
			xmlhttp.open( 'POST' , mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + QueryString.create( this.query ), true);
			xmlhttp.setRequestHeader('Content-type','application/x-www-form-urlencoded');
			xmlhttp.onload = function() { window.location =  mw.config.get('wgServer') + mw.config.get('wgArticlePath').replace( '$1', 'Wikipedia:Administrator intervention against vandalism' ); }
			xmlhttp.send( QueryString.create( postData ) );
 
		}
		xmlhttp.send( null );
 
		break;
 
	case 'username':
		var types = getChecked( form.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 ' ).toUpperCaseFirstChar();
		} else {
			types = [ types.slice( 0, -1 ).join( ', ' ), types.slice( -1 ) ].join( ', and ' ).toUpperCaseFirstChar();
		}
		reason = "*\{\{userlinks|" + uid + "\}\} &mdash; Violation of username policy because: " + types + "; ";
		if (comment != '' ) {
			reason += "''" + comment.toUpperCaseFirstChar() + "''. ";
		}
		reason += "\~\~\~\~";
		Status.init( form );
 
		Status.status( "Grabbing UAA page" );
		var xmlhttp = sajax_init_object();
		xmlhttp.query = {
			'title': 'Wikipedia:Usernames for administrator attention',
			'action': 'submit',
			'section': 1
		};
		xmlhttp.params = { reason:reason, uid:uid };
		xmlhttp.overrideMimeType('text/xml');
		xmlhttp.open( 'GET' , mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + QueryString.create( xmlhttp.query ), true);
		xmlhttp.onload = function() {
			uid = this.params.uid;
			reason = this.params.reason;
			var form = this.responseXML.getElementById('editform');
 
			if( !form ) {
				Status.error( 'Failed to retrieve edit form.' );
				return;
			}
			var text = form.wpTextbox1.value;
 
			Status.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 [[Special:Contributions/' + uid + '|' + uid + ']].'+ TwinkleConfig.summaryAd,
				'wpTextbox1': text.replace( /-->/, "-->\n" + reason.replace( '\$', "$$$$" ) )
			};
			var xmlhttp = sajax_init_object();
			xmlhttp.overrideMimeType('text/xml');
			xmlhttp.open( 'POST' , mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + QueryString.create( this.query ), true);
			xmlhttp.setRequestHeader('Content-type','application/x-www-form-urlencoded');
			xmlhttp.onload = function() { window.location =  mw.config.get('wgServer') + mw.config.get('wgArticlePath').replace( '$1', 'Wikipedia:Usernames for administrator attention' ); }
			xmlhttp.send( QueryString.create( postData ) );
 
		}
		xmlhttp.send( null );
		break;
	case 'sock':
		var sockpuppets = getTexts( form.sockpuppet );
		var evidence = form.evidence.value;
		Status.init( form );
 
		Status.status( 'Grabbing data of eventual previous reports' );
 
		var xmlhttp = sajax_init_object();
		xmlhttp.query = {
			'title': 'Special:Prefixindex',
			'from': 'Suspected sock puppets/' + uid,
			'namespace': 4
		};
		xmlhttp.params = { uid:uid, sockpuppets:sockpuppets, evidence:evidence };
		xmlhttp.overrideMimeType('text/xml');
		xmlhttp.open( 'GET' , mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + QueryString.create( xmlhttp.query ), true);
		xmlhttp.onload = function() {
			var a_tags = this.responseXML.getElementsByTagName('a');
			var re = new RegExp( RegExp.escape( 'Suspected sock puppets/' + this.params.uid ) );
			var number = 0;
			for( var i in a_tags ) {
				var title = a_tags[i].title;
				if( re.exec( title ) ) {
					var n = /\(\s*(\d+)(?:th|nd|rd|st)\s*\)\s*$/.exec( title );
					if( n && n[1] > number ) {
						number = n[1];
					} else if( number == 0 ) {
						number = 1;
					}
				}
			}
 
			if( number == 0 ) {
				this.params.numbering = this.params.number = '';
			} else {
				this.params.number = num2order( parseInt( number ) + 1);
				this.params.numbering = ' (' + this.params.number + ')';
			}
 
			Status.status( 'Creating report page [[Wikipedia:Suspected sock puppets/' +  this.params.uid + this.params.numbering + ']]');
 
			var xmlhttp = sajax_init_object();
			xmlhttp.query = {
				'title': 'Wikipedia:Suspected sock puppets/' +  this.params.uid + this.params.numbering,
				'action': 'submit'
			};
			xmlhttp.params = this.params;
			xmlhttp.overrideMimeType('text/xml');
			xmlhttp.open( 'GET' , mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + QueryString.create( xmlhttp.query ), true);
			xmlhttp.onload = function() {
				var form = this.responseXML.getElementById('editform');
				var text = 
					"===[[User:" + this.params.uid + "]]===\n" +
					";Suspected sockpuppeteer\n" +
					":\{\{user5|" + this.params.uid + "\}\}\n\n" +
					";Suspected sockpuppets\n" + 
					this.params.sockpuppets.map( function(v) { return ":\{\{user5|" + v + "\}\}" } ).join( "\n" ) + "\n\n" +
					";Report submission by\n" +
					"\~\~\~\~\n\n" +
					";Evidence\n" +
					this.params.evidence + "\n\n" +
					";Comments\n\n\n" +
					";Conclusions\n\n\n" +
					"----\n</div>\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:" +  this.params.uid + ']].' + TwinkleConfig.summaryAd,
					'wpTextbox1': text
				};
				var xmlhttp = sajax_init_object();
				xmlhttp.overrideMimeType('text/xml');
				xmlhttp.open( 'POST' , mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + QueryString.create( this.query ), true);
				xmlhttp.setRequestHeader('Content-type','application/x-www-form-urlencoded');
				xmlhttp.onload = function() { Status.info( 'Report created' ) }
				xmlhttp.send( QueryString.create( postData ) );
			}
			xmlhttp.send( null );
 
			Status.status( 'Linking report to open cases');
			var xmlhttp = sajax_init_object();
			xmlhttp.query = {
				'title': 'Wikipedia:Suspected sock puppets',
				'section': 4,
				'action': 'submit'
			};
			xmlhttp.params = this.params;
			xmlhttp.overrideMimeType('text/xml');
			xmlhttp.open( 'GET' , mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + QueryString.create( xmlhttp.query ), true);
			xmlhttp.onload = function() {
				var form = this.responseXML.getElementById('editform');
				text = form.wpTextbox1.value.replace( /(<!-- Add .*? list\. -->)/, "$1\n\{\{Wikipedia:Suspected sock puppets/" + this.params.uid + this.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:" +  this.params.uid + ']].' + TwinkleConfig.summaryAd,
					'wpTextbox1': text
				};
				var xmlhttp = sajax_init_object();
				xmlhttp.overrideMimeType('text/xml');
				xmlhttp.open( 'POST' , mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + QueryString.create( this.query ), true );
				xmlhttp.setRequestHeader('Content-type','application/x-www-form-urlencoded');
				xmlhttp.onload = function() { Status.info( 'Added to open cases' ) }
				xmlhttp.send( QueryString.create( postData ) );
			}
			xmlhttp.send( null );
 
			Status.status( 'Notifying suspected sockpuppeter');
			var xmlhttp = sajax_init_object();
			xmlhttp.query = {
				'title': 'User talk:' + this.params.uid,
				'action': 'submit'
			};
			xmlhttp.params = this.params;
			xmlhttp.overrideMimeType('text/xml');
			xmlhttp.open( 'GET' , mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + QueryString.create( xmlhttp.query ), true);
			xmlhttp.onload = function() {
				var form = this.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 sockpuppertering." + TwinkleConfig.summaryAd,
					'wpTextbox1': text + "\n\{\{subst:socksuspectnotice|1=" + this.params.uid + this.params.numbering + "\}\} \~\~\~\~"
				};
				var xmlhttp = sajax_init_object();
				xmlhttp.overrideMimeType('text/xml');
				xmlhttp.open( 'POST' , mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + QueryString.create( this.query ), true);
				xmlhttp.setRequestHeader('Content-type','application/x-www-form-urlencoded');
				xmlhttp.onload = function() { Status.info( 'Suspected sockpuppeter notified' ) }
				xmlhttp.send( QueryString.create( postData ) );
			}
			xmlhttp.send( null );
 
			var statusIndicator = document.createElement( 'div' );
			Status.status( [ statusIndicator ] );
			statusIndicator.appendChild( document.createTextNode( 'Tagging suspected socs, status: ' ) );
			statusIndicator.appendChild( document.createTextNode( '0%' ) );
			var nofnodes = this.params.sockpuppets.length * 2;
			counter = 0;
			updateCounter = function(obj, total) {
				obj.replaceChild( document.createTextNode( parseInt( 100 * ++counter/total ) + '%' ), obj.lastChild );
				if( counter == total ) {
					Status.info( 'tagging of sockpuppets complete.' );
 
				}
			}
			for( var i in this.params.sockpuppets ) {
				(function(current, total, obj, params) {
						var xmlhttp = sajax_init_object();
						xmlhttp.query = {
							'title': 'User:' + params.sockpuppets[current],
							'action': 'submit'
						};
						xmlhttp.overrideMimeType('text/xml');
						xmlhttp.open( 'GET' , mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + QueryString.create( xmlhttp.query ), true);
						xmlhttp.onload = function() {
							updateCounter( obj, total );
							var form = this.responseXML.getElementById('editform');
							text = form.wpTextbox1.value;
							if( /\{\{sockpuppet.*?\}\}/.exec( text ) ) { // already marked as a sock, just ignore then
								updateCounter( obj, total );
								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 supsected sockpuppet tag for suspected sockpuppeter [[User:" +  params.uid + ']].' + TwinkleConfig.summaryAd,
								'wpTextbox1': "\{\{subst:socksuspect|1=" + params.uid + "\}\}\n" + text
							};
							var xmlhttp = sajax_init_object();
							xmlhttp.current = this.current;
							xmlhttp.overrideMimeType('text/xml');
							xmlhttp.open( 'POST' , mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + QueryString.create( this.query ), true);
							xmlhttp.setRequestHeader('Content-type','application/x-www-form-urlencoded');
							xmlhttp.onload = function() { 
								updateCounter( obj, total );
							}
							xmlhttp.send( QueryString.create( postData ) );
						}
						xmlhttp.send( null );
					})( i, nofnodes, statusIndicator, this.params );
 
			}
 
		}
		xmlhttp.send( null );
	}
}
// </nowiki>