转到正文

MediaWiki:Gadget-twinklespeedy.js

来自维基教科书,全世界的免费课本
注意:保存后,更改可能不会立即生效。单击此处了解如何清除浏览器的缓存。
  • Mozilla / Firefox / Safari:按住Shift键,然后单击重新加载或按Ctrl-Shift-R(Apple Mac 上按Cmd-Shift-R);
  • Internet Explorer:按住Ctrl键,然后单击刷新或按Ctrl-F5
  • Konqueror:直接单击重新加载按钮或按F5
  • Opera用户可能需要在工具→首选项中彻底清除缓存。
//<pre><nowiki>
/**
This script requires MediaWiki:Gadget-morebits.js
It is a hack of w:User:AzaToth/twinklespeedy.js, so almost all the credit goes there
It was modified for use on English Wikibooks and is maintained by User:Mike.lifeguard
*/

//this module has its own configuration
TwinkleSpeedyConfig = {
	userTalkPageMode						:	'tab',
	summaryAd								:	" using [[w:WP:TW|TW]]",
	deletionSummaryAd						:	" using [[w:WP:TW|TW]]",
	deleteTalkPageOnDelete					:	true,
	markSpeedyPagesAsMinor					:	true,
	notifyUserOnSpeedyDeletionNomination	:	[
												'g9',//rfd
												'a3',//query
												'i9',//imgcopyvio
												'g12',//copyvio
												'i4',//nld
												'i7',//bfu
												'i6'//no rationale
												],
	orphanBacklinksOnSpeedyDelete			:	{ exclude: [
															'g1',// badpage
															'g12',//copyvio
															'a2',//naming-convention
															'a3',//query
															'i2',//corruptimg
															'i4',//nld
															'i6',//no rationale
															'i7',//bfu
															'i9'//imgcopyvio
															], orphan:true }//orphan deletions EXCEPT the above

};

function twinklespeedy() {
	//don't go
	var maketwinklego = false;
	//unless...
	//check for +patroller or +sysop and continue if so
	if( userIsInGroup( 'rollbacker' ) || userIsInGroup( 'editor' ) || userIsInGroup( 'reviewer' ) || userIsInGroup( 'sysop' ) ) {
		//check for IsArticle on wgAction=(true|purge|history|rollback)
		if( (mw.config.get('wgIsArticle') == true && (mw.config.get('wgAction') == "view" || mw.config.get('wgAction') == "purge" || mw.config.get('wgAction') == "rollback" || mw.config.get('wgAction') == "markpatrolled")) || (mw.config.get('wgIsArticle') == false && mw.config.get('wgAction') == "history") ) {
			//check for not Main Page
			if( mw.config.get('wgPageName') != "Main_Page" ) {
				maketwinklego = true;
			}
		}
	}
	//if you didn't make it, then too bad :(
	if(maketwinklego == true){
		if( userIsInGroup( 'sysop' ) ) {
			mw.util.addPortletLink( 'p-cactions', "javascript:twinklespeedy.callback()", "speedy", "tw-csd", "Twinkle speedy tag/delete", "");
		} else if ( userIsInGroup ('rollbacker') || userIsInGroup ('editor') || userIsInGroup ('reviewer') ) {
			mw.util.addPortletLink( 'p-cactions', "javascript:twinklespeedy.callback()", "speedy", "tw-csd", "Twinkle speedy tag", "");
		}
		else{
		mw.util.addPortletLink('p-cactions', 'javascript:alert("Your account doesn\'t have the appropriate permissions. See https://wikibooks.cn/wiki/User:Mike.lifeguard/Twinkle_Speedy_documentation");', 'csd', 'tw-csd', 'Twinkle speedy tag', '');
		}
	}
}
$(twinklespeedy);

