Usuário(a):Enrique Suarez Infante, S J/twinkle.js

Origem: Wikipédia, a enciclopédia livre.

Nota: Depois de publicar, poderá ter de contornar a cache do seu navegador para ver as alterações.

  • Firefox / Safari: Pressione Shift enquanto clica Recarregar, ou pressione Ctrl-F5 ou Ctrl-R (⌘-R no Mac)
  • Google Chrome: Pressione Ctrl-Shift-R (⌘-Shift-R no Mac)
  • Internet Explorer / Edge: Pressione Ctrl enquanto clica Recarregar, ou pressione Ctrl-F5
  • Opera: Pressione Ctrl-F5.
 /* Twinkle - reversão ***********************************************************************
  *    Origem: [[Usuário:Lijealso/twinklefluff.js]]
  *     Ajuda: [[Wikipedia:Software/Scripts/Twinkle]]
  * Descrição: Permite facilitar a reversão de edições.
  *     Autor: [[:w:en:AzaToth]]
  ********************************************************************************************/

/**
 Twinklefluff revert and antivandalism utillity
 */
// If TwinkleConfig aint exist.
if( typeof( TwinkleConfig ) == 'undefined' ) {
	TwinkleConfig = {};
}

/**
 TwinkleConfig.revertMaxRevisions (int)
 defines how many revision to query maximum, maximum possible is 50, default is 50
 */
if( typeof( TwinkleConfig.revertMaxRevisions ) == 'undefined' ) {
	TwinkleConfig.revertMaxRevisions = 50;
}


/**
 TwinkleConfig.userTalkPageMode may take arguments:
 'window': open a new window, remmenber the opened window
 'tab': opens in a new tab, if possible.
 'blank': force open in a new window, even if a such window exist
 */
if( typeof( TwinkleConfig.userTalkPageMode ) == 'undefined' ) {
	TwinkleConfig.userTalkPageMode = 'tab';
}

/**
 TwinkleConfig.openTalkPage (array)
 What types of actions that should result in opening of talk page
 */
if( typeof( TwinkleConfig.openTalkPage ) == 'undefined' ) {
	TwinkleConfig.openTalkPage = [ 'agf', 'norm', 'vand' ];
}

/**
 TwinkleConfig.openTalkPageOnAutoRevert (bool)
 Defines if talk page should be opened when canling revert from contrib page, this because from there, actions may be multiple, and opening talk page not suitable. If set to true, openTalkPage defines then if talk page will be opened.
 */
if( typeof( TwinkleConfig.openTalkPageOnAutoRevert ) == 'undefined' ) {
	TwinkleConfig.openTalkPageOnAutoRevert = false;
}

/**
 TwinkleConfig.openAOLAnonTalkPage may take arguments:
 true: to open Anon AOL talk pages on revert
 false: to not open them
 */
if( typeof( TwinkleConfig.openAOLAnonTalkPage ) == 'undefined' ) {
	TwinkleConfig.openAOLAnonTalkPage = false;
}

/**
 TwinkleConfig.summaryAd (string)
 If ad should be added or not to summary, default [[WP:TWINKLE|TWINKLE]]
 */
if( typeof( TwinkleConfig.summaryAd ) == 'undefined' ) {
	TwinkleConfig.summaryAd = " (Twinkle)";
}

/**
 TwinkleConfig.markRevertedPagesAsMinor (array)
 What types of actions that should result in marking edit as minor
 */
if( typeof( TwinkleConfig.markRevertedPagesAsMinor ) == 'undefined' ) {
	TwinkleConfig.markRevertedPagesAsMinor = [ 'agf', 'norm', 'vand', 'torev' ];
}

/**
 TwinkleConfig.watchRevertedPages (array)
 What types of actions that should result in forced addition to watchlist
 */
if( typeof( TwinkleConfig.watchRevertedPages ) == 'undefined' ) {
	TwinkleConfig.watchRevertedPages = [ 'agf', 'norm', 'vand', 'torev' ];
}

/**
 TwinkleConfig.offerReasonOnNormalRevert (boolean)
 If to offer a promt for extra summary reason for normal reverts, default to true
 */
