User:EhJJ/twinklespeedy.js

From Wiktionary

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
// If TwinkleConfig aint exist.
if( typeof( TwinkleConfig ) == 'undefined' ) {
	TwinkleConfig = {};
}

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

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


/**
 TwinkleConfig.watchSpeedyPages (array)
 What types of actions that should result in forced addition to watchlist
 */
if( typeof( TwinkleConfig.watchSpeedyPages ) == 'undefined' ) {
	TwinkleConfig.watchSpeedyPages = [ 'G3', 'G10', 'G11', 'G12' ];
}

/**
 TwinkleConfig.markSpeedyPagesAsMinor (boolean)
 If, when applying speedy template to page, to mark the edit as minor, default true
 */
if( typeof( TwinkleConfig.markSpeedyPagesAsMinor ) == 'undefined' ) {
	TwinkleConfig.markSpeedyPagesAsMinor = true;
}

/**
 TwinkleConfig.notifyUserOnSpeedyDeletionNomination (array)
 What types of actions that should result that the author of the page should be notified of nomination
 */
if( typeof( TwinkleConfig.notifyUserOnSpeedyDeletionNomination ) == 'undefined' ) {
	TwinkleConfig.notifyUserOnSpeedyDeletionNomination = [ 'G1', 'G2', 'G3', 'G4', 'G10', 'G11', 'G12', 'A1', 'A2', 'A3', 'A4', 'A5', 'I1', 'T1' ];
} 

/**
 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.deleteTalkPageOnDelete
 If talk page if exists should also be deleted (QD G8) when speedying a page (admin only)
 */
if( typeof( TwinkleConfig.deleteTalkPageOnDelete ) == 'undefined' ) {
	TwinkleConfig.deleteTalkPageOnDelete = false;
}

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

/**
 TwinkleConfig.orphanNormalPagesOnSpeedyDelete (hash)
 Defines if all backlinks to a page should be removed.
 property 'exclude' defined actions not to orphan
 */
if( typeof( TwinkleConfig.orphanBacklinksOnSpeedyDelete ) == 'undefined' ) {
	TwinkleConfig.orphanBacklinksOnSpeedyDelete = { exclude: ['G6'], orphan:true };
}

function twinklespeedy() {
	if( wgNamespaceNumber < 0 || wgCurRevisionId == false ) {
		return;
	}
	if( userIsInGroup( 'sysop' ) ) {
		mw.util.addPortletLink( 'p-cactions', "javascript:twinklespeedy.callback()", "qd", "tw-csd", "Quick delete according to WT:QD", "");
	} else if (twinkleConfigExists) {
		mw.util.addPortletLink( 'p-cactions', "javascript:twinklespeedy.callback()", "qd", "tw-csd", "Request quick deletion according to WT:QD", "");
	}
	else
	{
		mw.util.addPortletLink('p-cactions', 'javascript:alert("Your account is too new to use Twinkle.");', 'qd', 'tw-csd', 'Request quick deletion according to WT:QD', '');
	}
}
$(twinklespeedy);

