Zum Inhalt springen

Benutzer:C-M/twinklefluff.js

aus Wikipedia, der freien Enzyklopädie

Hinweis: Leere nach dem Veröffentlichen den Browser-Cache, um die Änderungen sehen zu können.

  • Firefox/Safari: Umschalttaste drücken und gleichzeitig Aktualisieren anklicken oder entweder Strg+F5 oder Strg+R (⌘+R auf dem Mac) drücken
  • Google Chrome: Umschalttaste+Strg+R (⌘+Umschalttaste+R auf dem Mac) drücken
  • Edge: Strg+F5 drücken oder Strg drücken und gleichzeitig Aktualisieren anklicken
// Have debug on now.
Status.debugLevel = 1;

/**
Twinklefluff revert and antivandalism utillity
*/
var VERSION = '1.0';

// 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 = 'window';
}

/**
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 [[en:WP:TWINKLE|TWINKLE]]
*/
if( typeof( TwinkleConfig.summaryAd ) == 'undefined' ) {
	TwinkleConfig.summaryAd = " (mit [[en:WP:TWINKLE|TWINKLE]] ([[Benutzer:C-M/twinkle.js|de]]))";
}

/**
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' ];
}


// 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 = [
	'HagermanBot',
	'HBC AIV helperbot',
	'HBC AIV helperbot2',
	'HBC AIV helperbot3',
]

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

addOnloadHook( 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 != 'Aktuelle Version' ) {
		// 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', 'rollback' ) );
		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', 'vandalism' ) );
		revVandLink.appendChild( spanTag( 'Black', ']' ) );
		revVandNode.appendChild(revVandLink);

		for(var i in list ) {
			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('span');
		//oldEditLink.href = "javascript:revertToRevision('" + oldrev + "')";

		var oeclass = document.createAttribute("class");
		oeclass.nodeValue = "spanlink";
		oldEditLink.setAttributeNode(oeclass);
                
		var oldClick = document.createAttribute("onclick");
		oldClick.nodeValue = "revertToRevision('" + oldrev + "')";
		oldEditLink.setAttributeNode(oldClick);
		oldEditLink.appendChild( spanTag( 'Black', '[' ) );
		oldEditLink.appendChild( spanTag( 'SaddleBrown', 'diese Version wiederherstellen' ) );
		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 != 'Aktuelle Version' ) {
			// 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 promptNode = document.createElement('strong');

		//var agfLink = document.createElement('span');
		var vandLink = document.createElement('span');
		var normLink = document.createElement('span');
		var promptLink = document.createElement('span');

/*		
		var agfClick = document.createAttribute("onclick");
		agfClick.nodeValue = "revertPage('agf' , '" + vandal + "')";
		agfLink.setAttributeNode(agfClick);
*/
		var vandClick = document.createAttribute("onclick");
		vandClick.nodeValue = "revertPage('vand' , '" + vandal + "')";
		vandLink.setAttributeNode(vandClick);

		var normClick = document.createAttribute("onclick");
		normClick.nodeValue = "revertPage('norm' , '" + vandal + "')";
		normLink.setAttributeNode(normClick);

		var promptClick = document.createAttribute("onclick");
		promptClick.nodeValue = "revertPage('prompt' , '" + vandal + "')";
		promptLink.setAttributeNode(promptClick);

		var vandclass = document.createAttribute("class");
		vandclass.nodeValue = "spanlink";
		vandLink.setAttributeNode(vandclass);

		var normclass = document.createAttribute("class");
		normclass.nodeValue = "spanlink";
		normLink.setAttributeNode(normclass);

		var promptclass = document.createAttribute("class");
		promptclass.nodeValue = "spanlink";
		promptLink.setAttributeNode(promptclass);
