User:Addihockey10/twinklespeedy.js

From Simple English Wikipedia, the free encyclopedia

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)
 If ad should be added or not to summary, default "([[WP:TW|TW]])"
 */
if( typeof( TwinkleConfig.summaryAd ) == 'undefined' ) {
	TwinkleConfig.summaryAd = "([[WP:TW|TW]])";
}

/**
 TwinkleConfig.deletionSummaryAd (string)
 If ad should be added or not to deletion summary, default "([[WP:TW|TW]])"
 */
if( typeof( TwinkleConfig.deletionSummaryAd ) == 'undefined' ) {
	TwinkleConfig.deletionSummaryAd = "([[WP: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 false
 */
if( typeof( TwinkleConfig.markSpeedyPagesAsMinor ) == 'undefined' ) {
	TwinkleConfig.markSpeedyPagesAsMinor = false;
}

/**
 TwinkleConfig.markSpeedyPagesAsPatrolled (boolean)
 If, when applying speedy template to page, to mark the page as patrolled, default true
 */
if( typeof( TwinkleConfig.markSpeedyPagesAsPatrolled ) == 'undefined' ) {
	TwinkleConfig.markSpeedyPagesAsPatrolled = true;
}
/**
 TwinkleConfig.notifyUserOnSpeedyDeletionNomination (array of strings)
 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', 't2' ];
}

/**
 TwinkleConfig.welcomeUserOnSpeedyDeletionNotification (array of strings)
 On what types of speedy deletion notifications shall the user be welcomed
 with a {{firstarticle}} notice if his talk page has not yet been created.
 */
if( typeof( TwinkleConfig.welcomeUserOnSpeedyDeletionNotification ) == 'undefined' ) {
	TwinkleConfig.welcomeUserOnSpeedyDeletionNotification = TwinkleConfig.notifyUserOnSpeedyDeletionNomination;
}

/**
 TwinkleConfig.openUserTalkPageOnSpeedyDelete (array of strings)
 What types of actions that should result user talk page to be opened when speedily deleting (admin only)
 */
if( typeof( TwinkleConfig.openUserTalkPageOnSpeedyDelete ) == 'undefined' ) {
	TwinkleConfig.openUserTalkPageOnSpeedyDelete = [ 'g1', 'g2', 'g3', 'g4', 'g5', 'g10', 'g11', 'g12', 'a1', 'a3', 'a7', 'a9', 'a10', 'f3', 'f4', 'f5', 'f6', 'f7', 'f9', 'f11', 'u3', 't2' ];
}

/**
 TwinkleConfig.userTalkPageMode may take arguments:
 'window': open a new window, remember 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 (boolean)
 If talk page if exists should also be deleted (CSD G8) when speeding a page (admin only)
 */
if( typeof( TwinkleConfig.deleteTalkPageOnDelete ) == 'undefined' ) {
	TwinkleConfig.deleteTalkPageOnDelete = false;
}

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

/**
 TwinkleConfig.speedyWindowWidth (integer)
 Defines the width of the Twinkle SD window in pixels
 */
if( typeof( TwinkleConfig.speedyWindowWidth ) == 'undefined' ) {
	TwinkleConfig.speedyWindowWidth = 800;
}

/**
 TwinkleConfig.speedyWindowHeight (integer)
 Defines the height of the Twinkle SD window in pixels
 */
if( typeof( TwinkleConfig.speedyWindowHeight ) == 'undefined' ) {
	TwinkleConfig.speedyWindowHeight = 500;
}

/**
 TwinkleConfig.deleteSysopDefaultToTag (boolean)
 Make the CSD screen default to "tag" instead of "delete" (admin only)
 */
if( typeof(TwinkleConfig.deleteSysopDefaultToTag) == 'undefined' ) TwinkleConfig.deleteSysopDefaultToTag = false;

function twinklespeedy() {
	// Disable on:
	// * special pages
	// * pages with neither a page nor local file revision
	if( wgNamespaceNumber < 0 ||
	(wgArticleId==0 && (wgNamespaceNumber!=6 || (document.getElementById("mw-imagepage-section-filehistory") && !(document.getElementById("mw-sharedupload")))))
	)  return;
 
	if( userIsInGroup( 'sysop' ) ) {
		twAddPortletLink( "javascript:twinklespeedy.callback()", "QD", "tw-csd", "Quickly delete according to WP:QD", "");
	} else if (twinkleConfigExists) {
		twAddPortletLink( "javascript:twinklespeedy.callback()", "QD", "tw-csd", "Request quick deletion according to WP:QD", "");
	}
	else
	{
		twAddPortletLink( 'javascript:alert("Your account is too new to use Twinkle.");', 'QD', 'tw-csd', 'Request quick deletion according to WP:QD', '');
	}
}
window.TwinkleInit = (window.TwinkleInit || []).concat(twinklespeedy); //schedule initializer

// This function is run when the CSD tab/header link is clicked
twinklespeedy.callback = function twinklespeedyCallback() {
	twinklespeedy.initDialog(userIsInGroup( 'sysop' ) ? twinklespeedy.callback.evaluateSysop : twinklespeedy.callback.evaluateUser, true);
}

// Prepares the speedy deletion dialog and displays it
// Parameters: 
//  - callbackfunc: the function to call when the dialog box is submitted
//  - firstTime: is this the first time? (false during a db-multiple run, true otherwise)
//  - content: (optional) a div element in which the form content should be rendered - allows
//    for placing content in an existing dialog box
twinklespeedy.initDialog = function twinklespeedyInitDialog(callbackfunc, firstTime, content) {
	var dialog;
	if (!content)
	{
		dialog = new SimpleWindow( TwinkleConfig.speedyWindowWidth, TwinkleConfig.speedyWindowHeight ); 
		dialog.setTitle( "Choose criteria for speedy deletion" );
	}

	var form = new QuickForm( callbackfunc, 'change' );
	if( firstTime && 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',
						checked : TwinkleConfig.deleteSysopDefaultToTag,
						event: function( event ) {
							event.target.form.notify.disabled = ! event.target.checked;
							event.target.form.notify.checked = event.target.checked;
							event.stopPropagation();
						}
					},
					{
						label: 'unlink links to this page',
						value: 'orphan_backlinks',
						name: 'orphan_backlinks',
						tooltip: 'If you want to orphan the current page. If checked, excludes will still apply',
						checked: TwinkleConfig.orphanBacklinksOnSpeedyDelete.orphan,
						event: function( event ) {
							TwinkleConfig.orphanBacklinksOnSpeedyDelete.orphan = event.target.checked;
							event.stopPropagation();
						}
					}
				]
			} );
	}
	
	// don't show this notification checkbox for db-multiple, as the value is ignored
	// XXX currently not possible to turn off notification when using db-multiple
	if (firstTime) {
		form.append( {
			type: 'checkbox',
			list: [
				{
					label: 'Notify if possible',
					value: 'notify',
					name: 'notify',
					tooltip: 'If a notification is defined in the configuration, then notify if this is true, else no notification',
					checked: !userIsInGroup( 'sysop' ),
					disabled: userIsInGroup( 'sysop' ),
					event: function( event ) {
						event.stopPropagation();
					}
				}
			]
		}
	);
	if( wgNamespaceNumber ==  Namespace.IMAGE ) {
		form.append( {type:'header', label:'Files' } );
		form.append ( {
				type: 'radio',
				name: 'csd',
				list: [
						{ 
							label: 'I1: Prohibited image',
							value: 'prohibitedimage',
							tooltip: 'Most media uploads are not allowed on Simple English Wikipedia. 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 Wikipedia logo.' 
						},
 
					]
 
			} );
	}
 
	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 Wikipedia: 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.'
					}
				]
 
		} );
	}
	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 WP: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: 'T2: They are deprecated or replaced by a newer template and are completely unused and not linked to.',
						value: 'replaced'
					},
				]
 
		} );
	} 
 
	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 Wikipedia; 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 Wikipedia 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;' 
					}
				]
		});
 
	form.append( { type:'header', label: 'Redirects' } );
	form.append( {
			type: 'radio',
			name: 'csd',
			list: [
				{ 
                                        label: 'R1: Redirects to a non-existent page.', 
					value: 'redirnone', 
					tooltip: 'Redirects to a non-existent page.'
				},
				{ 
 
					label: 'R2: Redirects from mainspace to any other namespace except the Category:, Template:, Wikipedia:, Help: and Portal: namespaces', 
					value: 'rediruser', 
					tooltip: '(this does not include the Wikipedia shortcut pseudo-namespaces). If this was the result of a page move, consider waiting a day or two before deleting the redirect'
				},
				{ 
					label: 'R3: Redirects as a result of an implausible typo that were recently created', 
					value: 'redirtypo', 
					tooltip: 'However, redirects from common misspellings or misnomers are generally useful, as are redirects in other languages'
				}
			]
		} );
	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',
	'redirnone': 'r1',
	'rediruser': 'r2',
	'redirtypo': 'r3',
	'prohibitedimage': 'f1',
	'catempty': 'c1',
	'catqr': 'c2',
	'catfd': 'c3',
	'userreq': 'u1',
	'nouser': 'u2',
	'replaced':'t2'
};
 
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 Wikipedia',
		'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)',
		'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 Wikipedia',
		'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',
		'replaced': 'was deprecated or replaced by a newer template and are completely unused and not linked to'
};

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;
			}

			if( self.params.openusertalk ) {
				// Open talk page of first contributor
				var query = {
					'action': 'query',
					'prop': 'revisions',
					'titles': wgPageName,
					'rvlimit': 1,
					'rvprop': 'user',
					'rvdir': 'newer'
				}

				var wikipedia_api = new Wikipedia.api( 'Grabbing username of initial contributor', query, twinklespeedy.callbacks.sysop.openUserTalkPage );
				wikipedia_api.params = self.params;
				wikipedia_api.post();
			}
			
			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 != 'f8' &&
				wgNamespaceNumber % 2 == 0 && 
				wgNamespaceNumber != Namespace.USER && 
				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 != 'f8' ) {
				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 file 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();

		},
		openUserTalkPage: function( self ) {
			var xmlDoc = self.responseXML;
			var user = xmlDoc.evaluate( '//rev/@user', xmlDoc, null, XPathResult.STRING_TYPE, null ).stringValue;
			var statusIndicator = new Status('Opening user talk page edit form for user ' + user, 'opening');
			
			var query = {
				'title': 'User talk:' + user,
				'action': 'edit',
				'preview': 'yes',
				'vanarticle': wgPageName.replace(/_/g, ' ')
			};
			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;
			}
			
			statusIndicator.info( 'complete' );
		},
		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': form.wpMinoredit.checked ? '' : undefined,
				'wpWatchthis': undefined,
				'wpStarttime': form.wpStarttime.value,
				'wpEdittime': form.wpEdittime.value,
				'wpAutoSummary': form.wpAutoSummary.value,
				'wpEditToken': form.wpEditToken.value,
				'wpSection': '',
				'wpSummary': 'Removing backlinks to ' + self.params.page + " that has been speedily deleted per ([[WP:CSD#" + self.params.normalized.toUpperCase() + "|CSD " + 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, file deletion is b0rked :(
				form = this.responseXML.getElementsByTagName( 'form' )[0];
				var postData = {
					'wpDeleteReasonList': 'other',
					'wpReason': "[[WP:CSD#G8|G8]]: Redirect to deleted page \"" + wgPageName + "\" " + TwinkleConfig.deletionSummaryAd,
					'wpEditToken': form.wpEditToken.value
				}
			} else {

				var postData = {
					'wpWatch': form.wpWatch.checked ? '' : undefined,
					'wpDeleteReasonList': 'other',
					'wpReason': "[[WP:CSD#G8|G8]]: 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 file instances ', '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 file 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,
				'wpSection': '',
				'wpSummary': 'Removing instance of file ' + self.params.image + " that has been speedily deleted per [[WP:CSD#" + self.params.normalized.toUpperCase() + "|CSD " + self.params.normalized.toUpperCase() + "]]" + ". " + TwinkleConfig.deletionSummaryAd,
				'wpTextbox1': text
			};
			self.post( postData );
		},
		deletePage: function( self ) {
			var form = this.responseXML.getElementById( 'deleteconfirm' );
			if( ! form ) { // Hell, file deletion is b0rked :(
				form = this.responseXML.getElementsByTagName( 'form' )[0];
				var postData = {
					'wpDeleteReasonList': 'other',
					'wpReason': "[[WP:CSD#" + self.params.normalized.toUpperCase() + "|" + 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': "[[WP:CSD#" + self.params.normalized.toUpperCase() + "|" + 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': "[[WP:CSD#G8|G8]]: Talk page of deleted page \"" + wgPageName + "\" " + 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 exist, 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...' );

			// check for existing deletion tags
			var tag = /(\{\{\s*(?:db|delete|db-.*?)(?:\||\s*\}\}))/.exec( text );
			if( tag ) {
				self.statelem.error( [ htmlNode( 'strong', tag[0] ) , " is already placed on the page." ] )
				return;
			}

			var xfd = /(\{\{(?:[rsaiftcm]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 CSD template?" ) ) {
				return;
			}
			
			var code;
			var parameters;
			if (self.params.normalized == 'multiple')
			{
				code = "\{\{db-multiple";
				for (var i in twinklespeedy.dbmultipleCriteria)
					if (typeof twinklespeedy.dbmultipleCriteria[i] == 'string')
						code += "|" + twinklespeedy.dbmultipleCriteria[i].toUpperCase();
				for (var i in twinklespeedy.dbmultipleParameters)
					if (typeof twinklespeedy.dbmultipleParameters[i] == 'string')
						code += "|" + i + "=" + twinklespeedy.dbmultipleParameters[i];
				code += "\}\}";
				self.params.utparams = [];
			}
			else
			{
				parameters = twinklespeedy.getParameters(self.params.value, self.params.normalized, self.statelem);
				if (!parameters) return;
				code = "\{\{db-" + self.params.value;
				for (var i in parameters)
					if (typeof parameters[i] == 'string')
						code += "|" + i + "=" + parameters[i];
				code += "\}\}";
				self.params.utparams = twinklespeedy.getUserTalkParameters(self.params.normalized, parameters);
			}	

			if( TwinkleConfig.markSpeedyPagesAsPatrolled && self.params.rcid != '' ) {
				// extract patrol token from "Mark page as patrolled" link on page
				var patrollinkmatch = /token=(.+)%2B%5C$/.exec($('.patrollink a').attr('href'));
				
				if (patrollinkmatch) {
					var patroltoken = patrollinkmatch[1] + "+\\";
					var patrolstat = new Status("Marking page as patrolled", "Doing...");
					(Wikipedia.numberOfActionsLeft)++;

					var query = {
						'title': wgPageName,
						'action': 'markpatrolled',
						'rcid': self.params.rcid,
						'token': patroltoken
					};

					jQuery.ajax( {
						context: patrolstat,
						type: 'GET',
						url: mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php', 
						data: QueryString.create(query),
						dataType: 'xml',
						success: function(xml, textStatus, jqXHR) {
							this.info(textStatus);
							Wikipedia.actionCompleted();
						},
						error: function(jqXHR, textStatus, errorThrown) {
							if (textStatus == "parsererror") { // kludge for Firefox 4.0b12
								this.info("Done");
								Wikipedia.actionCompleted();
							} else {
								this.error(textStatus + ': ' + errorThrown + ' occurred while trying to mark as patrolled.');
							}
						}
					} );
				}
			}

			// 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;
				if( wgPageName != ( 'User talk:' + user ) ) {
					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();
				} else {
					Status.info( 'Info', 'Current page is initial contributor\'s talk page, aborting notification' );
				}
			}

			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();
			}

			//wrap SD template in noinclude tags if we are in template space.
			//won't work with userboxes in userspace, or any other transcluded page outside template space
			if (self.params.wgCanonicalNamespace == "Template") code = "<noinclude>" + code + "</noinclude>";

			//Remove tags that become superfluous with this action
			text = text.replace(/{\{\s*(New unreviewed article|Userspace draft)\s*(\|(?:{{[^{}]*}}|[^{}])*)?}}\s*/ig, "");

			// Generate edit summary for edit
			var editsummary;
			switch (self.params.normalized)
			{
				case 'db':
					editsummary = 'Requesting [[WP:CSD|speedy deletion]] with rationale \"' + parameters["1"] + '\".';
					break;
				case 'multiple':
					editsummary = 'Requesting speedy deletion (';
					for (var i in twinklespeedy.dbmultipleCriteria)
						if (typeof twinklespeedy.dbmultipleCriteria[i] == 'string')
							editsummary += '[[WP:CSD#' + twinklespeedy.dbmultipleCriteria[i].toUpperCase() + '|CSD ' + twinklespeedy.dbmultipleCriteria[i].toUpperCase() + ']], ';
					editsummary = editsummary.substr(0, editsummary.length - 2); // remove trailing comma
					editsummary += ').';
					break;
				default:
					editsummary = "Requesting speedy deletion ([[WP:CSD#" + self.params.normalized.toUpperCase() + "|CSD " + self.params.normalized.toUpperCase() + "]]).";
					break;
			}

			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,
				'wpSection': '',
				'wpSummary': editsummary + TwinkleConfig.summaryAd,
				'wpTextbox1': code + ((self.params.normalized == 'g10' || twinklespeedy.dbmultipleCriteria.indexOf('g10') != -1) ?
					'' : ("\n" + text) ) // cause attack pages to be blanked
			};
			self.post( postData );
		},
		userNotification: function( self ) {
			var nowelcome = TwinkleConfig.welcomeUserOnSpeedyDeletionNotification.indexOf( self.params.normalized ) == -1;
			var form = self.responseXML.getElementById( 'editform' );
			var text = form.wpTextbox1.value;
			
			// specialcase "db" and "db-multiple"
			// XXX modify the "db-csd-notice-custom" template to cater for these special cases
			switch (self.params.normalized)
			{
				case 'db':
					text += "\n\{\{subst:db-reason-notice|1=" + wgPageName;
					break;
				case 'multiple':
					text += "\n\{\{subst:db-notice-multiple|1=" + wgPageName;
					break;
				default:
					text += "\n\{\{subst:db-csd-notice-custom|1=" + wgPageName + "|2=" + self.params.value;
					break;
			}
			for (var i in self.params.utparams)
				if (typeof self.params.utparams[i] == 'string')
					text += "|" + i + "=" + self.params.utparams[i];
			text += (nowelcome ? "|nowelcome=yes" : "") + "\}\} \~\~\~\~";
			
			var postData = {
				'wpMinoredit': form.wpMinoredit.checked ? '' : undefined,
				'wpWatchthis': form.wpWatchthis.checked ? '' : undefined,
				'wpStarttime': form.wpStarttime.value,
				'wpEdittime': form.wpEdittime.value,
				'wpAutoSummary': form.wpAutoSummary.value,
				'wpEditToken': form.wpEditToken.value,
				'wpSection': '',
				'wpSummary': 'Notification: Speedy deletion nomination of \[\[' + wgPageName + '\]\].' + TwinkleConfig.summaryAd,
				'wpTextbox1': text
			};
			self.post( postData );
		}
	}
}