twinklespeedy.callback = function twinklespeedyCallback() {
	var Window = new SimpleWindow( 800, 400 );
	Window.setTitle( "Choose criteria for quick deletion" );

	var form = new QuickForm( userIsInGroup( 'sysop' ) ? twinklespeedy.callback.evaluateSysop : twinklespeedy.callback.evaluateUser, 'change' );
	if( userIsInGroup( 'sysop' ) ) {
		form.append( {
				type: 'checkbox',
				list: [
					{
						label: 'Tag page only, don\'t delete',
						value: 'tag_only',
						name: 'tag_only',
						tooltip: 'If you just want to tag the page, instead of deleting it now',
						event: function( event ) {
							event.target.form.notify.disabled = ! event.target.checked;
							event.stopPropagation();
						}
					},
					{
						label: 'Orphan backlinks',
						value: 'orphan_backlinks',
						name: 'orphan_backlinks',
						tooltip: 'If you want to orphan all backlinks to current page, if checked, excludes will still apply',
						checked: TwinkleConfig.orphanBacklinksOnSpeedyDelete.orphan,
						event: function( event ) {
							TwinkleConfig.orphanBacklinksOnSpeedyDelete.orphan = event.target.checked;
							event.stopPropagation();
						}
					}
				]
			} );
	}

	form.append( {
			type: 'checkbox',
			list: [
				{
					label: 'Notify if possible',
					value: 'notify',
					name: 'notify',
					tooltip: 'Check if you would like the original author to know that this page has been marked for deletion.',
					checked: true,
				/*	disabled: userIsInGroup( 'sysop' ),  //No reason for sysops not to notify	*/
					event: function( event ) {
						event.stopPropagation();
					}
				}
			]
		}
	);
	if( wgNamespaceNumber ==  Namespace.IMAGE ) {
		form.append( {type:'header', label:'Images/Media' } );
		form.append ( {
				type: 'radio',
				name: 'csd',
				list: [
					{ 
						label: 'I1: Prohibited image',
						value: 'prohibitedimage',
						tooltip: 'Most media uploads are not allowed on Simple English Wiktionary. They should be uploaded to Wikimedia Commons instead. There are a few exceptions to this rule. Firstly, all spoken articles should be uploaded here, as they are for local use. Secondly, there are some logos that Commons does not accept, but are needed here, for example Image:Wiki.png, which is used as the Wiktionary logo.' 
					},
					
				]
			} );
	}

	form.append( { type:'header', label:'General criteria' } );
	form.append( {
			type: 'radio',
			name: 'csd',
			list: [
				{ 
					label: 'G1: Nonsense', 
					value: 'nonsense', 
					tooltip: 'All of the text is nonsense. Nonsense includes content that does not make sense or is not meaningful. However, this does not include bad writing, bad words, vandalism, things that are fake or impossible, or parts which are not in English. ' },
				{ 
					label: 'G2: Test page',
					value: 'test',
					tooltip: 'It is a test page, such as "Can I really create a page here?".' 
				},
				{ 
					label: 'G3: Complete vandalism',
					value: 'vandalism',
					tooltip: 'The content is completely vandalism.'
				},
				{ 
					label: 'G3: Pagemove vandalism', 
					value: 'pagemove',
					tooltip: 'Nonsense redirects that are created from the cleanup of page move vandalism'
				},
				{
					label: 'G4: Recreation of deleted material already deleted at RfD',
					value: 'repost',
					tooltip: 'Creation of content that is already deleted. It includes an identical or similar copy, with any title, of a page that was deleted, after being discussed in Requests for deletion, unless it was undeleted due to another discussion or was recreated in the user space. Before deleting again, the Administrator should be sure that the content is similar and not just a new article on the same subject. This rule cannot be used if the content had already been quickly deleted before.'
				},
//No G5 on this wiki
				{
					label: 'G6: History merge', 
					value: 'histmerge',
					tooltip: 'Temporarily deleting a page in order to merge page histories' 
				},
				{
					label: 'G6: Make way for move', 
					value: 'move',
					tooltip: 'Making way for a move like reversing a redirect' 
				},
				{
					label: 'G6: Closed Request for deletion as delete',
					value: 'afd',
					tooltip: 'An admin has closed a Requests for deletion debate as a "delete"'
				},
				{
					label: 'G6: Housekeeping',
					value: 'g6',
					tooltip: 'Other non-controversial "housekeeping" tasks'
				},
				{
					label: 'G7: Author requests deletion',
					value: 'author',
					tooltip: 'Any page whose original author wants deletion, can be quickly deleted, but only if most of the page was written by that author and was created as a mistake. If the author blanks the page, this can mean that he or she wants it deleted.'
				},
				{
					label: 'G7: Author blanked',
					value: 'blanked',
					tooltip: ' If the author blanks the page, this can be taken as a deletion request'
				},
				{
					label: 'G8: Pages dependent on deleted or non-existent pages',
					value: 'talk',
					tooltip: '... can be deleted, unless they contain discussion on deletion that can\'t be found anywhere else. Subpages of a talk page can only be deleted under this rule if their top-level page does not exist. This also applies to broken redirects. However, this cannot be used on user talk pages or talk pages of images on Commons.'
				},
// No G9, as this is not a criterion that is used frequently
				{ 
					label: 'G10: Attack page',
					value: 'attack', 
					tooltip: 'Pages that were only created to insult a person or thing (such as "John Q. Doe is dumb"). This includes articles on a living person that is insult and without sources, where there is no NPOV version in the edit history to revert to.'
				},
				{ 
					label: 'G11: Obvious advertising',
					value: 'spam', 
					tooltip: 'Pages which were created only to say good things about a company, item, group or service and which would need to be written again so that they can sound like an encyclopedia. However, simply having a company, item, group or service as its subject does not mean that an article can be deleted because of this rule: an article that is obvious advertising should have content that shouldn\'t be in an encyclopedia. If a page has already gone through RfD or QD and was not deleted, it should not be quickly deleted using this rule.'
				},
				{ 
					label: 'G12: Obviously breaking copyright law', 
					value: 'copyvio', 
					tooltip: 'Obviously breaking copyright law like a page which is 1) Copied from another website which does not have a license that can be used with Wiktionary; 2) Containing no content in the page history that is worth being saved. 3) Made by one person instead of being created on wiki and then copied by another website such as one of the many Wiktionary mirror websites. 4) Added by someone who doesn\'t tell if he got permission to do so or not, or if his claim has a large chance of not being true;' 
				}
			]
		});
if( wgNamespaceNumber ==  0 || wgNamespaceNumber == 1 ) {
	form.append( { type:'header', label:'Articles' } );
	form.append( {
			type: 'radio',
			name: 'csd',
			list: [
				{
					label: 'A1: Little or no meaning',
					value: 'nocontext',
					tooltip: 'Is very short and providing little or no meaning (e.g., "He is a funny man that has created Factory and the Hacienda. And, by the way, his wife is great."). Having a small amount of content is not a reason to delete if it has useful information.'
				},
				{
					label: 'A2: No content',
					value: 'nocontent',
					tooltip: 'Has no content. This includes any article consisting only of links (including hyperlinks, category tags and "see also" sections), a rephrasing of the title, and/or attempts to correspond with the person or group named by its title. This does not include disambiguation pages.'
				},
				{
					label: 'A3: Article that exists on another Wikimedia project',
					value: 'transwiki',
					tooltip: 'Has been copied and pasted from another Wiktionary: Any article or section from an article that has been copied and pasted with little or no change.'
				},
                                {
					label: 'A4: People, groups, companies or websites that are not notable.',
					value: 'notability',
					tooltip: 'An article about a real person, group of people, band, club, company, or web content that does not say why it is important. If not everyone agrees that the subject is not notable or there has been a previous RfD, the article may not be quickly deleted, and should be discussed at RfD instead.'
				},
				{
					label: 'A5: Not written in English',
					value: 'foreign',
					tooltip: 'Any article that is not written in English. An article that is written in any other languages but English.'
				},
				{
					label: 'A6: Obvious hoax',
					value: 'hoax',
					tooltip: 'Is an obvious hoax. An article that is surely fake or impossible.'
				},
/** Get rid of these for now				
				{
					label: 'A7: Unremarkable person',
					value: 'person',
					tooltip: 'An article about a real person that does not assert the importance or significance of its subject. If controversial, or if there has been a previous AfD that resulted in the article being kept, the article should be nominated for AfD instead'
				},
				{
					label: 'A7: Unremarkable band',
					value: 'band',
					tooltip: 'Article about a band, singer, musician, or musical ensemble that does not assert the importance or significance of the subject'
				},
				{
					label: 'A7: Unremarkable club',
					value: 'club',
					tooltip: 'Article about a club that does not assert the importance or significance of the subject'
				},
				{
					label: 'A7: Unremarkable company',
					value: 'corp',
					tooltip: 'Article about a company or corporation that does not assert the importance or significance of the subject'
				},
				{
					label: 'A7: Unremarkable website',
					value: 'web',
					tooltip: 'Article about a web site, blog, online forum, webcomic, podcast, or similar web content that does not assert the importance or significance of its subject'
				},
				{
					label: 'A9: Unremarkable musical recording',
					value: 'album',
					tooltip: 'An article about a musical recording which does not indicate why its subject is important or significant, and where the artist\'s article has never existed or has been deleted'
				}
**/
			]
		} );
}
	form.append( { type:'header', label: 'Redirects' } );
	form.append( {
			type: 'radio',
			name: 'csd',
			list: [
				{ 
					label: 'R1: Redirects to pages that do not exist',
					value: 'redirnone'
				},
				{ 
					label: 'R2: Redirects to the User: or User_talk: space from the main article space and vise versa', 
					value: 'rediruser', 
					tooltip: 'Redirects to the User: or User_talk: space from the main article space and vise versa. If this was because of a page move, please wait a day or two before deleting the redirect.'
				},
				{ 
					label: 'R3: Redirects with an uncommon typo', 
					value: 'redirtypo', 
					tooltip: 'Redirects from common accidental spellings are usually useful; redirects in other languages are not deletable using this rule.'
				}
			]
		} );
if( wgNamespaceNumber ==  14 || wgNamespaceNumber == 15 ) {
	form.append( { type:'header', label: 'Categories' } );
	form.append( {
			type: 'radio',
			name: 'csd',
			list: [
				{ 
					label: 'C1: Empty categories',
					value: 'catempty',
					tooltip: '(with no articles or subcategories for at least four days) whose only content includes links to parent categories. However, this can not be used on categories still being discussed on WT:RfD, or disambiguation categories. If the category wasn\'t newly made, it is possible that it used to have articles, and more inspection is needed.'
				},
				{
					label: 'C2: Quick renaming',
					value: 'catqr',
					tooltip: 'Empty categories that have already been renamed.'
				},
				{
					label: 'C3: Template categories',
					value: 'catfd',
					tooltip: 'If a category contains articles from only one template (such as Category:Cleanup needed from \{\{cleanup\}\}) and the template is deleted after being discussed, the category can also be deleted without being discussed.'
				}
			]
		} );
} if( wgNamespaceNumber ==  2 || wgNamespaceNumber == 3 ) {
	form.append( { type:'header', label: 'User pages' } );
	form.append( {
			type: 'radio',
			name: 'csd',
			list: [
				{
					label: 'U1: User request',
					value: 'userreq',
					tooltip: 'User pages can be deleted if its user wants to, but there are some exceptions. '
				},
				{
					label: 'U2: Non-existent user',
					value: 'nouser',
					tooltip: 'User pages of users that do not exist. Administrators should check Special:Contributions and Special:DeletedContributions.'
				},
			]
		} );
} if( wgNamespaceNumber ==  10 || wgNamespaceNumber == 11 ) {
	form.append( { type:'header', label: 'Templates' } );
	form.append( {
			type: 'radio',
			name: 'csd',
			list: [

				{ 
					label: 'T1: They are insulting or hateful',
					value: 'divisive'
				},
			]
		} );
} 

	var result = form.render();
	Window.setContent( result );
	Window.display();
}