if( typeof( TwinkleConfig.offerReasonOnNormalRevert ) == 'undefined' ) {
	TwinkleConfig.offerReasonOnNormalRevert = true;
}


// a list of usernames, usually only bots, that vandalism revert is jumped over, that is
// if vandalism revert is choosen on such username, then it's target in on the revision before.
// This is for handeling quick bots that makes edits seconds after the original edit is made.
// This only affect vandalism rollback, for good faith rollback, it will stop, indicating a bot 
// has no faith, and for normal rollback, it will rollback that edit.
var WHITELIST = [
'GOE',
'GOE2',
'GOE3',
]

var revertXML;
var contentXML;
var contentDoc;
var editXML;
var vandal;
var type;
var goodRev;
var nbrOfRevisions;
var curStatus;
var curVersion = true;

$( function() {
		if( QueryString.exists( 'twinklerevert' ) ) {
			twinkleAutoRevert();
		} else {
			addRevertButtons();
		}
	} );

function twinkleAutoRevert() {
	if( QueryString.get( 'oldid' ) != wgCurRevisionId ) {
		// not latest revision
		return;
	}

	var ntitle = getElementsByClassName( document.getElementById('bodyContent'), 'td' , 'diff-ntitle' )[0];
	if( ntitle.getElementsByTagName('a')[0].firstChild.nodeValue != 'Revisão actual' ) {
		// not latest revision
		return;
	}

	vandal = ntitle.getElementsByTagName('a')[3].firstChild.nodeValue.replace("'", "\\'");

	if( !TwinkleConfig.openTalkPageOnAutoRevert ) {
		TwinkleConfig.openTalkPage = [];
	}

	return revertPage( QueryString.get( 'twinklerevert' ), vandal );
}