twinklespeedy.callback = function twinklespeedyCallback() {
	var Window = new SimpleWindow( 600, 500 );
	Window.setTitle( "Speedy tagify, notify and deletify " );

	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',
						//keep admins from deleting when they meant to tag
						checked: true,
						tooltip: 'Admins may unselect this to delete. Read the tooltips carefully to get the result you want!',
						event: function( event ) {
							event.target.form.notify.disabled = ! event.target.checked;
							event.stopPropagation();
						}
					},
					{
						label: 'Orphan backlinks',
						value: 'orphan_backlinks',
						name: 'orphan_backlinks',
						tooltip: 'Will orphan all backlinks to the current page in the mainspace.',
						checked: false,
						event: function( event ) {
							TwinkleSpeedyConfig.orphanBacklinksOnSpeedyDelete.orphan = event.target.checked;
							event.stopPropagation();
						}
					}
				]
			} );
	}

	form.append( {
			type: 'checkbox',
			list: [
				{
					label: 'Notify if possible',
					value: 'notify',
					name: 'notify',
					tooltip: 'Please take care not to innundate a single user with many template messages. This box should remain checked unless tagging many pages by the same user. In cases where there is an appropriate template message, the script will use it; in all other cases, you\ll have to leave a message manually.',
					checked: true,
					//don't disable - must be allowed to NOT warn when tagging many uploads with subst:nld, for example
					//disabled: userIsInGroup( 'sysop' ),
					//disabled: userIsInGroup( 'user' ),
					event: function( event ) {
						event.stopPropagation();
					}
				}
			]
		}
	);
	if( mw.config.get('wgNamespaceNumber') ==  mw.config.get('wgNamespaceIds').file ) {
		form.append( {type:'header', label:'Images/Media' } );
		form.append ( {
				type: 'radio',
				name: 'csd',
				list: [
					{
						label: 'Duplicate image',
						value: 'dupeimg',
						tooltip: 'If tag-only: Tag the image for deletion because it is a duplicate of some other image. Have the image name ready at the prompt (including Image: prefix). If deleting: Deletes the image because it is a duplicate of some other image. Have the image name ready at the prompy (with Image: prefix).'
					},
					{
						label: 'Corrupt or empty image',
						value: 'corruptimg',
						tooltip: 'If tag-only: Tag this image for deletion because it is corrupt or empty. If deleting: Deletes the image because it is corrupt or empty.'
					},
					{
						label: 'Lack of licensing information: {{sub' + 'st:nld}}',
						value: 'noimgsrc',
						tooltip: 'Tag-only: Tags an image with {{sub' + 'st:nld}} and notifies the uploader. Please unselect notification to leave only one notification when tagging multiple uploads by the same user. If deleting: Admins can delete images tagged with {{sub' + 'st:nld}} for over 7 days with this option.'
					},
					{
						label: 'Unused unfree images',
						value: 'unusedFU',
						tooltip: 'Tag-only: This will tag images for deletion because they are unused, but have a fair use claim. If deleting: Admins may delete images which are unused, but have a fair use claim after they\'ve been tagged as such for 7 days.'
					},
					{
						label: 'Missing fair-use rationale: {{sub' + 'st:nfur}}',
						value: 'norat',
						tooltip: 'Tag-only: Tags images with a fair use claim but no rationale. If deleting: Admins may delete images with this option when they have been tagged for over 7 days as not having a fair use rationale.'
					},
					{
						label: 'Invalid fair-use claim',
						value: 'badfairuse',
						tooltip: 'Tag-only: Tags this image because it has an obviously bad fair use claim. If deleting: Admins may use this to delete images with obviously bad fair use claims after one week.'
					},
					{
						label: 'Images available as bit-for-bit identical copies on Commons: {{nowcommons}}',
						value: 'nowcommons',
						tooltip: 'Tag-only: Tags the image with {{nowcommons}}. Please have the commons image name (no Image: prefix) ready at the prompt. If deleting: Check that if the filename on commons is different from here that all links are updated. This tool will unlink images if you let it; BE CAREFUL and check the checkbox - do you really want to unlink the image? Check that the commons image exists, is the same, and has good license and source info. Have the commons image name (with Image: prefix) ready at the prompt.'
					},
					{
						label: 'Image copyright violation: {{copyvio}}',
						value: 'imgcopyvio',
						tooltip: 'Tag-only: Tags the image with {{copyvio}}. Please have the source ready at the prompt (full url including http://) if available. If not, then enter a short reason why you think it\'s a copyvio. If deleting: Admins may use this to delete images which have been tagged with {{copyvio}} for over 7 days. You should allow TW to unlink these images.'
					},
				]
			} );
	}
