User:Mike.lifeguard/TSdev.js

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

var version = "devlopment version 0.0.13a"; //this module has its own configuration TwinkleSpeedyConfig = { userTalkPageMode						:	'tab', summaryAd								:	" using TW", deletionSummaryAd						:	" using TW", deleteTalkPageOnDelete					:	true, markSpeedyPagesAsMinor					:	true, notifyUserOnSpeedyDeletionNomination	:	[ 'g9',//vfd '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( 'patroller' ) || userIsInGroup( 'sysop' ) ) { //check for IsArticle on wgAction=(true|purge|history|rollback) if( (wgIsArticle == true && (wgAction == "view" || wgAction == "purge" || wgAction == "rollback" || wgAction == "markpatrolled")) || (wgIsArticle == false && wgAction == "history") ) { //check for not Main Page if( 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 ('patroller') ) {			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 http://en.wikibooks.org/wiki/User:Mike.lifeguard/Twinkle_Speedy_documentation");', 'csd', 'tw-csd', 'Twinkle speedy tag', '');		}	} } $(twinklespeedy);

twinklespeedy.callback = function twinklespeedyCallback { var Window = new SimpleWindow( 800, 400 ); Window.setTitle( "Speedy tagify, notify and deletify " + version );

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( wgNamespaceNumber == Namespace.IMAGE ) { 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: ', 						value: 'noimgsrc',						tooltip: 'Tag-only: Tags an image with 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 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: ', 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( wgNamespaceNumber == 0 || wgNamespaceNumber == 1 ||wgNamespaceNumber == 102 ||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: {' + '{subpages}}', value: 'split', tooltip: 'Tag-only: Tag a module to be split into subpages. If deleting: Impossible.' },				{					label: 'Books violating the naming policy: {' + '{cleanup-nc}}', 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:VFD. If deleting: Admins may delete reposted content here.' },				{					label: 'VFD', value: 'vfd', tooltip: 'Tag-only: You\'ll tag it for deletion by VFD; don\'t forget to create the appropriate section at WB:VFD. If deleting: Admins may use this to delete after a VFD (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( wgNamespaceNumber == 14 || 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( wgNamespaceNumber == 2 || 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( wgNamespaceNumber == 10 || 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', 'vfd': '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', 'vfd': 'per VFD', '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': 'copyright violation unresolved after 7 days', 'query': 'had no meaningful content after 7 days tagged with ', '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 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 licensing/invalid fair use claim', 'nowcommons': 'nowcommons', 'imgcopyvio': 'unresolved 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 ) { 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': 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 && 				wgNamespaceNumber % 2 == 0 && 				document.getElementById( 'ca-talk' ).className != 'new' 			) { var talk_page = namespaces[ wgNamespaceNumber + 1 ] + ':' + wgTitle; var query = query = { 'title': talk_page, 'action': 'delete' };				var wikipedia_wiki = new Wikipedia.wiki( 'Deleting talk page', query, twinklespeedy.callbacks.sysop.deleteTalkPage ); wikipedia_wiki.params = self.params; wikipedia_wiki.followRedirect = false; wikipedia_wiki.get; }

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

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

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

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

var total = snapshot.snapshotLength * 2;

var onsuccess = function( self ) { var obj = self.params.obj; var total = self.params.total; var now = parseInt( 100 * ++(self.params.current)/total ) + '%'; obj.update( now ); self.statelem.unlink; if( self.params.current >= total ) { obj.info( now + ' (completed)' ); Wikipedia.removeCheckpoint; }			}			var onloaded = onsuccess;

var onloading = function( self ) {}

Wikipedia.addCheckpoint; if( snapshot.snapshotLength == 0 ) { statusIndicator.info( '100% (completed)' ); Wikipedia.removeCheckpoint; return; }

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

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

text = wikiPage.getText; if( text == old_text ) { // Nothing to do, return self.onsuccess( self ); Wikipedia.actionCompleted( self ); return; }			var postData = { 'wpMinoredit': 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 + " (deleted per 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 policy, Redirect to deleted page \"" + wgPageName + "\"." + TwinkleSpeedyConfig.deletionSummaryAd,					'wpEditToken': form.wpEditToken.value				}			} else {

var postData = { 'wpReason': "Speedy deleted; Redirect to deleted page \"" + 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 = 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 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': "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': "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 (cleanup-nc) 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': "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': "Speedy deleted because this image is redundant to " + img + "" + TwinkleSpeedyConfig.deletionSummaryAd, 'wpEditToken': form.wpEditToken.value };					self.post(postData); break; case 'g9'://vfd var archive = prompt('enter the full page name of the archived VFD (excluding and  like this: Wikibooks:Votes for deletion/ArchivedDiscussion)') if (archive == null){ return; }					var postData = { 'wpReason': "Deleted per VFD" + TwinkleSpeedyConfig.deletionSummaryAd, 'wpEditToken': form.wpEditToken.value }					self.post(postData); break; case 'g4'://repost var archive = prompt('Enter the full page name of the archived VFD (excluding and  like this: Wikibooks:Votes for deletion/ArchivedDiscussion)') if (archive == null) { return; }					var postData = { 'wpReason': "Repost of deleted content)" + TwinkleSpeedyConfig.deleteionSummaryAd,						'wpEditToken': form.wpEditToken.value					}					self.post(postData);					break;				case 'a3'://query					var postData = {						'wpReason': "No meaningful content after 7 days tagged with " + 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 policy because " + why + TwinkleSpeedyConfig.deletionSummaryAd,						'wpEditToken': form.wpEditToken.value					}					self.post(postData);					break;				default://everything else					var postData = {						'wpReason': "Speedy deleted per 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': "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': "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 (cleanup-nc) 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': "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': "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 VFD (excluding and  like this: Wikibooks:Votes for deletion/ArchivedDiscussion)') if (archive == null) { return; }					var postData = { 'wpReason': "Repost of deleted content)" + TwinkleSpeedyConfig.deleteionSummaryAd,						'wpEditToken': form.wpEditToken.value					}					self.post(postData);					break;				case 'g9'://vfd					var archive = prompt('enter the full page name of the archived VFD (excluding and  like this: Wikibooks:Votes for deletion/ArchivedDiscussion)')					if (archive == null){						return;					}					var postData = {						'wpReason': "Deleted per VFD" + TwinkleSpeedyConfig.deletionSummaryAd,						'wpEditToken': form.wpEditToken.value					}					self.post(postData);					break;				case 'a3'://query					var postData = {						'wpReason': "No meaningful content after 7 days tagged with  " + 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 policy because " + why + TwinkleSpeedyConfig.deletionSummaryAd, 'wpEditToken': form.wpEditToken.value }					self.post(postData); break; default: var postData = { 'wpReason': "Speedy deleted per 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 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 ) { 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': 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|nonsense, spam or vandalism page}}"; break; case 'g2'://new book var code = "{" + "{new book}}"; break; case 'g4'://'repost of deleted content var code = "{" + "{delete|repost of deleted content}}"; break; case 'g9'://nominate for VFD var code = "{" + "{vfd}}"; break; case 'g7'://only editor requested deletion var code = "{" + "{delete|the only editor requested 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'://cleanup-nc var code = "{" + "{cleanup-nc}}"; 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 = ""; break; case 'i5'://unused fair use image var code = "{" + "{delete|unused fair use image}}"; break; case 'i6'://no fair use rationale var code = ""; break; case 'i7'://invalid fair use claim var code = ""; 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 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 = "{" + "{Now Commons|1=" + commonsimage + "}}"; break; case 'g12'://copyvio page var url = prompt( 'please enter url if available' ); if( url == null ) { return; }				code = "{" + "{copyvio|1=" + url + "}}"; break; //for vfds case 'g9'://nom for VFD var code = "{" + "{vfd}}"; 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': 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: vfd a3: query i9: imgcopyvio g12: copyvio case 'i6'://no fair use rationale text+= "\n"; break; case 'i7'://bad fair use claim text+= "\n"; break; case 'g9'://VFD text += "\n"; break; case 'a3'://query text += "\n"; break; case 'i9'://image copyvio text += "\n"; break; case 'g12'://copyvio text += "\n"; break; case 'i4'://nld text += "\n"; break; default://template:test for anything missed :\ text += "\n"; break; }			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 ) { text = "" + "" + 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 ' + wgPageName + '.' + TwinkleSpeedyConfig.summaryAd, 'wpTextbox1': text };			self.post( postData ); },		}	} twinklespeedy.callback.evaluateSysop = function twinklespeedyCallbackEvaluateSysop(e) {

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

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

var value = e.target.value; var normalized = twinklespeedy.normalizeHash[ value ]; //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. ////Addendum: in the switch(normalized){ line (5 down), I just changed "self.params.normalized" to "normalized" since ////I changed the structure of that variable //	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: "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: "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'://vfd var archive = prompt('enter the full page name of the archived VFD (excluding and  like this: Wikibooks:Votes for deletion/ArchivedDiscussion)') if (archive == null){ return; }		var params = { value: value, normalized: normalized, reason: "Deleted per VFD" + 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 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': wgPageName }	var wikipedia_api = new Wikipedia.api( 'Checking if page exists', query, twinklespeedy.callbacks.sysop.main ); wikipedia_api.params = params; wikipedia_api.post; } twinklespeedy.callback.evaluateUser = function twinklespeedyCallbackEvaluateUser(e) { wgPageName = wgPageName.replace( /_/g, ' ' ); // for queen/king/whatever and country! var value = e.target.value; var normalized = twinklespeedy.normalizeHash[ value ];

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

Status.init( e.target.form );

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

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

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

}