function addRevertButtons() {

	var spanTag = function( color, content ) {
		var span = document.createElement( 'span' );
		span.style.color = color;
		span.appendChild( document.createTextNode( content ) );
		return span;
	}

	if( wgNamespaceNumber == -1 && wgCanonicalSpecialPageName == "Contributions" ) {
		var list = document.getElementById('bodyContent').getElementsByTagName( 'ul' )[0].getElementsByTagName( 'li' );
		var vandal = document.getElementById('contentSub').getElementsByTagName( 'a' )[0].getAttribute( 'title' ).replace(/^User( talk)?:/ , '').replace("'", "\\'");

		var revNode = document.createElement('strong');
		var revLink = document.createElement('a');
		revLink.appendChild( spanTag( 'Black', ' [' ) );
		revLink.appendChild( spanTag( 'SteelBlue', 'reverter' ) );
		revLink.appendChild( spanTag( 'Black', ']' ) );
		revNode.appendChild(revLink);

		var revVandNode = document.createElement('strong');
		var revVandLink = document.createElement('a');
		revVandLink.appendChild( spanTag( 'Black', ' [' ) );
		revVandLink.appendChild( spanTag( 'Red', 'vandalismo' ) );
		revVandLink.appendChild( spanTag( 'Black', ']' ) );
		revVandNode.appendChild(revVandLink);

		for(var i = 0; i < list.length; ++i ) {
			var item = list[i].lastChild;
			if ( !item ) {
				continue;
			}
			if( userIsInGroup( 'sysop' ) ) {
				item = item.previousSibling;
			}
			if( item.nodeName != 'STRONG' ) {
				continue
			}

			var href = list[i].getElementsByTagName( 'a' )[1].getAttribute( 'href' );
			var tmpNode = revNode.cloneNode( true );
			tmpNode.firstChild.setAttribute( 'href', href + '&' + QueryString.create( { 'twinklerevert': 'norm' } ) );
			list[i].appendChild( tmpNode );
			var tmpNode = revVandNode.cloneNode( true );
			tmpNode.firstChild.setAttribute( 'href', href + '&' + QueryString.create( { 'twinklerevert': 'vand' } ) );
			list[i].appendChild( tmpNode );
		}


	} else {

		var otitle = getElementsByClassName( document.getElementById('bodyContent'), 'td' , 'diff-otitle' )[0];
		var ntitle = getElementsByClassName( document.getElementById('bodyContent'), 'td' , 'diff-ntitle' )[0];

		if( !ntitle ) {
			// Nothing to see here, move along...
			return;
		}

		if( !otitle.getElementsByTagName('a')[0] ) {
			// no previous revision available
			return;
		}

		// Lets first add a [edit this revision] link
		var query = new QueryString( decodeURI( otitle.getElementsByTagName( 'a' )[0].getAttribute( 'href' ).split( '?', 2 )[1] ) );

		var oldrev = query.get( 'oldid' );

		var oldEditNode = document.createElement('strong');

		var oldEditLink = document.createElement('a');
		oldEditLink.href = "javascript:revertToRevision('" + oldrev + "')";
		oldEditLink.appendChild( spanTag( 'Black', '[' ) );
		oldEditLink.appendChild( spanTag( 'SaddleBrown', 'reverter para esta versão' ) );
		oldEditLink.appendChild( spanTag( 'Black', ']' ) );
		oldEditNode.appendChild(oldEditLink);

		var cur = otitle.insertBefore(oldEditNode, otitle.firstChild);
		otitle.insertBefore(document.createElement('br'), cur.nextSibling);

		if( ntitle.getElementsByTagName('a')[0].firstChild.nodeValue != 'Revisão actual' ) {
			// not latest revision
			curVersion = false;
			return;
		}

		vandal = ntitle.getElementsByTagName('a')[3].firstChild.nodeValue.replace("'", "\\'");

		var agfNode = document.createElement('strong');
		var vandNode = document.createElement('strong');
		var normNode = document.createElement('strong');

		var agfLink = document.createElement('a');
		var vandLink = document.createElement('a');
		var normLink = document.createElement('a');

		agfLink.href = "javascript:revertPage('agf' , '" + vandal + "')"; 
		vandLink.href = "javascript:revertPage('vand' , '" + vandal + "')"; 
		normLink.href = "javascript:revertPage('norm' , '" + vandal + "')"; 

		agfLink.appendChild( spanTag( 'Black', '[' ) );
		agfLink.appendChild( spanTag( 'DarkOliveGreen', 'reverter (boa-fé)' ) );
		agfLink.appendChild( spanTag( 'Black', ']' ) );

		vandLink.appendChild( spanTag( 'Black', '[' ) );
		vandLink.appendChild( spanTag( 'Red', 'reverter (vândalo)' ) );
		vandLink.appendChild( spanTag( 'Black', ']' ) );

		normLink.appendChild( spanTag( 'Black', '[' ) );
		normLink.appendChild( spanTag( 'SteelBlue', 'reverter' ) );
		normLink.appendChild( spanTag( 'Black', ']' ) );

		agfNode.appendChild(agfLink);
		vandNode.appendChild(vandLink);
		normNode.appendChild(normLink);

		var cur = ntitle.insertBefore(agfNode, ntitle.firstChild);
		cur = ntitle.insertBefore(document.createTextNode(' || '), cur.nextSibling);
		cur = ntitle.insertBefore(normNode, cur.nextSibling);
		cur = ntitle.insertBefore(document.createTextNode(' || '), cur.nextSibling);
		cur = ntitle.insertBefore(vandNode, cur.nextSibling);
		cur = ntitle.insertBefore(document.createElement('br'), cur.nextSibling);
	}

}