if( mw.config.get('wgNamespaceNumber') ==  0 || mw.config.get('wgNamespaceNumber') == 1 ||mw.config.get('wgNamespaceNumber') == 102 ||mw.config.get('wgNamespaceNumber') == 110) {
	form.append( { type:'header', label:'Modules' } );
	form.append( {
			type: 'radio',
			name: 'csd',
			list: [
				{
					label: '{{query'+'}}',
					value: 'query',
					tooltip: 'Tag-only: This will tag a page with {{query'+'}}. If deleting: Admins can use this option to delete a page that has been tagged with {{query'+'}} for over 7 days (only). For pages that have no meaningful content but haven\'t been tagged (and don\'t deserve to be), use the general deletion option, and provide a reason when prompted.'
				},
				{
					label: 'No meaningful content',
					value: 'nocontent',
					tooltip: 'Tag-only: This will tag a page for speedy deletion because it has no meaningful content. If deleting: Admins can use this to delete pages which clearly have no meaningful content.'
				},
				{
					label: 'New books: {{new book}}',
					value: 'newbook',
					tooltip: 'Tag-only: This will add {{new book}} to the page. If deleting: Impossible.'
				},
				{
					label: 'Modules for transwiki: {{transwiki}}',
					value: 'transwiki',
					tooltip: 'Tag-only: This will tag a page for transwiki. Please have the text for an interwiki link ready at the prompt (no [[ or ]]). If deleting: Admins may use this to delete a page after the transwiki is complete.'
				},
				{
					label: 'Very large modules: {{split}}',
					value: 'split',
					tooltip: 'Tag-only: Tag a module to be split into subpages. If deleting: Impossible.'
				},
				{
					label: 'Books violating the naming policy: {{fix title}}',
					value: 'nc',
					tooltip: 'Tag-only: This will tag the page as violating the naming policy. If deleting: Impossible.'
				},
				{
					label: 'Generic cleanup',
					value: 'cleanup',
					tooltip: 'Tag-only: This leaves {{cleanup}} with a mandatory reason. If deleting: Impossible.'
				}
			]
		} );
	}
	form.append( { type:'header', label:'General criteria' } );
	form.append( {
			type: 'radio',
			name: 'csd',
			list: [
				{
					label: 'Nonsense, spam or vandalism page',
					value: 'badpage',
					tooltip: 'Tag-only: Tags the page for speedy deletion because it\'s a bad page page. If deleting: Admins may delete such pages here'
				},
				{
					label: 'Recreation of deleted material',
					value: 'repost',
					tooltip: 'Tag-only: Will tag this page for speedy deletion because it\'s a repost of content previously deleted at WB:RFD. If deleting: Admins may delete reposted content here.'
				},
				{
					label: 'RFD',
					value: 'rfd',
					tooltip: 'Tag-only: You\'ll tag it for deletion by RFD; don\'t forget to create the appropriate section at WB:RFD. If deleting: Admins may use this to delete after a RFD (please have the pagename of the archived discussion ready at the prompt).'
				},
				{
					label: 'Generic Speedy deletion',
					value: 'gen',
					tooltip: 'Tag-only: You\'ll be prompted for a reason If deleting: Admins can use this for speedy deletions which don\'t fit elsewhere. Have a reason ready at the prompt.'
				},
				{
					label: 'Author requests deletion',
					value: 'author',
					tooltip: 'Tag-only: Use this to request deletion of your own pages, or request speedy deletions for another user. If deleting: Admins can delete page by author request here.'
				},
				{
					label: 'Author blanked',
					value: 'blanked',
					tooltip: 'Tag-only: Tags a page for deletion if the author blanked it. If deleting: Admins may take a blanking by the only author to be a deletion request and delete here.'
				},
				{
					label: 'Copyright violation: {{copyvio}}',
					value: 'copyvio',
					tooltip: 'Tag-only: Adds {{copyvio}}; please have the url ready at the prompt. If deleting: Admins can use this to delete a page tagged with {{copyvio}} for more than 7 days.'
				}
			]
		});
	form.append( { type:'header', label: 'Redirects' } );
	form.append( {
			type: 'radio',
			name: 'csd',
			list: [
				{
					label: 'Broken redirect',
					value: 'redirnone',
					tooltip: 'Tag-only: This will tag the page for deletion because it redirects to a nonexistent page If deleting: Admins may use this to delete broken redirects.'
				},
				{
					label: 'Orphaned redirects',
					value: 'redirorphan',
					tooltip: 'Tag-only: This will tag the page for deletion because it\'s an orphaned redirect. Make sure it\'s orphaned using Special:Whatlinkshere! If deleting: Admins can delete orphaned redirects here.'
				}
			]
		} );
if( mw.config.get('wgNamespaceNumber') ==  14 || mw.config.get('wgNamespaceNumber') == 15 ) {
	form.append( { type:'header', label: 'Categories' } );
	form.append( {
			type: 'radio',
			name: 'csd',
			list: [
				{
					label: 'Empty categories',
					value: 'catempty',
					tooltip: 'Tag-only: This will tag an empty category for deletion. If deleting: Admins may delete unneeded, empty categories with this option.'
				}
			]
		} );
} if( mw.config.get('wgNamespaceNumber') ==  2 || mw.config.get('wgNamespaceNumber') == 3 ) {
	form.append( { type:'header', label: 'User pages' } );
	form.append( {
			type: 'radio',
			name: 'csd',
			list: [
				{
					label: 'User request',
					value: 'userreq',
					tooltip: 'Tag-only: Use this to request deletion of pages in your userspace. If deleting: Admins may use this to delete pages in the userspace upon request.'
				},
			]
		} );
} if( mw.config.get('wgNamespaceNumber') ==  10 || mw.config.get('wgNamespaceNumber') == 11 ) {
	form.append( { type:'header', label: 'Templates' } );
	form.append( {
			type: 'radio',
			name: 'csd',
			list: [

				{
					label: 'Template for deletion',
					value: 'template',
					tooltip: 'Tag-only: Use this to request deletion of templates. If deleting: Admins may delete templates with this option.'
				}
			]
		} );
}

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