twinklespeedy.normalizeHash = {
	'nonsense': 'G1',
	'test': 'G2',
	'vandalism': 'G3',
	'pagemove': 'G3',
	'repost': 'G4',
	'histmerge': 'G6',
	'move': 'G6',
	'afd': 'G6',
	'g6': 'G6',
	'author': 'G7',
	'blanked': 'G7',
	'talk': 'G8',
	'attack': 'G10',
	'spam': 'G11',
	'copyvio': 'G12',
	'nocontext': 'A1',
	'nocontent': 'A2',
	'transwiki': 'A3',
	'notability': 'A4',
	'foreign': 'A5',
	'hoax': 'A6',
/** NOT USED FOR NOW
	'person': 'a7',
	'corp': 'a7',
	'web': 'a7',
	'band': 'a7',
	'club': 'a7',
	'album': 'a9',
**/
	'redirnone': 'R1',
	'rediruser': 'R2',
	'redirtypo': 'R3',
	'prohibitedimage': 'I1',
	'catempty': 'C1',
	'catqd': 'C2',
	'catfd': 'C3',
	'userreq': 'U1',
	'nouser': 'U2',
	'divisive': 'T1',
};

twinklespeedy.reasonHash = {
	'nonsense': 'was all nonsense',
	'test': 'was a test page',
	'vandalism': 'was vandalism',
	'pagemove': 'was a redirect created during cleanup of page move vandalism',
	'repost': 'was a copy of a page that was deleted by RfD',
	'histmerge': 'was in the way of trying to fix or clean up something',
	'move': 'was in the way of making a move',
	'afd': 'was closed as delete in a RfD',
	'g6': 'was housekeeping',
	'author': 'was asked to be deleted by the author',
	'blanked': 'was implied to be deleted by the author',
	'talk': 'was a talk page of a page that does not exist',
	'attack': 'was an attack page',
	'spam': 'was advertising',
	'copyvio': 'was breaking copyright law',
	'nocontext': 'was a page that had little or no meaning',
	'nocontent': 'was a page that had no content', 
	'transwiki': 'was copied from another Wiktionary',
	'notability': 'was a page that didn\'t say why the subject was notable',
	'foreign': 'was not written in English',
	'hoax': 'was obviously a hoax (not true)',
/** NOT USED ON THIS WIKI
	'person' : 'was an article about a real person that didn\'t assert the importance or significance of its subject',
	'web': 'was an article about a web site, blog, online forum, webcomic, podcast, or similar web content that didn\'t assert the importance or significance of its subject',
	'corp': 'was an article about a company or corporation that didn\'t assert the importance or significance of its subject',
	'club': 'was an article about a club that didn\'t assert the importance or significance of the subject',
	'band': 'was an article about a band, singer, musician, or musical ensemble that didn\'t assert the importance or significance of the subject',
	'album': 'was an article about a musical recording which does not indicate why its subject is important or significant, and where the artist\'s article has never existed or has been deleted',
**/
	'redirnone': 'was a redirect to a page that does not exist',
	'rediruser': 'was a redirect to the Talk:, User: or User talk: space',
	'redirtypo': 'was a redirect with an uncommon typo',
	'prohibitedimage': 'was an image/media that is not allowed on Wiktionary',
	'catempty': 'was an empty category',
	'catqr': 'was a renamed category',
	'catfd': 'was a category containing articles from a now deleted template',
	'userreq': 'was a user page whose user requested deletion',
	'nouser': 'was a user page of a user that did not exist',
	'divisive': 'was an insulting or hateful template',
};