/*
		//agfLink.href = "javascript:revertPage('agf' , '" + vandal + "')"; 
		vandLink.href = "javascript:revertPage('vand' , '" + vandal + "')"; 
		normLink.href = "javascript:revertPage('norm' , '" + vandal + "')"; 
		promptLink.href = "javascript:revertPage('prompt' , '" + vandal + "')";
*/

		
		//agfLink.appendChild( spanTag( 'Black', '[' ) );
		//agfLink.appendChild( spanTag( 'DarkOliveGreen', 'zurücksetzen (AGF)' ) );
		//agfLink.appendChild( spanTag( 'Black', ']' ) );

		vandLink.appendChild( spanTag( 'Black', '[' ) );
		vandLink.appendChild( spanTag( 'Red', 'zurücksetzen (Vandalismus)' ) );
		vandLink.appendChild( spanTag( 'Black', ']' ) );

		normLink.appendChild( spanTag( 'Black', '[' ) );
		normLink.appendChild( spanTag( 'SteelBlue', 'zurücksetzen' ) );
		normLink.appendChild( spanTag( 'Black', ']' ) );
		
		promptLink.appendChild( spanTag( 'Black', '[' ) );
		promptLink.appendChild( spanTag( 'Grey', 'zurücksetzen (Begründung)' ) );
		promptLink.appendChild( spanTag( 'Black', ']' ) );


		//agfNode.appendChild(agfLink);
		vandNode.appendChild(vandLink);
		normNode.appendChild(normLink);
		promptNode.appendChild(promptLink);
	
		//var cur = ntitle.insertBefore(agfNode, ntitle.firstChild);
		//cur = ntitle.insertBefore(document.createTextNode(' | '), cur.nextSibling);
		var cur = ntitle.insertBefore(normNode, ntitle.firstChild);
		cur = ntitle.insertBefore(document.createTextNode(' | '), cur.nextSibling);
		cur = ntitle.insertBefore(promptNode, 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();
		Status.debug( 'revertXML' + revertXML );
		revertXML.overrideMimeType('text/xml');

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

		Status.status( 'Querying revisions' );
		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( 'Error: ' + e.what() );
		} else {
			Status.error( 'Error: ' + e );
		}
	}

}
function revertPageCallback() {

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

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

	var doc = revertXML.responseXML.documentElement;

	if( !doc ) {
		Status.error( 'Possible failure in recieving document, will abort.' );
		return;
	}
	var revisions = doc.getElementsByTagName('rev');
	var top = revisions[0];
	Status.debug( 'revisions[0]: ' + top );

	if( top.getAttribute( 'revid' ) < wgCurRevisionId ) {
		Status.error( [ 'The recieved top revision id ', htmlNode( 'strong', top.getAttribute('revid') ), ' is less than our current revision id, this could indicate that the current revision has been deleted, the server is lagging, or that bad data has been recieved. Will stop proceeding at this point.' ] );
		return;
	}
	if( !top ) {
		Status.error( 'No top revision found,  this could indicate that the page has been deleted, or that a problem in the transmittion has occoured, will abort reversion ');
		return;
	}


	Status.status( [ 'Evaluating revisions to see if ', htmlNode( 'strong', vandal), ' is the last contributor...' ] );
	Status.debug( 'wgCurRevisionId: ' + wgCurRevisionId + ', top.getAttribute(revid): ' + top.getAttribute('revid') );

	if( wgCurRevisionId != top.getAttribute('revid') ) {
		Status.warn( [ 'Latest revision ', htmlNode( 'strong', top.getAttribute('revid') ), ' doesn\'t equals our revision ', htmlNode( 'strong', wgCurRevisionId) ] );
		Status.debug( 'top.getAttribute(user): ' + top.getAttribute( 'user' ) );

		if( top.getAttribute( 'user' ) == vandal ) {
			switch( type ) {
				case 'vand':
				Status.info( [ 'Latest revision is made by ', htmlNode( 'strong', vandal ) , ', as we assume vandalism, we continue to revert' ]);
				break;
				case 'afg':
				Status.warn( [ 'Latest revision is made by ', htmlNode( 'strong', vandal ) , ', as we assume good faith, we stop reverting, as the problem might have been fixed.' ]);
				return;
				default:
				Status.warn( [ 'Latest revision is made by ', htmlNode( 'strong', vandal ) , ', but we will stop reverting anyway.' ] );
				return;
			}
		} else if( 
			type == 'vand' && 
			WHITELIST.indexOf( top.getAttribute( 'user' ) ) != -1 && 
			top.nextSibling.getAttribute( 'pageId' ) == wgCurRevisionId 
		) {
			Status.info( [ 'Latest revision is made by ', htmlNode( 'strong', top.getAttribute( 'user' ) ), ', a trusted bot, and the revision before was made by our vandal, so we proceed with the revert.' ] );
			top = top.nextSibling;
		} else {
			Status.error( [ 'Latest revision is made by ', htmlNode( 'strong', top.getAttribute( 'user' ) ), ', so it might already been reverted, stopping  reverting.'] );
			return;
		}
	} 

	if( WHITELIST.indexOf( vandal ) != -1  ) {
		switch( type ) {
			case 'vand':
			Status.info( [ 'Vandalism revert is choosen on ', htmlNode( 'strong', vandal ), ', as this is a whitelisted bot, we assume you wanted to revert vandalism made by the previous user instead.' ] );
			top = top.nextSibling;
			vandal = top.getAttribute( 'user' );

			break;
			case 'agf':
			Status.warn( [ 'Good faith revert is choosen on ', htmlNode( 'strong', vandal ), ', as this is a whitelisted bot, it makes no sense at all to revert it as a good faith edit, will stop reverting.' ] );
			return;

			break;
			case 'norm':
			default:
			var cont = confirm( 'Normal revert is choosen, but the top user (' + vandal + ') is a whitelisted bot, do you want to revert the revision before instead?' );
			if( cont ) {
				Status.info( [ 'Normal revert is choosen on ', htmlNode( 'strong', vandal ), ', as this is a whitelisted bot, and per confirm, we\'ll revert the previous revision instead.' ] );
				top = top.nextSibling;
				vandal = top.getAttribute( 'user' );
			} else {
				Status.warn( [ 'Normal revert is choosen on ', htmlNode( 'strong', vandal ), ', this is a whitelisted bot, bet per confirm, revert will proceed.' ] );
			}
			break;
		}
	}

	Status.status( 'Suche die letzte Version...' );

	goodRev = top;
	nbrOfRevisions = 0;

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

		goodRev = goodRev.nextSibling;

		nbrOfRevisions++;

		if( goodRev == null ) {
			Status.error( [ 'keine vorherige Version gefunden, eventuell ist ', htmlNode( 'strong', vandal ), ' der einzige Bearbeiter, oder er hat mehr als ' + TwinkleConfig.revertMaxRevisions + ' Bearbeitungen hintereinander getätigt.' ] );
			return;
		}
	}

	if( nbrOfRevisions == 0 ) {
		Status.error( "We where to revert zero revisions. As that makes no sense, we'll stop reverting this time. It could be that the edit already have been reverted, but the revision id was still the same." );
		return;
	}

	if( 
		type != 'vand' && 
		nbrOfRevisions > 1  && 
		!confirm( vandal + ' hat den Artikel ' + nbrOfRevisions + ' mal hinterinander bearbeitet - alles zurücksetzen?' ) 
	) {
		Status.info( 'Stoppe auf Benutzerwunsch.' );
		return;
	}

	Status.progress( [ ' revision ', htmlNode( 'strong', goodRev.getAttribute( 'revid' ) ), ' that was made ', htmlNode( 'strong', nbrOfRevisions ), ' revisions ago by ', htmlNode( 'strong', goodRev.getAttribute( 'user' ) ) ] );

	Status.status( [ 'Lade den Inhalt der Revision ', htmlNode( 'strong', goodRev.getAttribute( 'revid' ) ) ] );
	var query = {
		'action': 'query',
		'prop': 'revisions',
		'titles': wgPageName,
		'rvlimit': 1,
		'rvprop': 'content',
		'rvstartid': goodRev.getAttribute( 'revid' ),
		'format': 'xml'
	}

	Status.debug( 'query:' + query.toSource() );

	// 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( 'Statusfehler, breche ab' );
		return;
	}

	contentDoc = revertXML.responseXML.documentElement;
	if( !contentDoc ) {
		Status.error( 'Keine Version zum Zurücksetzen gefunden, breche ab.');
		return;
	}

	Status.status( 'Hole Editfenster...' );

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

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

	Status.debug( 'query:' + query.toSource() );

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