// prompts user for parameters to be passed into the speedy deletion tag
twinklespeedy.getParameters = function twinklespeedyGetParameters(value, normalized, statelem)
{
	var parameters = [];
	switch( normalized ) {
		case 'db':
			var rationale = prompt('Please enter a mandatory rationale.   \n\"This page qualifies for speedy deletion because:\"');
			if (rationale == null || rationale.replace(/^\s*/, "").replace(/\s*$/, "") == '')
			{
				statelem.error( 'You must specify a rationale.  Aborted by user.' );
				return;
			}
			if (rationale != '') parameters["1"] = rationale;
			break;
		case 'u1':
			var rationale = '';
			if (wgNamespaceNumber==3 && !(/\//.test(wgTitle)))
			{
				var rationale = prompt('Please provide a mandatory rationale to explain why this user talk page should be deleted:');
				if (rationale == null || rationale.replace(/^\s*/, "").replace(/\s*$/, "") == '')
				{
					statelem.error( 'Aborted by user.' );
					return;
				}
			}
			if (rationale != '') parameters["rationale"] = rationale;
			break;
		case 'f8':
			var pagenamespaces = wgPageName.replace( '_', ' ' );
			var filename = prompt( 'Please enter the name of the file on Commons:', pagenamespaces );
			if (filename == null)
			{
				statelem.error( 'Aborted by user.' );
				return;
			}
			if (filename != '' && filename != pagenamespaces)
			{
				if (filename.indexOf("Image:") == 0 || filename.indexOf("File:") == 0)
				{
					parameters["1"] = filename;
				}
				else
				{
					statelem.error("The File: prefix was missing from the image filename.  Aborted.");
					return;
				}
			}
			parameters["date"] = "\~\~\~\~\~";
			break;
		case 'g6':
			var rationale = null;
			switch( value ) {
				case 'histmerge':
					var title = prompt( 'Please enter the title to merge into:' );
					if (title == null)
					{
						statelem.error( 'Aborted by user.' );
						return;
					}
					parameters["1"] = title;
					break;
				case 'move':
					var title = prompt( 'Please enter the title of the page to be moved here:' );
					if (title == null)
					{
						statelem.error( 'Aborted by user.' );
						return;
					}
					var reason = prompt( 'Please enter the reason for the page move:' );
					if (reason == null)
					{
						self.statelem.error( 'Aborted by user.' );
						return;
					}
					parameters["1"] = title;
					parameters["2"] = reason;
					break;
				case 'g6':
					rationale = prompt( 'Please provide an optional rationale (leave empty to skip):' );
					if (rationale == null)
					{
						statelem.error( 'Aborted by user.' );
						return;
					}
					if (rationale != '') parameters["rationale"] = rationale; 
					break;
			}
			break;
		case 'g7':
			var rationale = prompt('Please provide an optional rationale (perhaps linking to where the author requested this deletion - leave empty to skip):');
			if (rationale == null)
			{
				statelem.error( 'Aborted by user.' );
				return;
			}
			if (rationale != '') parameters["rationale"] = rationale; 
			break;
		case 'f9':
		case 'g12':
			var url = prompt( 'Please enter the URL if available, including the "http://":' );
			if (url == null)
			{
				statelem.error( 'Aborted by user.' );
				return;
			}
			parameters["url"] = url;
			break;
		case 'a2':
			var source = prompt('Enter an interwiki link to the article on the foreign-language wiki (for example, "fr:Bonjour"):');
			if (source == null)
			{
				statelem.error('Aborted by user.');
				return;
			}
			parameters["source"] = source;
			break;
		case 'a10':
			var title = prompt( 'Enter the article name that is duplicated:' );
			if (title == null)
			{
				statelem.error( 'Aborted by user.' );
				return;
			}
			parameters["article"] = title;
			break;
		case 'f1':
			var img = prompt( 'Enter the file this is redundant to, excluding the "Image:" or "File:" prefix:' );
			if (img == null)
			{
				statelem.error( 'Aborted by user.' );
				return;
			}
			parameters["filename"] = img;
			break;
		case 't3':
			var template = prompt( 'Enter the template this is redundant to, excluding the "Template:" prefix:' );
			if (template == null)
			{
				statelem.error( 'Aborted by user.' );
				return;
			}
			parameters["1"] = "\~\~\~\~\~";
			parameters["2"] = template;
			break;
		case 'g10':
			parameters["blanked"] = 'yes';
			// it is actually blanked elsewhere in code, but setting the flag here
			break;
	}
	return parameters;
}

// function for processing talk page notification template parameters
twinklespeedy.getUserTalkParameters = function twinklespeedyGetUserTalkParameters(normalized, parameters)
{
	var utparams = [];
	switch (normalized)
	{
		case 'db':
			utparams["2"] = parameters["1"];
			break;
		case 'a10':
			utparams["key1"] = "article";
			utparams["value1"] = parameters["article"];
			break;
	}
	return utparams;
}

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 ],
		openusertalk: TwinkleConfig.openUserTalkPageOnSpeedyDelete.indexOf( normalized ) != -1
	};
	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;
		
	if (value == 'multiple')
	{
		e.target.form.style.display = "none"; // give the user a cue that the dialog is being changed
		twinklespeedy.targetdialogcontent = e.target.form.parentNode; // make this accessible in scopeless setTimeout
		setTimeout("twinklespeedy.initDialog(twinklespeedy.callback.doMultiple, false, twinklespeedy.targetdialogcontent)", 150);
		return;
	}
	
	if (value == 'multiple-finish')
		value = 'multiple';
	else
	{
		// clear these out, whatever the case, to avoid errors
		twinklespeedy.dbmultipleCriteria = [];
		twinklespeedy.dbmultipleParameters = [];
	}
		
	var normalized = twinklespeedy.normalizeHash[ value ];

	// analyse each db-multiple criterion to determine whether to watch the page/notify the creator
	var watchPage = false;
	if (value == 'multiple')
	{
		for (var i in twinklespeedy.dbmultipleCriteria)
		{
			if (typeof twinklespeedy.dbmultipleCriteria[i] == 'string' && 
				TwinkleConfig.watchSpeedyPages.indexOf(twinklespeedy.dbmultipleCriteria[i]) != -1)
			{
				watchPage = true;
				break;
			}
		}
	}
	else watchPage = TwinkleConfig.watchSpeedyPages.indexOf(normalized) != -1;
	
	var notifyuser = false;
	if (value == 'multiple')
	{
		for (var i in twinklespeedy.dbmultipleCriteria)
		{
			if (typeof twinklespeedy.dbmultipleCriteria[i] == 'string' && 
				TwinkleConfig.notifyUserOnSpeedyDeletionNomination.indexOf(twinklespeedy.dbmultipleCriteria[i]) != -1)
			{
				notifyuser = true;
				break;
			}
		}
	}
	else notifyuser = (TwinkleConfig.notifyUserOnSpeedyDeletionNomination.indexOf(normalized) != -1) && e.target.form.notify.checked;
				
	var params = {
		value: value,
		normalized: normalized,
		watch: watchPage,
		usertalk: notifyuser,
		rcid: QueryString.exists( 'rcid' ) ? QueryString.get( 'rcid' ) : '',
		wgCanonicalNamespace : wgCanonicalNamespace
	};

	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();
}

twinklespeedy.dbmultipleCriteria = [];
twinklespeedy.dbmultipleParameters = [];
twinklespeedy.callback.doMultiple = function twinklespeedyCallbackDoMultiple(e)
{
	var value = e.target.value;
	var normalized = twinklespeedy.normalizeHash[value];
	if (value != 'multiple-finish')
	{
		if (twinklespeedy.dbmultipleCriteria.indexOf(normalized) != -1)
			alert('You already selected that criterion. Please choose another.');
		else
		{
			var parameters = twinklespeedy.getParameters(value, normalized, Status);
			if (parameters)
			{
				for (var i in parameters)
					if (typeof parameters[i] == 'string')
						twinklespeedy.dbmultipleParameters[i] = parameters[i];
				twinklespeedy.dbmultipleCriteria.push(normalized);
			}
		}
		e.target.form.style.display = "none"; // give the user a cue that the dialog is being changed
		twinklespeedy.targetdialogcontent = e.target.form.parentNode; // make this accessible in scopeless setTimeout
		setTimeout("twinklespeedy.initDialog(twinklespeedy.callback.doMultiple, false, twinklespeedy.targetdialogcontent)", 150);
	}
	else
	{
		twinklespeedy.callback.evaluateUser(e);
	}
}