twinklespeedy.callbacks = {
	sysop: {
		main: function( self ) {
			var xmlDoc = self.responseXML;
			var normal = xmlDoc.evaluate( '//normalized/n/@to', xmlDoc, null, XPathResult.STRING_TYPE, null ).stringValue;
			if( normal ) {
				wgPageName = normal;
			}
			var exists = xmlDoc.evaluate( 'boolean(//pages/page[not(@missing)])', xmlDoc, null, XPathResult.BOOLEAN_TYPE, null ).booleanValue;

			if( ! exists ) {
				self.statelem.error( "It seems that the page doesn't exist, perhaps it has already been deleted" );
				return;
			}
			var query = { 
				'title': wgPageName, 
				'action': 'delete'
			};

			var wikipedia_wiki = new Wikipedia.wiki( 'Deleting page', query, twinklespeedy.callbacks.sysop.deletePage );
			wikipedia_wiki.params = self.params;
			wikipedia_wiki.followRedirect = false;
			wikipedia_wiki.get();

			if( 
				TwinkleConfig.deleteTalkPageOnDelete && 
				self.params.normalized != 'i8' &&
				wgNamespaceNumber % 2 == 0 && 
				document.getElementById( 'ca-talk' ).className != 'new' 
			) {
				var talk_page = namespaces[ wgNamespaceNumber  + 1 ] + ':' + wgTitle;
				var query = query = {
					'title': talk_page,
					'action': 'delete'
				};
				var wikipedia_wiki = new Wikipedia.wiki( 'Deleting talk page', query, twinklespeedy.callbacks.sysop.deleteTalkPage );
				wikipedia_wiki.params = self.params;
				wikipedia_wiki.followRedirect = false;
				wikipedia_wiki.get();
			}

			if( wgNamespaceNumber == 6 && self.params.normalized != 'i8' ) {
				var query = {
					'action': 'query',
					'list': 'imageusage',
					'titles': wgPageName,
					'iulimit': userIsInGroup( 'sysop' ) ? 5000 : 500 // 500 is max for normal users, 5000 for bots and sysops
				};
				var wikipedia_api = new Wikipedia.api( 'Grabbing image links', query, twinklespeedy.callbacks.sysop.unlinkImageInstancesMain );
				wikipedia_api.params = self.params;
				wikipedia_api.post();
			}
			var doOrphan = TwinkleConfig.orphanBacklinksOnSpeedyDelete;
			if( 
				doOrphan.orphan && 
				doOrphan.exclude.indexOf( self.params.normalized.toLowerCase() ) == -1 
			) {
				var query = {
					'action': 'query',
					'list': 'backlinks',
					'blfilterredir': 'nonredirects',
					'bltitle': wgPageName,
					'bllimit': userIsInGroup( 'sysop' ) ? 5000 : 500, // 500 is max for normal users, 5000 for bots and sysops
					'blnamespace': [0, 100] // Main namespace and portal namespace only, keep on talk pages.
				};
				var wikipedia_api = new Wikipedia.api( 'Grabbing backlinks', query, twinklespeedy.callbacks.sysop.unlinkBacklinksMain );
				wikipedia_api.params = self.params;
				wikipedia_api.post();
			}
			var query = {
				'action': 'query',
				'list': 'backlinks',
				'blfilterredir': 'redirects',
				'bltitle': wgPageName,
				'bllimit': userIsInGroup( 'sysop' ) ? 5000 : 500 // 500 is max for normal users, 5000 for bots and sysops
			};
			var wikipedia_api = new Wikipedia.api( 'Grabbing redirects', query, twinklespeedy.callbacks.sysop.deleteRedirectsMain );
			wikipedia_api.params = self.params;
			wikipedia_api.post();

		},
		unlinkBacklinksMain: function( self ) {
			var xmlDoc = self.responseXML;
			var snapshot = xmlDoc.evaluate('//backlinks/bl/@title', xmlDoc, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null );

			if( snapshot.snapshotLength == 0 ) {
				return;
			}

			var statusIndicator = new Status('Removing backlinks', '0%');

			var total = snapshot.snapshotLength * 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();
			if( snapshot.snapshotLength == 0 ) {
				statusIndicator.info( '100% (completed)' );
				Wikipedia.removeCheckpoint();
				return;
			}

			var params = clone( self.params );
			params.current = 0;
			params.total = total;
			params.obj = statusIndicator;
			params.page = wgPageName;


			for ( var i = 0; i < snapshot.snapshotLength; ++i ) {
				var title = snapshot.snapshotItem(i).value;
				var query = {
					'title': title,
					'action': 'submit'
				}
				var wikipedia_wiki = new Wikipedia.wiki( "Unlinking on " + title, query, twinklespeedy.callbacks.sysop.unlinkBacklinks );
				wikipedia_wiki.params = params;
				wikipedia_wiki.onloading = onloading;
				wikipedia_wiki.onloaded = onloaded;
				wikipedia_wiki.onsuccess = onsuccess;
				wikipedia_wiki.get();
			}
		},
		unlinkBacklinks: function( self ) {
			var form = self.responseXML.getElementById('editform');
			var text = form.wpTextbox1.value;
			var old_text = text;
			var wikiPage = new Mediawiki.Page( text );
			wikiPage.removeLink( self.params.page );

			text = wikiPage.getText();
			if( text == old_text ) {
				// Nothing to do, return
				self.onsuccess( self );
				Wikipedia.actionCompleted( self );
				return;
			}
			var postData = {
				'wpMinoredit': (typeof form.wpMinoredit == "undefined") ? undefined : (form.wpMinoredit.checked ? 1 : undefined),
				'wpWatchthis': undefined,
				'wpStarttime': form.wpStarttime.value,
				'wpEdittime': form.wpEdittime.value,
				'wpAutoSummary': form.wpAutoSummary.value,
				'wpEditToken': form.wpEditToken.value,
				'wpSummary': 'Removing backlinks to ' + self.params.page + " that has been speedily deleted per ([[WT:QD#" + self.params.normalized.toUpperCase() + "|QD " + self.params.normalized.toUpperCase() + "]])" + "; " + TwinkleConfig.deletionSummaryAd,
				'wpTextbox1': text
			};
			self.post( postData );
		},
		deleteRedirectsMain: function( self ) {
			var xmlDoc = self.responseXML;
			var snapshot = xmlDoc.evaluate('//backlinks/bl/@title', xmlDoc, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null );

			var total = snapshot.snapshotLength * 2;

			if( snapshot.snapshotLength == 0 ) {
				return;
			}

			var statusIndicator = new Status('Deleting redirects', '0%');

			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();
			if( snapshot.snapshotLength == 0 ) {
				statusIndicator.info( '100% (completed)' );
				Wikipedia.removeCheckpoint();
				return;
			}

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


			for ( var i = 0; i < snapshot.snapshotLength; ++i ) {
				var title = snapshot.snapshotItem(i).value;
				var query = {
					'title': title,
					'action': 'delete'
				}
				var wikipedia_wiki = new Wikipedia.wiki( "Deleting " + title, query, twinklespeedy.callbacks.sysop.deleteRedirects );
				wikipedia_wiki.params = params;
				wikipedia_wiki.onloading = onloading;
				wikipedia_wiki.onloaded = onloaded;
				wikipedia_wiki.onsuccess = onsuccess;
				wikipedia_wiki.followRedirect = false;
				wikipedia_wiki.get();
			}
		},
		deleteRedirects: function( self ) {
			var form = this.responseXML.getElementById( 'deleteconfirm' );
			if( ! form ) { // Hell, image deletion is b0rked :(
				form = this.responseXML.getElementsByTagName( 'form' )[0];
				var postData = {
					'wpDeleteReasonList': 'other',
					'wpReason': "Quick deleted per ([[WT:QD#R1|QD R1]]), Redirect to deleted page \"" + wgPageName + "\"." + TwinkleConfig.deletionSummaryAd,
					'wpEditToken': form.wpEditToken.value
				}
			} else {

				var postData = {
					'wpWatch': form.wpWatch.checked ? '' : undefined,
					'wpDeleteReasonList': 'other',
					'wpReason': "Quick deleted per ([[WT:QD#R1|QD R1]]), Redirect to deleted page \"" + wgPageName + "\"." + TwinkleConfig.deletionSummaryAd,
					'wpEditToken': form.wpEditToken.value
				}
			}
			self.post( postData );
		},
		unlinkImageInstancesMain: function( self ) {
			var xmlDoc = self.responseXML;
			var snapshot = xmlDoc.evaluate('//imageusage/iu/@title', xmlDoc, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null );

			if( snapshot.snapshotLength == 0 ) {
				return;
			}

			var statusIndicator = new Status('Unlinking instances image', '0%');

			var total = snapshot.snapshotLength * 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();
			if( snapshot.snapshotLength == 0 ) {
					statusIndicator.info( '100% (completed)' );
					Wikipedia.removeCheckpoint();
					return;
			}

			var params = clone( self.params );
			params.current = 0;
			params.total = total;
			params.obj = statusIndicator;
			params.image = wgTitle;

			for ( var i = 0; i < snapshot.snapshotLength; ++i ) {
				var title = snapshot.snapshotItem(i).value;
				var query = {
					'title': title,
					'action': 'submit'
				}
				var wikipedia_wiki = new Wikipedia.wiki( "Unlinking on " + title, query, twinklespeedy.callbacks.sysop.unlinkImageInstances );
				wikipedia_wiki.params = params;
				wikipedia_wiki.onloading = onloading;
				wikipedia_wiki.onloaded = onloaded;
				wikipedia_wiki.onsuccess = onsuccess;
				wikipedia_wiki.get();
			}
		},
		unlinkImageInstances: function( self ) {
			var form = self.responseXML.getElementById('editform');
			var text = form.wpTextbox1.value;
			var old_text = text;
			var wikiPage = new Mediawiki.Page( text );
			wikiPage.commentOutImage( self.params.image, 'Commented out because image was deleted' );

			text = wikiPage.getText();
			if( text == old_text ) {
				// Nothing to do, return
				self.onsuccess( self );
				Wikipedia.actionCompleted( self );
				return;
			}
			var postData = {
				'wpMinoredit': form.wpMinoredit.checked ? '' : undefined,
				'wpWatchthis': undefined,
				'wpStarttime': form.wpStarttime.value,
				'wpEdittime': form.wpEdittime.value,
				'wpAutoSummary': form.wpAutoSummary.value,
				'wpEditToken': form.wpEditToken.value,
				'wpSummary': 'Removing instance of image ' + self.params.image + " that has been speedily deleted per ([[WT:QD#" + self.params.normalized.toUpperCase() + "|QD " + self.params.normalized.toUpperCase() + "]])" + "; " + TwinkleConfig.deletionSummaryAd,
				'wpTextbox1': text
			};
			self.post( postData );
		},
		deletePage: function( self ) {
			var form = this.responseXML.getElementById( 'deleteconfirm' );
			if( ! form ) { // Hell, image deletion is b0rked :(
				form = this.responseXML.getElementsByTagName( 'form' )[0];
				var postData = {
					'wpDeleteReasonList': 'other',
					'wpReason': "Quick deleted per ([[WT:QD#" + self.params.normalized.toUpperCase() + "|QD " + self.params.normalized.toUpperCase() + "]]), " + self.params.reason + "." + TwinkleConfig.deletionSummaryAd,
					'wpEditToken': form.wpEditToken.value
				}
				self.post( postData );
			} else {

				var postData = {
					'wpWatch': (self.params.watch || form.wpWatch.checked) ? '' : undefined,
					'wpDeleteReasonList': 'other',
					'wpReason': "Quick deleted per ([[WT:QD#" + self.params.normalized.toUpperCase() + "|QD " + self.params.normalized.toUpperCase() + "]]), " + self.params.reason + "." + TwinkleConfig.deletionSummaryAd,
					'wpEditToken': form.wpEditToken.value
				}
				self.post( postData );
			}
		},
		deleteTalkPage: function( self ) {
			form = this.responseXML.getElementById( 'deleteconfirm' );

			var postData = {
				'wpWatch': (self.params.watch || form.wpWatch.checked) ? '' : undefined,
				'wpDeleteReasonList': 'other',
				'wpReason': "Quick deleted per ([[WT:QD#g8|QD g8]]), was a talk page of deleted page." + TwinkleConfig.deletionSummaryAd,
				'wpEditToken': form.wpEditToken.value
			}
			self.post( postData );
		}
	},
	user: {
		main: function( self ) {
			var xmlDoc = self.responseXML;

			var exists = xmlDoc.evaluate( 'boolean(//pages/page[not(@missing)])', xmlDoc, null, XPathResult.BOOLEAN_TYPE, null ).booleanValue;

			if( ! exists ) {
				self.statelem.error( "It seems that the page doesn't exists, perhaps it has already been deleted" );
				return;
			}
			var query = { 
				'title': wgPageName, 
				'action': 'submit'
			};

			var wikipedia_wiki = new Wikipedia.wiki( 'Tagging page', query, twinklespeedy.callbacks.user.tagPage );
			wikipedia_wiki.params = self.params;
			wikipedia_wiki.followRedirect = false;
			wikipedia_wiki.get();
		},
		tagPage: function( self ) {
			form = this.responseXML.getElementById( 'editform' );

			var text = form.wpTextbox1.value;

			self.statelem.status( 'Checking for tags on the page...' );
//THESE NEXT TWO FUNCTIONS STILL NEED TO BE UPDATED FOR SEWP
			var tag = /(\{\{(?:db\|?|delete)\|?.*?\}\})/.exec( text );

			if( tag ) {
				self.statelem.error( [ htmlNode( 'strong', tag[0] ) , " is already placed on the page." ] )
				return;
			}

			var xfd = /(\{\{(?:[rsaitcm]fd|md1)[^{}]*?\}\})/i.exec( text );

			if( xfd && !confirm( "The deletion related template " + xfd[0] + " is already present on the page, do you still want to apply QD template?" ) ) {
				return;
			}
			var code;
			switch( self.params.normalized ) {
			
			case 'G6':
				switch( self.params.value ) {
				case 'histmerge':
					var title = prompt( 'please enter the title to merge into here' );
					if( title == null ) {
						return;
					}
					code = "\{\{QD|" +  self.params.normalized+ "|" + title + "\}\}";
					break;
				default:
					code = "\{\{QD|" +  self.params.normalized+ "\}\}";
					break;

				}
				break;
			case 'G12':
				var url = prompt( 'Please say where this is copied from or put the link here.' );
				if( url == null ) {
					return;
				}
				code = "\{\{QD|" +  self.params.normalized+ "|" + url + "\}\}";
				break;

			default:
				code = "\{\{QD|" +  self.params.normalized+ "\}\}";
				break;
			}

			// Notification to first contributor
			var query = {
				'action': 'query',
				'prop': 'revisions',
				'titles': wgPageName,
				'rvlimit': 1,
				'rvprop': 'user',
				'rvdir': 'newer'
			}
			var callback = function( self ) {
				var xmlDoc = self.responseXML;
				var user = xmlDoc.evaluate( '//rev/@user', xmlDoc, null, XPathResult.STRING_TYPE, null ).stringValue;
				var query = {
					'title': 'User talk:' + user,
					'action': 'submit'
				};
				var wikipedia_wiki = new Wikipedia.wiki( 'Notifying of initial contributor (' + user + ')', query, twinklespeedy.callbacks.user.userNotification );
				wikipedia_wiki.params = self.params;
				wikipedia_wiki.get();
			}

			if( self.params.usertalk ) {
				var wikipedia_api = new Wikipedia.api( 'Grabbing data of initial contributor', query, callback );
				wikipedia_api.params = self.params;
				wikipedia_api.post();
			}

			var postData = {
				'wpMinoredit': TwinkleConfig.markSpeedyPagesAsMinor ? '' : undefined,
				'wpWatchthis': (self.params.watch || form.wpWatchthis.checked ) ? '' : undefined,
				'wpStarttime': form.wpStarttime.value,
				'wpEdittime': form.wpEdittime.value,
				'wpAutoSummary': form.wpAutoSummary.value,
				'wpEditToken': form.wpEditToken.value,
				'wpSummary': "Requesting quick deletion ([[WT:QD#" + self.params.normalized.toUpperCase() + "|QD " + self.params.normalized.toUpperCase() + "]])." + TwinkleConfig.summaryAd,
				'wpTextbox1': code + "\n" + text
			};
			self.post( postData );
		},
		userNotification: function( self ) {
			var form = self.responseXML.getElementById( 'editform' );
			var text = form.wpTextbox1.value;
			text += "\n\{\{subst:QD-notice|page=" + wgPageName + "|cat=" + self.params.normalized + "|reason=" + twinklespeedy.reasonHash[ self.params.value ] + "\}\} \~\~\~\~";

			var postData = {
				'wpMinoredit': (typeof form.wpMinoredit == "undefined") ? undefined : (form.wpMinoredit.checked ? 1 : undefined),
				'wpWatchthis': form.wpWatchthis.checked ? '' : undefined,
				'wpStarttime': form.wpStarttime.value,
				'wpEdittime': form.wpEdittime.value,
				'wpAutoSummary': form.wpAutoSummary.value,
				'wpEditToken': form.wpEditToken.value,
				'wpSummary': 'Notification: Quick deletion nomination of \[\[' + wgPageName + '\]\].' + TwinkleConfig.summaryAd,
				'wpTextbox1': text
			};
			self.post( postData );
		}
	}
}