function selectCustomRevertReason(){ // von PDD übernommen
 var detailgrund = prompt("Grund des Reverts?\n"
 + "Mögliche Shortcuts:"
 + "\n for: \t keine Weblinks zu Foren"
 + "\n web: \t ungeeignete Webseite"
 + "\n pop: \t Webeite mit ung. Navigation"
 + "\n dis: \t Diskussionsseite"
 + "\n rere: \t Konsens finden"
 + "\n va: \t Vandalismus"
 + "\n ba: \t Barbarismus"
 + "\n er: \t Eigenrevert"
 + "\n unt: \t Signieren"
 + "\n unf: \t Unfall"
 + "\n twl: \t keine Weblinks im Fließtext"
 + "\n blau: \t Überverlinkung"
 + "\n komm: \t Kommentare auf die Diskussion"
 + "\n qa: \t Änderungen mit Quelle begründen"
 + "\n rl: \t Relevanz fraglich"
 + "\n pov: \t [[WP:NPOV]] beachten"
 + "\n wl: \t Ver-/Entlinkung begründen "
 + "\n loe: \t Löschungen begründen"
 + "\n wwni: \t Textform nicht enzyklopädisch"
 + "\n enz: \t ungenügende Textqualität"                 
 
 , "Unfug bzw. Vandalismus");
   if (detailgrund == null) return;
 
//   detailgrund = trim(detailgrund);
   // detailgrund-shortcuts von [[Benutzer:-jha-]]
   switch (detailgrund) {
      case "for":  detailgrund='Bitte keine Weblinks zu Foren, Blogs oder Fanseiten (siehe auch [[WP:WEB]]).';
                   break;
      case "web":  detailgrund='Link zu nicht zielführender Website entfernt (siehe auch [[WP:WEB]]).';
                   break;
      case "pop":  detailgrund='Link führte zu Website mit bevormundender Navigation (siehe auch [[WP:WEB]]).';
                   break;
      case "dis":  detailgrund='Bitte Diskussionsseite beachten.';
                   break;
      case "rere": detailgrund='Bitte zunächst auf der Diskussionsseite einen Konsens herstellen.';
                   break;
      case "va":   detailgrund='Grund: Vandalismus.';
                   break;
      case "ba":   detailgrund='Grund: Barbarismus.';
                   break;
      case "er":   detailgrund='Eigenrevert! (Ich muss wohl mal wieder zum Optiker...)';
                   break;
      case "unt":  detailgrund='Nicht unterschriebenen Diskussionsbeitrag entfernt (siehe auch [[WP:SIG]]).';
                   break;
      case "unf":  detailgrund='Grund: Unfall in der Editbox';
                   break;
      case "twl":  detailgrund='Bitte keine Weblinks im Artikeltext selbst angeben (siehe auch [[WP:WEB]]).';
                   break;
      case "blau": detailgrund='Bitte keine extreme Überverlinkung (siehe auch [[WP:BLAU]]).';
                   break;
      case "komm": detailgrund='Kommentare gehören nicht in den Artikel, sondern auf die Diskussionsseite.';
                   break;
      case "qa":   detailgrund='Anonyme Änderungen bitte ggf. mit Fundstellen/Belegen/Quellen begründen';
                   break;
      case "rl":   detailgrund='Relevanz fraglich.'
                   break;
      case "pov":  detailgrund='Beitrag widerspricht dem Grundsatz des Neutralen Standpunktes. Lob und Kritik müssen durch relevante Quellen belegt werden. Bitte [[WP:NPOV]] beachten.';
                   break;
      case "wl":   detailgrund='Nicht begründete/nachvollziehbare Ver-/Entlinkung. Bitte begründen! ([[WP:ZQ|Zusammenfassung und Quellen]] oder ggf. Diskussionsseite nutzen.)';
                   break;
      case "loe":  detailgrund='Nicht begründete/nachvollziehbare Löschung. Bitte begründen! ([[WP:ZQ|Zusammenfassung und Quellen]] oder ggf. Diskussionsseite nutzen.)';
                   break;
      case "wwni": detailgrund='Form des Beitrages vermittelt kein enzylopädisches Wissen. Bitte die Grundsätze in [[WP:WWNI|Was Wikipedia nicht ist]] beachten.';
                   break;
      case "enz":  detailgrund='Beitrag nicht von enzyklopädischer Textqualität. Bitte "[[WP:WSIGA|Wie schreibe ich einen guten Artikel]]" beachten.';
                   break;
   }

   return detailgrund;

}

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

	if( revertXML.status != 200 ){
		Status.error( 'Statusfehler, breche ab' );
		return;
	}

	Status.status( 'Bearbeite Artikel...' );

	var doc = revertXML.responseXML;

	var form = doc.getElementById( 'editform' );
	Status.debug( 'editform: ' + form );
	if( !form ) {
		Status.error( 'Serverfehler - konnte das Editformular nicht finden, breche ab.' );
		return;
	}
	form.style.display = 'none';


	var content = contentDoc.getElementsByTagName('rev')[0];
	if( !content ) {
		Status.error( 'Keine Revision gefunden, breche ab!' );
		return;
	}

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

	textbox.value = "";

	var cn =  content.childNodes;

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

	Status.status( 'Schreibe Bearbeitungskommentar...' );
	var summary;



	switch( type ) {
		case 'agf':
		summary = "Änderungen von [[Special:Contributions/" + vandal + "|" + vandal + "]] rückgängig gemacht. Bitte [[Hilfe:Erste Schritte]] lesen. Danke!" + TwinkleConfig.summaryAd;
		break;
		case 'vand':
			summary = "[[Wikipedia:Vandalismus|Vandalismus]] von [[Special:Contributions/" + vandal + "|" + vandal + "]] rückgängig gemacht und letzte Version von [[User:" + goodRev.getAttribute( 'user' ) + "|" + goodRev.getAttribute( 'user' ) + "]] wiederhergestellt." + TwinkleConfig.summaryAd;
		break;
		case 'prompt':
		
			var myreason = selectCustomRevertReason();
			if (myreason == null) return;
			summary = "Zurückgesetzt: " + myreason + TwinkleConfig.summaryAd;
		break;
		case 'norm':
		summary = "Änderungen von [[Special:Contributions/" + vandal + "|" + vandal + "]] rückgängig gemacht und letzte Version von [[User:" + goodRev.getAttribute( 'user' ) + "|" + goodRev.getAttribute( 'user' ) + "]] wiederhergestellt." + 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( [ 'Öffne Benutzerdiskussion von ' + vandal + '... ', htmlNode( 'strong', vandal ) ]);

	var opentalk = true;

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

		if( isIPAddress( vandal ) ) {
			Status.info( [ htmlNode( 'strong', vandal ), ' ist eine IP-Adresse, überprüfe ob sie zu einem AOL-Proxy gehört' ] );

			if( AOLNetworks.some( function( net ) { return isInNetwork( vandal, net ) } )) {
				if( TwinkleConfig.openAOLAnonTalkPage ) {
					Status.info( [ htmlNode( 'strong', vandal ), ' ist ein AOL-Proxy - öffne aufgrund der Konfiguration trotzdem die Benutzerdiskussion' ] );
				} else {
					Status.warn( [ htmlNode( 'strong', vandal ), ' ist ein AOL-Proxy - öffne die Benutzerdiskussion nicht, da die Adressen zufällig vergeben werden.' ] );
					opentalk = false;
				}
			} else {
				Status.info( [ htmlNode( 'strong', vandal ), ' ist eine normale IP-Adresse, öffne die Benutzerdiskussion' ] );
			}

		}

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

			Status.debug( 'query:' + query.toSource() );

			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( 'Versende Formular...' );
	form.submit();
}