twinklespeedy.normalizeHash = {
	'badpage': 'g1',
	'newbook': 'g2',
	'repost': 'g4',
	'nocontent': 'g5',
	'rfd': 'g9',
	'gen': 'g13',
	'author': 'g7',
	'blanked': 'g7',
	'copyvio': 'g12',
	'cleanup': 'a1',
	'nc': 'a2',
	'query': 'a3',
	'split': 'a4',
	'transwiki': 'a5',
	'redirnone': 'r1',
	'redirorphan': 'r3',
	'dupeimg': 'i1',
	'corruptimg': 'i2',
	'noimgsrc': 'i4',
	'unusedFU': 'i5',
	'norat': 'i6',
	'badfairuse': 'i7',
	'nowcommons': 'i8',
	'imgcopyvio': 'i9',
	'catempty': 'c1',
	'userreq': 'u1',
	'template': 't1',
};

twinklespeedy.reasonHash = {
	'badpage': 'Nonsense, spam or vandalism page',
	'newbook': '',
	'repost': 'repost of deleted content',
	'nocontent': 'no meaningful content',
	'rfd': 'per RFD',
	'g13': '',
	'author': 'the only editor requested deletion',
	'blanked': 'the only editor has blanked the page',
	'talk': 'was a talk page whose corresponding page does not exist',
	'copyvio': '[[WB:COPYVIO|copyright violation]] unresolved after 7 days',
	'query': 'had no meaningful content after 7 days tagged with {{[[Template:qr-em|query]]}}',
	'transwiki': 'was transwikied to the appropriate wiki',
	'redirnone': 'was a redirect to a non-existent page',
	'redirorphan': 'orphaned redirect',
	'dupeimg': 'a same or better image exists',
	'corruptimg': 'was a corrupt or empty image',
	'noimgsrc': 'Image tagged with [[WB:NLD|nld]] for more than seven days',
	'unusedFU': 'unused fair use image',
	'norat': 'was an image with fair use tag but no fair use rationale for more than seven days',
	'badfairuse': 'incompatible [[WB:MEDIA|licensing]]/invalid fair use claim',
	'nowcommons': 'nowcommons',
	'imgcopyvio': 'unresolved [[WB:COPYVIO|copyright violation]] over 7 days old',
	'catempty': 'was an empty category',
	'userreq': 'was a user page whose user requested deletion',
};

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 ) {
				mw.config.get('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 exists, perhaps it has already been deleted" );
				return;
			}
			var query = {
				'title': mw.config.get('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(
				TwinkleSpeedyConfig.deleteTalkPageOnDelete &&
				mw.config.get('wgNamespaceNumber') % 2 == 0 &&
				document.getElementById( 'ca-talk' ).className != 'new'
			) {
				var talk_page = mw.config.get('wgFormattedNamespaces')[ mw.config.get('wgNamespaceNumber')  + 1 ] + ':' + mw.config.get('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( mw.config.get('wgNamespaceNumber') == 6 && self.params.normalized != 'i8' ) {
				var query = {
					'action': 'query',
					'list': 'imageusage',
					'titles': mw.config.get('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 = TwinkleSpeedyConfig.orphanBacklinksOnSpeedyDelete;
			if(
				doOrphan.orphan &&
				doOrphan.exclude.indexOf( self.params.normalized.toLowerCase() ) == -1
			) {
				var query = {
					'action': 'query',
					'list': 'backlinks',
					'blfilterredir': 'nonredirects',
					'bltitle': mw.config.get('wgPageName'),
					'bllimit': userIsInGroup( 'sysop' ) ? 5000 : 500, // 500 is max for normal users, 5000 for bots and sysops
					'blnamespace': [0] // Main namespace only
				};
				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': mw.config.get('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 = mw.config.get('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,
				'wpStarttime': form.wpStarttime.value,
				'wpEdittime': form.wpEdittime.value,
				'wpAutoSummary': form.wpAutoSummary.value,
				'wpEditToken': form.wpEditToken.value,
				'wpSummary': 'Removing backlinks to ' + self.params.page + " (deleted per [[WB:SPEEDY|policy]])" + "; " + TwinkleSpeedyConfig.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 = {
					'wpReason': "Speedy deleted per [[WB:SPEEDY|policy]], Redirect to deleted page \"" + mw.config.get('wgPageName') + "\"." + TwinkleSpeedyConfig.deletionSummaryAd,
					'wpEditToken': form.wpEditToken.value
				}
			} else {

				var postData = {
					'wpReason': "[[WB:SPEEDY|Speedy deleted]]; Redirect to deleted page \"" + mw.config.get('wgPageName') + "\"." + TwinkleSpeedyConfig.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 image 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 = mw.config.get('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,
				'wpStarttime': form.wpStarttime.value,
				'wpEdittime': form.wpEdittime.value,
				'wpAutoSummary': form.wpAutoSummary.value,
				'wpEditToken': form.wpEditToken.value,
				'wpSummary': 'Removing instance of image ' + self.params.image + " (speedily deleted per [[WB:SPEEDY|policy]])" + "; " + TwinkleSpeedyConfig.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];
				switch (self.params.normalized){
				case 'g12':
					var source = prompt('Please enter the source if possible')
					if (source == null) {
						return;
					}
					var postData = {
						'wpReason': "[[WB:COPYVIO|copyvio]] (" + source + ") unresolved after 7 days" + TwinkleSpeedyConfig.deletionSummaryAd,
						'wpEditToken': form.wpEditToken.value
					}
					self.post(postData);
					break;
				case 'i9':
					var source = prompt('Please enter the source if possible')
					if (source == null) {
						return;
					}
					var postData = {
						'wpReason': "[[WB:COPYVIO|copyvio]] (" + source + ") unresolved after 7 days" + TwinkleSpeedyConfig.deletionSummaryAd,
						'wpEditToken': form.wpEditToken.value
					}
					break;
					self.post(postData);
					break;
					case 'g2':
					window.alert ('I can\'t let you do that, Dave.');
					break;//don't ever delete on g2 (new book)
				case 'a1'://cleanup w/ mandatory parameter
					window.alert ('I can\'t let you do that, Dave.');
					break;//don't ever delete on a1 (cleanup)
				case 'a2':
					window.alert ('I can\'t let you do that, Dave.');
					break;//don't ever delete on a2 (fix title)
				case 'a4':
					window.alert ('I can\'t let you do that, Dave.');
					break;//don't ever delete on a4 (split)
				case 't1'://template; requires prompt
					var why = prompt('Enter a reason for speedy deletion.')
					if (why == null) {
						return;
					}
					var postData = {
						'wpReason': "[[WB:DP|Deleted]] because " + why + "." + TwinkleSpeedyConfig.deletionSummaryAd,
						'wpEditToken': form.wpEditToken.value
					};
					self.post(postData);
					break;
				case 'i1'://redundant image
					var img = prompt('Enter the image this one is redundant to with the Image: prefix.')
					if (img == null){
						return;
					}
					var postData = {
						'wpReason': "[[WB:SPEEDY|Speedy deleted]] because this image is redundant to [[:" + img + "]]" + TwinkleSpeedyConfig.deletionSummaryAd,
						'wpEditToken': form.wpEditToken.value
					};
					self.post(postData);
					break;
				case 'g9'://rfd
					var archive = prompt('enter the full page name of the archived RFD (excluding [[ and ]] like this: Wikibooks:Requests for deletion/ArchivedDiscussion)')
					if (archive == null){
						return;
					}
					var postData = {
						'wpReason': "Deleted per [[" + archive + "|RFD]]" + TwinkleSpeedyConfig.deletionSummaryAd,
						'wpEditToken': form.wpEditToken.value
					}
					self.post(postData);
					break;
				case 'g4'://repost
					var archive = prompt('Enter the full page name of the archived RFD (excluding [[ and ]] like this: Wikibooks:Requests for deletion/ArchivedDiscussion)')
					if (archive == null) {
						return;
					}
					var postData = {
						'wpReason': "Repost of [[" + archive + "|deleted content]])" + TwinkleSpeedyConfig.deleteionSummaryAd,
						'wpEditToken': form.wpEditToken.value
					}
					self.post(postData);
					break;
				case 'a3'://query
					var postData = {
						'wpReason': "[[WB:SPEEDY|No meaningful content]] after 7 days tagged with {{[[Template:Qr-em|query]]}} " + TwinkleSpeedyConfig.deletionSummaryAd,
						'wpEditToken': form.wpEditToken.value
					}
					self.post(postData);
					break;
				case 'g13'://general
					var why = prompt('enter a reason for deletion')
					if (why == null){
						return;
					}
					var postData = {
						'wpReason': "Deleted per [[WB:SPEEDY|policy]] because " + why + TwinkleSpeedyConfig.deletionSummaryAd,
						'wpEditToken': form.wpEditToken.value
					}
					self.post(postData);
					break;
				default://everything else
					var postData = {
						'wpReason': "Speedy deleted per [[WB:SPEEDY|policy]]; " + self.params.reason + "." + TwinkleSpeedyConfig.deletionSummaryAd,
						'wpEditToken': form.wpEditToken.value
					}
					self.post(postData);
					break;
				}
			}
			else {
				switch (self.params.normalized){
				case 'g12':
					var source = prompt('Please enter the source if possible')
					if (source == null) {
						return;
					}
					var postData = {
						'wpReason': "[[WB:COPYVIO|copyvio]] (" + source + ") unresolved after 7 days" + TwinkleSpeedyConfig.deletionSummaryAd,
						'wpEditToken': form.wpEditToken.value
					}
					self.post(postData);
					break;
				case 'i9':
					var source = prompt('Please enter the source if possible')
					if (source == null) {
						return;
					}
					var postData = {
						'wpReason': "[[WB:COPYVIO|copyvio]] (" + source + ") unresolved after 7 days" + TwinkleSpeedyConfig.deletionSummaryAd,
						'wpEditToken': form.wpEditToken.value
					}
					self.post(postData);
					break;
				case 'g2':
					window.alert ('I can\'t let you do that, Dave.');
					break;//don't ever delete on g2 (new book)
				case 'a1'://cleanup w/ mandatory parameter
					window.alert ('I can\'t let you do that, Dave.');
					break;//don't ever delete on a1 (cleanup)
				case 'a2':
					window.alert ('I can\'t let you do that, Dave.');
					break;//don't ever delete on a2 (fix title)
				case 'a4':
					window.alert ('I can\'t let you do that, Dave.');
					break;//don't ever delete on a4 (split)
				case 't1'://template; requires prompt
					var why = prompt('Enter a reason for speedy deletion.')
					if (why == null) {
						return;
					}
					var postData = {
						'wpReason': "[[WB:DP|Deleted]] because " + why + "." + TwinkleSpeedyConfig.deletionSummaryAd,
						'wpEditToken': form.wpEditToken.value
					};
					self.post(postData);
					break;
				case 'i1'://redundant image
					var img = prompt('Enter the image this one is redundant to with the Image: prefix.')
					if (img == null){
						return;
					}
					var postData = {
						'wpReason': "[[WB:SPEEDY|Speedy deleted]] because this image is redundant to [[:" + img + "]]" + TwinkleSpeedyConfig.deletionSummaryAd,
						'wpEditToken': form.wpEditToken.value
					};
					self.post(postData);
					break;
				case 'g4'://repost
					var archive = prompt('Enter the full page name of the archived RFD (excluding [[ and ]] like this: Wikibooks:Requests for deletion/ArchivedDiscussion)')
					if (archive == null) {
						return;
					}
					var postData = {
						'wpReason': "Repost of [[" + archive + "|deleted content]])" + TwinkleSpeedyConfig.deleteionSummaryAd,
						'wpEditToken': form.wpEditToken.value
					}
					self.post(postData);
					break;
				case 'g9'://rfd
					var archive = prompt('enter the full page name of the archived RFD (excluding [[ and ]] like this: Wikibooks:Requests for deletion/ArchivedDiscussion)')
					if (archive == null){
						return;
					}
					var postData = {
						'wpReason': "Deleted per [[" + archive + "|RFD]]" + TwinkleSpeedyConfig.deletionSummaryAd,
						'wpEditToken': form.wpEditToken.value
					}
					self.post(postData);
					break;
				case 'a3'://query
					var postData = {
						'wpReason': "[[WB:SPEEDY|No meaningful content]] after 7 days tagged with {{[[Template:Qr-em|query]]}} " + TwinkleSpeedyConfig.deletionSummaryAd,
						'wpEditToken': form.wpEditToken.value
					}
					self.post(postData);
					break;
				case 'g13'://general
					var why = prompt('enter a reason for deletion')
					if (why == null){
						return;
					}
					var postData = {
						'wpReason': "Deleted per [[WB:SPEEDY|policy]] because " + why + TwinkleSpeedyConfig.deletionSummaryAd,
						'wpEditToken': form.wpEditToken.value
					}
					self.post(postData);
					break;
				default:
					var postData = {
						'wpReason': "Speedy deleted per [[WB:SPEEDY|policy]]; " + self.params.reason + "." + TwinkleSpeedyConfig.deletionSummaryAd,
						'wpEditToken': form.wpEditToken.value
					}
					self.post(postData);
					break;
				}
			}
		},
		deleteTalkPage: function( self ) {
			form = this.responseXML.getElementById( 'deleteconfirm' );
			var postData = {
				'wpReason': "Speedy deleted per [[WB:SPEEDY|policy]]; was a talk page of deleted content." + TwinkleSpeedyConfig.deletionSummaryAd,
				'wpEditToken': form.wpEditToken.value
			}
			self.post( postData );//this deletes the talk page, supposedly :\
		}
	},
	user: {
		main: function( self ) {
			var xmlDoc = self.responseXML;
			var normal = xmlDoc.evaluate( '//normalized/n/@to', xmlDoc, null, XPathResult.STRING_TYPE, null ).stringValue;
			if( normal ) {
				mw.config.get('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 exists, perhaps it has already been deleted" );
				return;
			}
			var query = {
				'title': mw.config.get('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;
//check for tag was removed here
			var code;
			switch( self.params.normalized ) {
			case 'g1'://nonsense
				var code = "{{delete|[[WB:SPEEDY|nonsense, spam or vandalism]] page}}";
				break;
			case 'g2'://new book
				var code = "{{new book}}";
				break;
			case 'g4'://'repost of deleted content
				var code = "{{delete|[[WB:SPEEDY|repost of deleted content]]}}";
				break;
			case 'g9'://nominate for RFD
				var code = "{{rfd}}";
				break;
			case 'g7'://only editor requested deletion
				var code = "{{delete|the only editor requested [[WB:SPEEDY|deletion]]}}";
				break;
			case 'a1'://cleanup
				var clean = prompt('Enter a comment regarding what cleanup is needed');
				if (clean == null) {
					return;
				}
				var code = "{{cleanup|" + clean + "}}";
				break;
			case 'a2'://fix title
				var code = "{{fix title}}";
				break;
			case 'a3': //{{query}}
				var comments = prompt('Enter any additional comments for the author');
				if (comments != null) {
					var code = "{{query|" + comments + "}}"
				} else {
					var code = "{{query" + "}}";
				}
				break;
			case 'a4'://{{split}}
				var code = "{{split}}"
				break;
			case 'a5'://was transwikied
				var wikiwiki = prompt( 'Enter which project this should get moved to' );
				if( wikiwiki == null ) {
					return;
				}
				var code = "{{transwiki|" + wikiwiki + "}}";
				break;
			case 'r1'://broken redirect
				var code = "{{delete|broken redirect}}";
				break;
			case 'r3'://orphan redirect
				var code = "{{delete|orphan redirect}}";
				break;
			case 'i2'://broken image
				var code = "{{delete|corrupt or empty media}}";
				break;
			case 'i4'://{{nld}}
				var code = "{{sub" + "st:nld}}";
				break;
			case 'i5'://unused fair use image
				var code = "{{delete|unused fair use image}}";
				break;
			case 'i6'://no fair use rationale
				var code = "{{sub" + "st:nfur}}";
				break;
			case 'i7'://invalid fair use claim
				var code = "{{sub" + "st:bfu}}";
				break;
			case 'i9'://copyvio image
				var url = prompt( 'please enter url if available' );
				if( url == null ) {
					return;
				}
				code = "{{copyvio|1=" + url + "}}";
				break;
			case 'c1'://empty cat
				var code = "{{delete|empty category}}";
				break;
			case 'u1'://user request
				var code = "{{delete|userpage of a user requesting [[WB:SPEEDY|deletion]]}}";
				break;
			case 't1'://template per policy
				var reason = prompt( 'Please enter a reason to delete this template');
				if( reason == null ) {
					return;
				}
				var code = "{{delete|" + reason + "}}";
				break;
			case 'i8'://nowcommons
				var commonsimage = prompt( 'enter the image name on commons, including the Image: prefix' );
				if( commonsimage == null) {
					return;
				}
				var code =  "{{sub" + "st:ncd|" + commonsimage + "}}";
				break;
			case 'g12'://copyvio page
				var url = prompt( 'please enter url if available' );
				if( url == null ) {
					return;
				}
				code = "{{copyvio|1=" + url + "}}";
				break;
			//for rfds
			case 'g9'://nom for RFD
				var code = "{{rfd}}";
				break;
			//for generic speedies
			case 'g13':
				var genericreason = prompt( 'enter a detailed reason for deletion:' );
				if (genericreason == null) {
					return;
				}
				code = "{{delete|" + genericreason + "}}";
				break;
			case 'i1'://dupe image
				var img = prompt( 'enter the image this is redundant to, including the Image: prefix' );
				if( img == null ) {
					return;
				}
				code = "{{delete|redundant to [[:" + img + "]]}}";
				break;
			default://the rest, in case I missed one
				code = "{{delete}}";
				break;
			}
			// Notification to first contributor
			var query = {
				'action': 'query',
				'prop': 'revisions',
				'titles': mw.config.get('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': TwinkleSpeedyConfig.markSpeedyPagesAsMinor ? '' : undefined,
				'wpStarttime': form.wpStarttime.value,
				'wpEdittime': form.wpEdittime.value,
				'wpAutoSummary': form.wpAutoSummary.value,
				'wpEditToken': form.wpEditToken.value,
				'wpSummary': "Speedy tagging" + TwinkleSpeedyConfig.summaryAd,
				'wpTextbox1': code + "\n" + text
			};
			//patrol this page if possible
/*			var patrolled = getElementsByClassName(document.getElementById('content'), 'div', 'patrollink');
				if (patrolled && patrolled[0]) {
					var link = patrolled[0].getElementsByTagName('a')[0];
					var makepatrolled = new XMLHttpRequest();
					makepatrolled.open('GET', link, false);
					makepatrolled.send(null);
					if (makepatrolled.status == 200) {
						dump(makepatrolled.responseText);
					}
				}*/
			self.post( postData );
		},
		userNotification: function( self ) {
			var form = self.responseXML.getElementById( 'editform' );
			var text = form.wpTextbox1.value;
			var code;
			switch( self.params.normalized ) {
			//g9: rfd a3: query i9: imgcopyvio g12: copyvio
			case 'i6'://no fair use rationale
				text+= "\n{{sub" + "st:Image fairuse|" + mw.config.get('wgPageName') + "|~~" + "~~}}";
				break;
			case 'i7'://bad fair use claim
				text+= "\n{{sub" + "st:Image badfairuse|" + mw.config.get('wgPageName') + +"|~~" + "~~}}";
				break;
			case 'g9'://RFD
				text += "\n{{sub" + "st:Vfd warning|" + mw.config.get('wgPageName') + "|~~" + "~~}}";
				break;
			case 'a3'://query
				text += "\n{{sub" + "st:Query notice|" + mw.config.get('wgPageName') + "|~~" + "~~}}";
				break;
			case 'i9'://image copyvio
				text += "\n{{sub" + "st:Nothanks|" + mw.config.get('wgPageName') + "|~~" + "~~}}";
				break;
			case 'g12'://copyvio
				text += "\n{{sub" + "st:Nothanks|" + mw.config.get('wgPageName') + "|~~" + "~~}}";
				break;
			case 'i4'://nld
				text += "\n{{sub" + "st:Image copyright|" + mw.config.get('wgPageName') + "|~~" + "~~}}";
				break;
			default://template:test for anything missed :\
				text += "\n{{sub" + "st:test|~~" + "~~}}";
				break;
			}
			var xmlDoc = self.responseXML;
			var normal = xmlDoc.evaluate( '//normalized/n/@to', xmlDoc, null, XPathResult.STRING_TYPE, null ).stringValue;
			if( normal ) {
				mw.config.get('wgPageName') = normal;
			}
			var exists = xmlDoc.evaluate( 'boolean(//pages/page[not(@missing)])', xmlDoc, null, XPathResult.BOOLEAN_TYPE, null ).booleanValue;
			if( exists ) {
				text = "{{sub" + "st:welcome}}~~" + "~~" + text;
			}
			var postData = {
				'wpMinoredit': form.wpMinoredit.checked ? '' : undefined,
				'wpStarttime': form.wpStarttime.value,
				'wpEdittime': form.wpEdittime.value,
				'wpAutoSummary': form.wpAutoSummary.value,
				'wpEditToken': form.wpEditToken.value,
				'wpSummary': 'Notification regarding [[:' + mw.config.get('wgPageName') + ']].' + TwinkleSpeedyConfig.summaryAd,
				'wpTextbox1': text
			};
			self.post( postData );
			},
		}
	}
twinklespeedy.callback.evaluateSysop = function twinklespeedyCallbackEvaluateSysop(e) {

	mw.config.get('wgPageName') = mw.config.get('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 ];

	//this was intended to make sure the var is not undefined in some cases as reported by Reece.
	//While it is true that the parameter is undefined here, it somehow works properly for everyone but him.
	//By having this here, we get normalized=='g13' but we also get it passed properly when deletion actually happens
	//So I'm not sure where the parameter /is/ being passed, but it is not here. I am horribly confused by this, but
	//perhaps enabling JSL for him will help? We can hope :) otherwise I am not sure what to do.
	//if ( ! self.params.normalized ){
	//	self.params.normalized = 'g13';
	//}
	switch (normalized){
	case 'i1'://redundant image
		var img = prompt('Enter the image this one is redundant to with the Image: prefix.')
		if (img == null){
			return;
		}
		var params = {
			value: value,
			normalized: normalized,
			reason: "[[WB:SPEEDY|Speedy deleted]] because this image is redundant to [[:" + img + "]]" + TwinkleSpeedyConfig.deletionSummaryAd
		};
		break;
	case 'a5'://transwiki
		var wiki = prompt('Enter the interwiki link to the content without [[ or ]].')
		if (wiki == null){
			return;
		}
		var params = {
			value: value,
			normalized: normalized,
			reason: "[[" + wiki + "|Transwikied]]" + TwinkleSpeedyConfig.deletionSummaryAd
		};
		break;
	case 'i8'://nowcommons
		var img = prompt('Enter the image name on commons with the Image: prefix.')
		if (img == null){
			return;
		}
		var params = {
			value: value,
			normalized: normalized,
			reason: "NowCommons: [[:commons:" + img + "]]" + TwinkleSpeedyConfig.deletionSummaryAd
		};
		break;
	case 'g9'://rfd
		var archive = prompt('enter the full page name of the archived RFD (excluding [[ and ]] like this: Wikibooks:Requests for deletion/ArchivedDiscussion)')
		if (archive == null){
			return;
		}
		var params = {
			value: value,
			normalized: normalized,
			reason: "Deleted per [[" + archive + "|RFD]]" + TwinkleSpeedyConfig.deletionSummaryAd
		};
		break;
	case 'g13'://general
		var why = prompt('Enter a reason for deletion:')
		if (why == null){
			return;
		}
		var params = {
			value: value,
			normalized: normalized,
			reason: "Deleted per [[WB:SPEEDY|policy]] because " + why + TwinkleSpeedyConfig.deletionSummarAd
		}
		break;
	default:
		var params = {
			value: value,
			normalized: normalized,
			reason: twinklespeedy.reasonHash[ value ]
		};
		break;
	}

	Status.init( e.target.form );

	var query = {
		'action': 'query',
		'titles': mw.config.get('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) {
	mw.config.get('wgPageName') = mw.config.get('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,
		usertalk: TwinkleSpeedyConfig.notifyUserOnSpeedyDeletionNomination.indexOf( normalized ) != -1 && e.target.form.notify.checked
	};

	Status.init( e.target.form );

	Wikipedia.actionCompleted.redirect = mw.config.get('wgPageName');
	Wikipedia.actionCompleted.notice = "Tagging complete";

	var query = {
		'action': 'query',
		'titles': mw.config.get('wgPageName')
	}

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

}
//</pre></nowiki>
华夏公益教科书