function revertPage( pType, pVandal, rev, page ) {

	wgPageName = page || wgPageName;
	wgCurRevisionId = rev || wgCurRevisionId;


	try {
		vandal = pVandal;
		type = pType;
		Status.init( document.getElementById('bodyContent') );

		revertXML = sajax_init_object();
		revertXML.overrideMimeType('text/xml');

		var query = {
			'action': 'query',
			'prop': 'revisions',
			'titles': wgPageName,
			'rvlimit': TwinkleConfig.revertMaxRevisions,
			'rvprop': [ 'ids', 'timestamp', 'user', 'comment' ],
			'format': 'xml'
		}

		Status.status( 'A analisar' );
		revertXML.onreadystatechange = revertPageCallback;
		revertXML.open( 'GET' , mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?' + QueryString.create( query ), true );
		revertXML.send( null );
	} catch(e) {
		if( e instanceof Exception ) {
			Status.error( 'Erro: ' + e.what() );
		} else {
			Status.error( 'Erro: ' + e );
		}
	}

}
function revertPageCallback() {

	if ( revertXML.readyState != 4 ){
		Status.progress('.');
		return;
	} 

	if( revertXML.status != 200 ){
		Status.error('Ocorreu um erro');
		return;
	}

	var doc = revertXML.responseXML.documentElement;

	if( !doc ) {
		Status.error( 'Ocorreu possivelmente um erro ao obter o documento, a interromper a operação.' );
		return;
	}
	var revisions = doc.getElementsByTagName('rev');
	var top = revisions[0];

	if( top.getAttribute( 'revid' ) < wgCurRevisionId ) {
		Status.error( [ 'A última versão ', htmlNode( 'strong', top.getAttribute('revid') ), ' é menor que a versão analisada. Pode ser um sinal de que a versão voi eliminada, o servidor está a sofrer atrasos na actualização ou que o Twinkle recebeu dados errados. As ações serão interrompidas.' ] );
		return;
	}
	if( !top ) {
		Status.error( 'A última versão da página não foi encontrada. A página pode ter sido eliminada ou que ocorreu um erro na transmissão dos dados. A interromper a reversão ');
		return;
	}


	Status.status( [ 'Averiguando as versões para ver se ', htmlNode( 'strong', vandal), ' é o último editor...' ] );

	if( wgCurRevisionId != top.getAttribute('revid') ) {
		Status.warn( [ 'A última versão ', htmlNode( 'strong', top.getAttribute('revid') ), ' não equivale à versão ', htmlNode( 'strong', wgCurRevisionId) ] );

		if( top.getAttribute( 'user' ) == vandal ) {
			switch( type ) {
			case 'vand':
				Status.info( [ 'A última edição foi feita por ', htmlNode( 'strong', vandal ) , ', como se assume que é vandalismo, a edição será revertida' ]);
				break;
			case 'afg':
				Status.warn( [ 'A última edição foi feita por ', htmlNode( 'strong', vandal ) , ', como se asssume a boa-fé as edições não serão revertidas pois o problema poderá ter sido resolvido.' ]);
				return;
			default:
				Status.warn( [ 'A última edição foi feita por ', htmlNode( 'strong', vandal ) , ', mas de qualquer forma a edição não será revertida.' ] );
				return;
			}
		} else if( 
			type == 'vand' && 
			WHITELIST.indexOf( top.getAttribute( 'user' ) ) != -1 && 
			top.nextSibling.getAttribute( 'pageId' ) == wgCurRevisionId 
		) {
			Status.info( [ 'A última edição foi feita por ', htmlNode( 'strong', top.getAttribute( 'user' ) ), ' que é um robô de confiança e a edição anterior foi feita pelo vândalo por isso irei fazer a reversão.' ] );
			top = top.nextSibling;
		} else {
			Status.error( [ 'A última edição foi feita por ', htmlNode( 'strong', top.getAttribute( 'user' ) ), ', por isso a eidção já poderá ter sido revertida. A interromper a reversão.'] );
			return;
		}
	} 

	if( WHITELIST.indexOf( vandal ) != -1  ) {
		switch( type ) {
		case 'vand':
			Status.info( [ 'Está a reverter como vandalismo a edição de ', htmlNode( 'strong', vandal ), ', como é um robô de confiança, assume-se que queira reverter uma edição anterior de outro usuário.' ] );
			top = top.nextSibling;
			vandal = top.getAttribute( 'user' );

			break;
		case 'agf':
			Status.warn( [ 'Está a reverter como boa-fé a edição de ', htmlNode( 'strong', vandal ), ', como é um robô de confiança, não faz sentido reverter como boa-fé. A interromper a reversão.' ] );
			return;

			break;
		case 'norm':
		default:
			var cont = confirm( 'Está a reverter como uma reversão normal, mas como o último editor (' + vandal + ') é um robô de confiança, não quer reverter antes a edição anterior a ele?' );
			if( cont ) {
				Status.info( [ 'Escolheu uma reversão normal da edição por ', htmlNode( 'strong', vandal ), ', como é um robô de confiança, e por confirmação, serão revertidas as edições anteriores ao robô.' ] );
				top = top.nextSibling;
				vandal = top.getAttribute( 'user' );
			} else {
				Status.warn( [ 'Escolheu uma reversão normal da edição de ', htmlNode( 'strong', vandal ), ', como é um robô de confiança, e por confirmação, as edições dele serão revertidas.' ] );
			}
			break;
		}
	}

	Status.status( 'Localizando a última edição estável...' );

	goodRev = top;
	nbrOfRevisions = 0;

	while( goodRev.getAttribute('user') == vandal ) {

		goodRev = goodRev.nextSibling;

		nbrOfRevisions++;

		if( goodRev == null ) {
			Status.error( [ 'Não encontrei edições anteriores. Talvez o ', htmlNode( 'strong', vandal ), ' seja o único editor ou o editor fez mais de ' + TwinkleConfig.revertMaxRevisions + ' edições seguidas.' ] );
			return;
		}
	}

	if( nbrOfRevisions == 0 ) {
		Status.error( "Ia reverter zero edições. Como isto não faz sentido, a reversão será interrompida. A edição poderá ter sido revertida mas o número da versão poderá ser o mesmo." );
		return;
	}

	if( 
		type != 'vand' && 
		nbrOfRevisions > 1  && 
		!confirm( vandal + ' fez ' + nbrOfRevisions + ' edições seguidas. Tem a certeza que as quer reverter todas?' ) 
	) {
		Status.info( 'Interrompendo a reversão a pedido' );
		return;
	}

	Status.progress( [ ' versão ', htmlNode( 'strong', goodRev.getAttribute( 'revid' ) ), ' feita ', htmlNode( 'strong', nbrOfRevisions ), ' edições antes por ', htmlNode( 'strong', goodRev.getAttribute( 'user' ) ) ] );

	Status.status( [ 'Obtendo o conteúdo da edição ', htmlNode( 'strong', goodRev.getAttribute( 'revid' ) ) ] );
	var query = {
		'action': 'query',
		'prop': 'revisions',
		'titles': wgPageName,
		'rvlimit': 1,
		'rvprop': 'content',
		'rvstartid': goodRev.getAttribute( 'revid' ),
		'format': 'xml'
	}

	// getting the content for the last good revision
	revertXML = sajax_init_object();
	revertXML.overrideMimeType('text/xml');
	revertXML.onreadystatechange = revertCallback2;
	revertXML.open( 'GET' , mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?' + QueryString.create( query ), true );
	revertXML.send( null );

}

function revertCallback2() {
	if ( revertXML.readyState != 4 ){
		Status.progress( '.' );
		return;
	} 

	if( revertXML.status != 200 ){
		Status.error( 'Bad status , bailing out' );
		return;
	}

	contentDoc = revertXML.responseXML.documentElement;
	if( !contentDoc ) {
		Status.error( 'Ocorreu um erro ao tentar obter a versão a reverter. A reversão será interrompida.');
		return;
	}

	Status.status( 'Editando' );

	revertXML = sajax_init_object();
	revertXML.overrideMimeType('text/xml');
	revertXML.onreadystatechange = revertCallback3;

	var query = {
		'title': wgPageName,
		'action': 'submit'
	};

	revertXML.open( 'GET' , mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + QueryString.create( query ), true );
	revertXML.send( null );
}

function revertCallback3() {
	if ( revertXML.readyState != 4 ){
		Status.progress( '.' );
		return;
	} 

	if( revertXML.status != 200 ){
		Status.error( 'Ocorreu um erro' );
		return;
	}

	Status.status( 'Atualizando o conteúdo...' );

	var doc = revertXML.responseXML;

	var form = doc.getElementById( 'editform' );
	if( !form ) {
		Status.error( 'não consegui obter o elemento "editform", a interromper. Pode não ter sido possível obter uma resposta por parte do servidor' );
		return;
	}
	form.style.display = 'none';


	var content = contentDoc.getElementsByTagName('rev')[0];
	if( !content ) {
		Status.error( 'ocorreu um erro ao tentar obter a versão da edição, a interromper.' );
		return;
	}

	var textbox = doc.getElementById( 'wpTextbox1' );

	textbox.value = "";

	var cn =  content.childNodes;

	for( var i = 0; i < cn.length; ++i ) {
		textbox.value += cn[i].nodeValue ? cn[i].nodeValue : '';
	}

	Status.status( 'Atualizando o sumário...' );
	var summary;

	var extra_summary = '';
	switch( type ) {
	case 'agf':
		extra_summary = prompt( "Se preferir acrescente um comentário ao sumário de edição:" );
		summary = "Revertidas edições em [[Wikipedia:Assumir a boa fé|boa fé]] de [[Special:Contributions/" + vandal + "|" + vandal + "]]" + ( extra_summary ? "; " + extra_summary.toUpperCaseFirstChar() : '' ) + "." + TwinkleConfig.summaryAd;
		break;
	case 'vand':
		summary = "Revertendo " + nbrOfRevisions + ( nbrOfRevisions > 1 ? " edições" : '' ) + ( nbrOfRevisions < 2 ? " edição" : '' ) + " de [[Wikipedia:Vandalismo|vandalismo]] por [[Special:Contributions/" + vandal + "|" + vandal + "]] para a última edição de [[Usuário:" + goodRev.getAttribute( 'user' ) + "|" + goodRev.getAttribute( 'user' ) + "]]." + TwinkleConfig.summaryAd;
		break;
	case 'norm':
		if( TwinkleConfig.offerReasonOnNormalRevert ) {
			extra_summary = prompt( "Se preferir acrescente um comentário ao sumário de edição:" );
		}
		summary = "Revertendo " + nbrOfRevisions + ( nbrOfRevisions > 1 ? " edições" : '' ) + ( nbrOfRevisions < 2 ? " edição" : '' ) + " de [[Special:Contributions/" + vandal + "|" + vandal + "]] para a última edição de [[User:" + goodRev.getAttribute( 'user' ) + "|" + goodRev.getAttribute( 'user' ) + "]]" + ( extra_summary ? "; " + extra_summary.toUpperCaseFirstChar() : '' ) + '.' + TwinkleConfig.summaryAd;
	}
	doc.getElementById( 'wpSummary' ).value = summary;

	if( TwinkleConfig.markRevertedPagesAsMinor.indexOf( type ) != -1 ) {
		doc.getElementById( 'wpMinoredit' ).checked = true;
	}

	if( TwinkleConfig.watchRevertedPages.indexOf( type ) != -1 ) {
		doc.getElementById( 'wpWatchthis' ).checked = true;
	}

	Status.status( [ 'Abrindo a página de discussão em modo de edição do usuário ', htmlNode( 'strong', vandal ) ]);

	var opentalk = true;

	if( TwinkleConfig.openTalkPage.indexOf( type ) != -1 ) {

		if( isIPAddress( vandal ) ) {
			Status.info( [ htmlNode( 'strong', vandal ), ' é um endereço IP, a verificar se pertence a um proxy AOL' ] );

			if( AOLNetworks.some( function( net ) { return isInNetwork( vandal, net ) } )) {
				if( TwinkleConfig.openAOLAnonTalkPage ) {
					Status.info( [ htmlNode( 'strong', vandal ), ' é um endereço de um proxy AOL. Conforme a configuração, a página de discussão do IP será aberta' ] );
				} else {
					Status.warn( [ htmlNode( 'strong', vandal ), ' é um endereço de um proxy AOL. A página de discussão do IP não será aberta uma vez que esses endereços são atribuídos aleatóriamente' ] );
					opentalk = false;
				}
			} else {
				Status.info( [ htmlNode( 'strong', vandal ), ' é um endereço IP. A abrir a página de discussão' ] );
			}

		}

		if( opentalk ) {
			var query = {
				'title': 'Usuário Discussão:' + vandal,
				'action': 'edit',
				'vanarticle': wgPageName.replace(/_/g, ' '),
				'vanarticlerevid': wgCurRevisionId,
				'vanarticlegoodrevid': goodRev.getAttribute( 'revid' ),
				'type': type,
				'count': nbrOfRevisions
			}

			switch( TwinkleConfig.userTalkPageMode ) {
			case 'tab':
				window.open( mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + QueryString.create( query ), '_tab' );
				break;
			case 'blank':
				window.open( mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + QueryString.create( query ), '_blank', 'location=no,toolbar=no,status=no,directories=no,scrollbars=yes,width=1200,height=800' );
				break;
			case 'window':
				default :
				window.open( mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + QueryString.create( query ), 'twinklewarnwindow', 'location=no,toolbar=no,status=no,directories=no,scrollbars=yes,width=1200,height=800' );
				break;
			}
		}
	}

	document.getElementById('globalWrapper').appendChild( form );

	Status.status( 'A submeter...' );
	form.submit();
}

function revertToRevision( oldrev ) {

	try {
		Status.init( document.getElementById('bodyContent') );

		var query = {
			'action': 'query',
			'prop': 'revisions',
			'titles': wgPageName,
			'rvlimit': 1,
			'rvstartid': oldrev,
			'rvprop': [ 'ids', 'timestamp', 'user', 'comment', 'content' ],
			'format': 'xml'
		}

		Status.status( 'Analisando' );

		var xmlhttp = sajax_init_object();
		xmlhttp.overrideMimeType('text/xml');
		xmlhttp.open( 'GET' , mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?' + QueryString.create( query ), true );
		xmlhttp.onload = function(e) {

			Status.status( 'Obtendo o conteúdo' );
			var xmlhttp = sajax_init_object();
			xmlhttp.lastGoodRevision = this.responseXML.documentElement.getElementsByTagName('rev')[0];
			xmlhttp.query = {
				'title': wgPageName,
				'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(e) {

				Status.status( 'Atualizando o conteúdo da versão anterior...' );

				var form = this.responseXML.getElementById( 'editform' );
				var text;

				if( !form ) {
					Status.error( 'não foi possível obter o elemento  "editform", a interromper. Pode ter ocorrido um erro na resposta do servidor' );
					return;
				}

				text = this.lastGoodRevision.textContent;

				Status.status( 'Actualizando o sumário...' );
				var optional_summary = prompt( "Se preferir acrescente a razão da reversão no sumário de edição" );

				var summary = 'Revertendo para a edição ' + this.lastGoodRevision.getAttribute( 'revid' ) + ' de [[User:' + this.lastGoodRevision.getAttribute( 'user' ) + '|' + this.lastGoodRevision.getAttribute( 'user' ) + ']]' + ( optional_summary ? "; " + optional_summary : '' ) + '.' + TwinkleConfig.summaryAd;
				var postData = {
					'wpMinoredit': TwinkleConfig.markRevertedPagesAsMinor.indexOf( 'torev' ) != -1 ? true : form.wpMinoredit.checked, 
					'wpWatchthis': TwinkleConfig.watchRevertedPages.indexOf( 'torev' ) != -1 ? true : form.wpWatchthis.checked,
					'wpStarttime': form.wpStarttime.value,
					'wpEdittime': form.wpEdittime.value,
					'wpAutoSummary': form.wpAutoSummary.value,
					'wpEditToken': form.wpEditToken.value,
					'wpSummary': summary,
					'wpTextbox1': text
				};

				Status.status( 'A submeter...' );

				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', wgPageName.replace( '_', ' ' ) ); }
				xmlhttp.send( QueryString.create( postData ) );
			}

			xmlhttp.send( null );


		}
		xmlhttp.send( null );
	} catch(e) {
		if( e instanceof Exception ) {
			Status.error( 'Erro: ' + e.what() );
		} else {
			Status.error( 'Erro: ' + e );
		}
	}

}

<noinclude>
[[Categoria:!Código-fonte de scripts|Twinkle]]
[[en:User:AzaToth/twinklefluff.js]]
</noinclude>