twinklespeedy.callback.evaluateSysop = function twinklespeedyCallbackEvaluateSysop(e) {

	wgPageName = wgPageName.replace( /_/g, ' ' ); // for queen/king/whatever and country!

	var tag_only = e.target.form.tag_only;
	if( tag_only && tag_only.checked ) {
		return twinklespeedy.callback.evaluateUser(e);
	}

	var value = e.target.value;
	var normalized = twinklespeedy.normalizeHash[ value ];

	var params = {
		value: value,
		normalized: normalized,
		watch: TwinkleConfig.watchSpeedyPages.indexOf( normalized ) != -1,
		reason: twinklespeedy.reasonHash[ value ]
	};
	Status.init( e.target.form );

	var query = {
		'action': 'query',
		'titles': wgPageName
	}
	var wikipedia_api = new Wikipedia.api( 'Checking if page exists', query, twinklespeedy.callbacks.sysop.main );
	wikipedia_api.params = params;
	wikipedia_api.post();
}



twinklespeedy.callback.evaluateUser = function twinklespeedyCallbackEvaluateUser(e) {
	wgPageName = wgPageName.replace( /_/g, ' ' ); // for queen/king/whatever and country!
	var value = e.target.value;
	var normalized = twinklespeedy.normalizeHash[ value ];

	var params = {
		value: value,
		normalized: normalized,
		watch: TwinkleConfig.watchSpeedyPages.indexOf( normalized ) != -1,
		usertalk: TwinkleConfig.notifyUserOnSpeedyDeletionNomination.indexOf( normalized ) != -1 && e.target.form.notify.checked
	};

	Status.init( e.target.form );

	Wikipedia.actionCompleted.redirect = wgPageName;
	Wikipedia.actionCompleted.notice = "Tagging complete";

	var query = {
		'action': 'query',
		'titles': wgPageName
	}

	var wikipedia_api = new Wikipedia.api( 'Checking if page exists', query, twinklespeedy.callbacks.user.main );
	wikipedia_api.params = params;
	wikipedia_api.post();

}