function revertToRevision( oldrev ) {

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

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

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

		Status.status( 'Querying revision' );
		revertXML.onreadystatechange = revertToRevisionCallback;
		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( 'Error: ' + e.what() );
		} else {
			Status.error( 'Error: ' + e );
		}
	}

}

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

	if( revertXML.status != 200 ){
		Status.error( 'Statusfehler, breche ab' );
		return;
	}

	contentDoc = revertXML.responseXML.documentElement;

	Status.status( 'Hole Editfenster...' );

	revertXML = sajax_init_object();
	revertXML.overrideMimeType('text/xml');
	revertXML.onreadystatechange = revertToRevisionCallback2;
	revertXML.open( 'GET' , mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + QueryString.create( { 'title': wgPageName, 'action': 'submit' } ), true );
	revertXML.send( null );
}

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

	if( revertXML.status != 200 ){
		Status.error( 'Statusfehler, breche ab' );
		return;
	}

	Status.status( 'Bearbeite Artikel...' );

	var doc = revertXML.responseXML;

	var form = doc.getElementById( 'editform' );
	Status.debug( 'editform: ' + form );
	if( !form ) {
		Status.error( 'Serverfehler - konnte das Editformular nicht finden, breche ab.' );
		return;
	}
	form.style.display = 'none';


	var content = contentDoc.getElementsByTagName('rev')[0];

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

	textbox.value = "";

	var cn =  content.childNodes;

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

	Status.status( 'Schreibe Bearbeitungskommentar...' );
	var summary = 'Auf Revision ' + content.getAttribute( 'revid' ) + ' von [[User:' + content.getAttribute( 'user' ) + '|' + content.getAttribute( 'user' ) + ']] zurückgesetzt.' +TwinkleConfig.summaryAd;

	doc.getElementById( 'wpSummary' ).value = summary;

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

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

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

	Status.status( 'Versende Formular...' );
	form.submit();
}