Jump to content

User:Holly Cheng/dev quickimgdelete.js

From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
/* <pre><nowiki> */
/* quickimgdelete.js
 * Current version: 2.4.1
 * =======================================
 * Created by [[User:Howcheng|Howard Cheng]]
 * Released under the [[GNU Public License]] (GPL)
 * Full documentation at 	[[User talk:Howcheng/quickimgdelete.js]]
 * =======================================
 */
// ==General configuration==
var qid_testFilePage = "User:Howcheng/Sandbox";
var qid_testUserPage = "User:Howcheng/SandboxRedirect";
var qid_testLogPage = "User:Howcheng/Sandbox3";
var qid_editToken; // needed for editing by API
var qid_action; // the action code (passed by the link click)
var qid_templateAddError = false; // flag for error adding to file description page

// == Shared functions ==
function qid_makeApiCall(method, parms, data) {
	var url = "/w/api.php?format=json";
	if (parms)
		url += "&" + parms;
	var promise = $.ajax({
		type: method,
		url: url,
		async: false,
		data: data
	});
	return promise;
}
function qid_getPageInfo(result) {
	var pageId = qid_getPageId(result);
	return result.query.pages[pageId];
}
function qid_getPageContent(page) {
	return page.revisions[0].slots.main["*"];
}
function qid_setDialogMessage(message) {
	mw.notify(message);
}
function qid_getPageId(result) {
	var pageId = mw.config.get('wgArticleId') + '';
	if (result.query.pages) {
		var pageIds = Object.keys(result.query.pages);
		pageId = pageIds[0];
	}
	return pageId;
}

function qid_getFileInfo() {
	// retrieve upload data, content, and edit token
	var data = {
		'action': 'query',
		'prop': 'imageinfo|info|revisions',
		'iiprop': 'user|timestamp',
		'iilimit': 10,
		'rvprop': 'content',
		'rvslots': '*',
		'redirects': '',
		'iilocalonly': '',
		'titles': mw.config.get('wgPageName'),
		'meta': 'tokens'
	};
	var promise = qid_makeApiCall("POST", null, data);
	promise.done(qid_getEditToken);
	promise.fail(qid_getFileInfo_error);
	return promise;
}
function qid_getFileInfo_error() {
	qid_setDialogMessage("An error occurred while attempting to get the file info");
}
function qid_getEditToken(result) {
	if (!result.query.tokens)
		qid_setDialogMessage("Could not find the CSRF token");
	var tokens = result.query.tokens;
	qid_editToken = tokens.csrftoken;
}

function qid_addTemplateToFilePage(page, templateWikiText, summary, templatesToRemove) {
	var content = qid_getPageContent(page);
	if (templatesToRemove) {
		for (var i = 0; i < templatesToRemove.length; i++) {
			content = qid_removeTemplate(content, templatesToRemove[i]);
		}
	}
	content = templateWikiText + '\n' + content;

	// get the current timestamp for edit conflict avoidance
	var now = new Date();
	var tsYear = now.getUTCFullYear() + '';
	var tsMonth = (now.getUTCMonth() + '').padStart(2, '0');
	var tsDay = (now.getUTCDate() + '').padStart(2, '0');
	var tsHours = (now.getUTCHours() + '').padStart(2, '0');
	var tsMins = (now.getUTCMinutes() + '').padStart(2, '0');
	var tsSecs = (now.getUTCSeconds() + '').padStart(2, '0');
	var tsMsecs = (now.getUTCMilliseconds() + '').padStart(3, '0');
	var timestamp = tsYear + '-' + tsMonth + '-' + tsDay + 'T' + tsHours + ':' + tsMins + ':' + tsSecs + '.' + tsMsecs + 'Z';
	
	var targetPage = qid_testFilePage ? qid_testFilePage : page.title;
	console.log('Attempting to add ' + templateWikiText + ' to ' + targetPage + (targetPage === qid_testFilePage ? '' : ' (supposed to be ' + page.title + ')'));

	var editData = {
		'action': 'edit',
		'format': 'json',
		'title': targetPage,
		'summary': summary + ' (using [[User talk:Howcheng/quickimgdelete.js|quickimgdelete]])',
		'starttimestamp': timestamp,
		'contentmodel': 'wikitext',
		'contentformat': 'text/x-wiki',
		'text': content,
		'token': qid_editToken
	};
	var promise = $.ajax({
		type: "POST",
		url: mw.util.wikiScript('api'),
		data: editData,
		dataType: 'json'
	});
	promise.then(function(result) {
			qid_processEditSuccess(result, 'Template added to ' + mw.config.get('wgPageName'));
		}, function(result) {
	        qid_setDialogMessage('Error: Request failed adding template to ' + mw.config.get('wgPageName'));
	        qid_templateAddError = true;
	    })
	    .then(function(result) {
	    	if (qid_templateAddError)
	    		return;
	    	// get parsed template HTML
	    	var parseData = {
	    		'action': 'parse',
	    		'contentmodel': 'wikitext',
	    		'prop': 'text',
	    		'pst': '',
	    		'title': mw.config.get('wgPageName'),
	    		'text': templateWikiText
	    	};
	    	var parsePromise = qid_makeApiCall("POST", null, parseData);
	    	parsePromise.done(function(result) {
	    		// inject into page
	    		var parsed = result.parse.text["*"];
	    		$('#mw-imagepage-content').prepend(parsed);
	    	});
	    	console.log('Injected parsed template HTML into ' + mw.config.get('wgPageName'));
	    });
	return promise;
}

function qid_notifyUploadersWhoAreNotBots(page, notifyFunc) {
	var userList = [];
	for (var i = 0; i < page.imageinfo.length; i++) {
		var username = page.imageinfo[i].user;
		userList.push(username);
	}
	var listData = {
		'action': 'query',
		'list': 'users',
		'ususers': userList.join('|'),
		'usprop': 'groups'
	};
	var promise = qid_makeApiCall("POST", null, listData);
	promise.done(function(result) {
		for (var i = 0; i < result.query.users.length; i++) {
			var user = result.query.users[i];
			var isBot = false;
			for (var j = 0; j < user.groups.length; j++) {
				if (user.groups[j] === 'bot') {
					isBot = true;
					break;
				}
			}
			if (isBot) {
				console.log('User:' + user + ' is a bot; not going to leave a notification');
				continue;
			}
			// determine if user talk is redirected somewhere else (e.g. renamed user)
			var utPromise = qid_getUserTalkPage(user.name);
			var utPageName = 'User talk:' + user.name;
			utPromise.done(function(result) {
				if (qid_getPageId(result) == '-1') {
					// no talk page
					console.log('No page exists at ' + utPageName + '; skipping...');
					return;
				}
				var warnPage = qid_testUserPage ? qid_testUserPage : utPageName;
				var utPage = qid_getPageInfo(result);
				var utContent = qid_getPageContent(utPage);
				if (utContent) {
					var line1 = utContent.split('\n')[0];
					if (utContent.toLowerCase().indexOf("#redirect") > -1) {
						var reBrackets = /\[\[([^\]]+)\]\]/;
						var match = line1.match(reBrackets);
						if (match !== null) {
							console.log('Found a redirect at ' + warnPage + ' to ' + match[1]);
							warnPage = match[1];
						}
					}
				}
	
				notifyFunc(warnPage, utContent);
			});
		}
	});
	promise.fail(function() { qid_setDialogMessage('Error when trying to get the uploader user info'); });
}

function qid_addTemplateToUserTalkPage(warnPage, warnWikiText, warnSummary) {
	warnWikiText = '\n' + warnWikiText + '\n';
	var warnData = {
		'action': 'edit',
		'format': 'json',
		'title': warnPage,
		'summary': warnSummary + ' (using [[User talk:Howcheng/quickimgdelete.js|quickimgdelete]])',
		'contentmodel': 'wikitext',
		'contentformat': 'text/x-wiki',
		'appendtext': warnWikiText,
		'token': qid_editToken
	};
	console.log('Attempting to add a user warning template to ' + warnPage);
	var warnPromise = $.ajax({
		type: "POST",
		url: mw.util.wikiScript('api'),
		data: warnData,
		dataType: 'json'
	});
	warnPromise.then(function(result) {
			qid_processEditSuccess(result, 'Warning template added to ' + warnPage);
		}, function(result) {
			qid_setDialogMessage('Error: Request failed when adding warning template to ' + warnPage);
		});
	return warnPromise;
}

function qid_getUserTalkPage(username) {
	var data = {
		'action': 'query',
		'prop': 'revisions',
		'rvprop': 'content',
		'rvslots': '*',
		'titles': qid_testUserPage ? qid_testUserPage : 'User talk:' + username
	};
	var promise = qid_makeApiCall("POST", null, data);
	promise.fail(function () { qid_setDialogMessage("An error occurred while attempting to get the user talk page for " + username); });
	return promise;
}

function qid_processEditSuccess(result, successMessage) {
	if (result && result.edit && result.edit.result == 'Success') {
		qid_setDialogMessage(successMessage);
	} else if (result && result.error) {
		qid_setDialogMessage('Error: API returned error code "' + result.error.code + '": ' + result.error.info);
	} else {
		qid_setDialogMessage('Error: Unknown result from API.')
	}
}

function qid_userBeenWarned(txt, template) {
	var re = eval("/\<!-- ?Template:" + template + " ?--\>/;");
	return re.test(txt);
}
function qid_removeNamespace(fullpagename) {
	var colonPos = fullpagename.indexOf(':');
	var pagename = fullpagename.substring(colonPos + 1);
	return pagename;
}
function qid_removeTemplate(editformval, template) {
	var re = eval('/\{\{' + template + '/gi');
	var templatepos = editformval.search(re);
	if (templatepos > -1) {
	var lastbracepos = editformval.indexOf('}}', templatepos) + 1;
		editformval = editformval.substr(0, templatepos) + editformval.substr(lastbracepos + 2);
	}
	return editformval;
}

/** ================================================================================
  * ==Automatic 'nominate for discussion' script==
  * The actions in this section do three things:
  * 1. Add a tag to the image page.
  * 2. List the image on a log page.
  * 3. Add a warning template to the uploader's talk page.
  */
// Configuration
nfd_text = "Nominate for discussion";
nfd_tooltip = "Nominate this image for discussion";
nfd_prompt = "Why do you want to nominate this image for discussion?";
nfd_delReq = "Wikipedia:Files for discussion/";
nfd_deleteTemplate = "ffd";
nfd_idwTemplate = "Fdw";
nfd_ifdTemplate = "Ffd2";
nfd_glossary = new Array(
  new Array("AB", "Absent uploader"),
  new Array("AU", "Absent uploader"),
  new Array("CV", "Copyright violation"),
  new Array("OB", "Obsolete"),
  new Array("OR", "Orphaned"),
  new Array("LQ", "Low quality"),
  new Array("UE", "Unencyclopedic")
);
 
function nfd_onload() {
  if (document.getElementById('ca-edit') == null) // not editable by non-admin
    return;
  if (mw.config.get('wgAction') == "view" && mw.config.get('wgCanonicalNamespace') == "File") {
    mw.util.addPortletLink('p-tb', 'javascript:nfd_tagImage(\'nfd\')', nfd_text, 'nom-for-del', nfd_tooltip);
  }
}

function nfd_tagImage(action) {
	qid_action = action;
	var promise = qid_getFileInfo();
	promise.done(nfd_getFileInfo_success);
}
function nfd_getFileInfo_success(result) {
	var template, warnTemplate, logTemplate;
	var templateParms, warnTemplateParms, logTemplateParms;
	var summary, warnSummary, logSummary;
	var logPage;
	var warnTemplateHasSig = false;
	var promptMsg;
	var page = qid_getPageInfo(result);
	var promises = [];
	
	// determine the listing page and the template to add to it, the template to add to the file and user pages, and the edit summaries
	switch (qid_action) {
		case 'nfd':
			promptMsg = nfd_prompt;
			template = nfd_deleteTemplate;
			summary = 'nomination for [[WP:FFD|discussion]]';
			warnTemplate = nfd_idwTemplate;
			warnTemplateHasSig = true;
			warnSummary = '[[:' + mw.config.get('wgPageName') + ']] nominated for discussion' ;
			logTemplate = nfd_ifdTemplate;
			logPage = nfd_delReq;
			break;
	}
	
	// get user input for discussion rationale
	var reason = window.prompt(promptMsg, '');
	if (!reason) {
		qid_setDialogMessage("No discussion rationale entered. Action cancelled.");
		return;
	}
	
	// build the template wikitext
	var now = new Date();
	var monthNames = [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ];
	var logDate = now.getUTCFullYear() + ' ' + monthNames[now.getUTCMonth()] + ' ' + now.getUTCDate();
	var templateWikiText = '{{' + template + '|log=' + logDate + '}}';
	
	// add template wikitext to page
	var templatePromise = qid_addTemplateToFilePage(page, templateWikiText, summary, [ 'untagged' ]);
	promises.push(templatePromise);
	
	// build the log template wikitext
	var logWikiText = '{{subst:' + logTemplate + '|1=' + mw.config.get('wgTitle');
	switch (qid_action) {
		case 'nfd':
			// expand abbreviations
			for (var i = 0; i < nfd_glossary.length; i++) {
				var abbrev = nfd_glossary[i][0];
				var meaning = nfd_glossary[i][1];
				var re = eval("/\\b" + abbrev + "\\b/");
				if (re.test(reason))
				 	reason = reason.replace(re, meaning);
			}
			// find original uploader
			var uploader = page.imageinfo[page.imageinfo.length - 1].user;
			logWikiText += '|Uploader=' + uploader + '|Reason=' + reason;
			break;
	}
	logWikiText += '}} ~~' + '~~';
	
	// add listing to log page
	logPage += logDate;
	logSummary = 'Adding [[:' + mw.config.get('wgPageName') + ']] (using [[User talk:Howcheng/quickimgdelete.js|quickimgdelete]])';
	var logData = {
		'action': 'edit',
		'format': 'json',
		'title': qid_testLogPage ? qid_testLogPage : logPage,
		'summary': logSummary,
		'contentmodel': 'wikitext',
		'contentformat': 'text/x-wiki',
		'appendtext': '\n' + logWikiText + '\n',
		'token': qid_editToken
	};
	var logPromise = $.ajax({
		type: "POST",
		url: mw.util.wikiScript('api'),
		data: logData,
		dataType: 'json'
	});
	console.log('Attempting to add an entry to ' + logPage);
	logPromise.then(function(result) {
			qid_processEditSuccess(result, 'Entry added to ' + logPage);
		}, function(result) {
			qid_setDialogMessage('Error: Request failed when adding to ' + logPage);
	});
	promises.push(logPromise);
	
	// warn the users
	qid_notifyUploadersWhoAreNotBots(page, function(warnPage) {
		var warnWikiText = '\n{{subst:' + warnTemplate;
		warnWikiText += '|1=' + mw.config.get('wgTitle') + '}}';
		if (!warnTemplateHasSig)
			warnWikiText += ' ~~' + '~~';
		warnWikiText += '\n';
		var warnPromise = qid_addTemplateToUserTalkPage(warnPage, warnWikiText, warnSummary);
		promises.push(warnPromise);
	});

	// wait for all ajax calls to finish
	$.when.apply($, promises).done(function() {
		if (!qid_templateAddError)
			qid_setDialogMessage('All done!')
	});
}

/** ================================================================================
  * ==Automatic 'mark no source' (mns) and 'mark no license' (mnl) script== // mnx = applies to all
  * The actions in this section do two things:
  * 1. Add a tag to the image page.
  * 2. Add a warning to the uploader's talk page.
  */
// Configuration
mcv_text = "Copyright violation";
mcv_tooltip = "Mark this image as a copyright violation";
mns_text = "No source";
mns_tooltip = "Mark this image as missing required source information";
mnl_text = "No license";
mnl_tooltip = "Mark this image as missing required licensing information";
mnsl_text = "No source/license";
mnsl_tooltip = "Mark this image as missing both required source and licensing information";
mnp_text = "No permission";
mnp_tooltip = "Mark this image as missing evidence of permission";
mnr_text = "No rationale";
mnr_tooltip = "Mark this image as missing non-free rationale";
mor_text = "Orphaned non-free";
mor_tooltip = "Mark this image as an orphaned non-free image";
mrfu_text = "Replaceable non-free";
mrfu_tooltip = "Mark this image as a replaceable non-free image";
mfud_text = "Non-free use disputed";
mfud_tooltip = "Mark this image as non-free use disputed";
mbsr_text = "Base URL";
mbsr_tooltip = "This image links directly to the image or is a generic base URL";

function mnx_markNo(action) {
	qid_action = action;
	var promise = qid_getFileInfo();
	promise.done(mnx_getFileInfo_success);
}
function mnx_getFileInfo_success(result) {
	var template, warnTemplate;
	var templateParms, warnTemplateParms;
	var warnNoNamespace, hasShortNotice;
	var fileSrc;
	var subst = true;
	var page = qid_getPageInfo(result);
	
	// determine the template to add to the file and user pages and the edit summaries
	switch (qid_action) {
		case 'mnx_mcv':
			template = 'db-g12';
			warnTemplate = "db-copyvio-notice";
			fileSrc = window.prompt('Please enter the source URL of the image:', '');
			if (fileSrc == null) {
				alert("Action cancelled");
				return;
			}
			if (fileSrc == '') {
				alert("Error: no source URL entered. Aborting.")
				return;
			}
			templateParms = 'header=1|url=' + fileSrc;
			summary = "Image is a copyright violation; see " + fileSrc;
			warnSummary = "Warning: copyright violation";
			break;
		case 'mnx_mns':
			template = 'nsd';
			warnTemplate = "Di-no source-notice";
			summary = "Image is missing source information and will be deleted in seven days if it is not added.";
			warnSummary = "Warning: image missing source information.";
			warnNoNamespace = true;
			break;
		case 'mnx_mnl':
			template = 'nld';
			warnTemplate = "Di-no license-notice";
			summary = "Image is missing license information and will be deleted in seven days if it is not added.";
			warnSummary = "Warning: image missing license information.";
			warnNoNamespace = true;
			break;
		case 'mnx_mnsl':
			template = 'nsdnld';
			warnTemplate = "Di-no source-notice";
			summary = "Image is missing source and license information and will be deleted in seven days if both are not added.";
			warnSummary = "Warning: image missing source and license information.";
			warnNoNamespace = true;
			break;
		case 'mnx_mnp':
			template = 'npd';
			summary = "Image is missing evidence of permission and will be deleted in seven days if it is not provided.";
			fileSrc = window.prompt('(Optional) Please enter the source of the image:', '');
			if (fileSrc)
				templateParms = 'source=' + fileSrc;
			warnTemplate = "Di-no permission-notice";
			warnSummary = "Warning: image missing evidence of permission.";
			warnNoNamespace = true;
			break;
		case 'mnx_mnr':
			template = 'nrd';
			summary = "Image is missing non-free usage rationale and will be deleted in seven days if it is not added.";
			warnTemplate = "Missing rationale";
			warnSummary = "Warning: image missing non-free usage rationale.";
			hasShortNotice = true;
			break;
		case 'mnx_mor':
			template = 'orfud';
			summary = "This non-free image is not used in any articles and will be deleted in seven days if it remains so.";
			warnTemplate = "Orphaned";
			warnSummary = "The non-free image you uploaded is now orphaned.";
			hasShortNotice = true;
			break;
		case 'mnx_mrfu':
			template = 'rfu';
			summary = "This non-free image appears to illustrate a subject for which a free one could reasonably be found or created and will be deleted in two days.";
			warnTemplate = "Replaceable";
			warnSummary = "The non-free image you uploaded is replaceable by a free one.";
			warnNoNamespace = true;
			hasShortNotice = true;
			break;
		case 'mnx_mfud':
			template = 'dfu';
			summary = "The usage of this non-free image is disputed.";
			var nonFreeDisputeReason = window.prompt('Please enter the reason why you are disputing the usage of this non-free image:', '');
			if (!nonFreeDisputeReason) {
				alert("No reason given. Action cancelled.");
				return;
			}
			templateParms = '1=' + nonFreeDisputeReason;
			warnTemplate = "No fair";
			warnSummary = "The use of a non-free image you uploaded is disputed.";
			hasShortNotice = true;
			break;
		case 'mnx_mbsr':
			template = 'bsr';
			summary = "The source URL given is inadequate.";
			subst = false;
			warnTemplate = "bsr-user";
			warnSummary = "Please provide a better source URL for your image.";
			break;
	}
	// build the template wikitext
	var templateWikiText = '{{'
	if (subst)
		templateWikiText += 'subst:';
	templateWikiText += template;
	if (templateParms)
		templateWikiText += '|' + templateParms;
	templateWikiText += '}}';
	
	var promises = [];
	// add template wikitext to page
	var templatePromise = qid_addTemplateToFilePage(page, templateWikiText, summary, [ 'untagged' ]);
	promises.push(templatePromise);
		
	// warn the users
	qid_notifyUploadersWhoAreNotBots(page, function(warnPage, utContent) {
		var useShortNotice = false;
		if (hasShortNotice && qid_userBeenWarned(utContent, warnTemplate)) {
			// yes, use short version of template
			warnTemplate += ' short';
		}
		var warnWikiText = '{{subst:' + warnTemplate;
		var filename = mw.config.get(warnNoNamespace ? 'wgTitle' : 'wgPageName');
		warnWikiText += '|1=' + filename + '}} ~~' + '~~';
		var warnPromise = qid_addTemplateToUserTalkPage(warnPage, warnWikiText, warnSummary);
		promises.push(warnPromise);
	});
	
	// wait for all ajax calls to finish
	$.when.apply($, promises).done(function() {
		if (!qid_templateAddError)
			qid_setDialogMessage('All done!')
	});
}

function mnx_onload() {
  if (document.getElementById('ca-edit') == null) // not editable by non-admin
    return;
  if (mw.config.get('wgAction') == "view" && mw.config.get('wgCanonicalNamespace') == "File") {
    mw.util.addPortletLink('p-tb', 'javascript:mnx_markNo(\'mnx_mcv\')', mcv_text, 'mark-copyvio', mcv_tooltip);
    mw.util.addPortletLink('p-tb', 'javascript:mnx_markNo(\'mnx_mns\')', mns_text, 'mark-no-source', mns_tooltip);
    mw.util.addPortletLink('p-tb', 'javascript:mnx_markNo(\'mnx_mnl\')', mnl_text, 'mark-no-license', mnl_tooltip);
    mw.util.addPortletLink('p-tb', 'javascript:mnx_markNo(\'mnx_mnsl\')', mnsl_text, 'mark-no-source-license', mnsl_tooltip);
    mw.util.addPortletLink('p-tb', 'javascript:mnx_markNo(\'mnx_mnp\')', mnp_text, 'mark-no-permission', mnp_tooltip);
    mw.util.addPortletLink('p-tb', 'javascript:mnx_markNo(\'mnx_mnr\')', mnr_text, 'mark-no-rationale', mnr_tooltip);
    mw.util.addPortletLink('p-tb', 'javascript:mnx_markNo(\'mnx_mor\')', mor_text, 'mark-orphaned', mor_tooltip);
    mw.util.addPortletLink('p-tb', 'javascript:mnx_markNo(\'mnx_mrfu\')', mrfu_text, 'mark-replaceable', mrfu_tooltip);
    mw.util.addPortletLink('p-tb', 'javascript:mnx_markNo(\'mnx_mfud\')', mfud_text, 'mark-disputed', mfud_tooltip);
    mw.util.addPortletLink('p-tb', 'javascript:mnx_markNo(\'mnx_mbsr\')', mbsr_text, 'mark-base-url', mbsr_tooltip);
  }
}

/** ================================================================================
  * ==Automatic speedy tagging==
  * The actions in this section do one thing:
  * 1. Add a tag to the image page.
  */
// Configuration
mred_text = "Mark as redundant image";
mred_tooltip = "Mark this image as redundant (tag for speedy deletion)";
mmi_text = "Mark as missing image";
mmi_tooltip = "Mark as missing image (tag for speedy deletion)";
mmtc_text = "Mark as Move to Commons";
mmtc_tooltip = "Mark as candidate to move to Commons";
mncd_text = "Mark as Commons duplicate";
mncd_tooltip = "Mark as Commons duplicate";

function speedyi_onload() {
  if (document.getElementById('ca-edit') == null) // not editable by non-admin
    return;
  if (mw.config.get('wgAction') == "view" && mw.config.get('wgCanonicalNamespace') == "File") {
    mw.util.addPortletLink('p-tb', 'javascript:speedyi_mark(\'speedyi_mred\')', mred_text, 'mark-redundant', mred_tooltip);
    mw.util.addPortletLink('p-tb', 'javascript:speedyi_mark(\'speedyi_mmi\')', mmi_text, 'mark-missing', mmi_tooltip);
    mw.util.addPortletLink('p-tb', 'javascript:speedyi_mark(\'speedyi_mmtc\')', mmtc_text, 'mark-movecommons', mmtc_tooltip);
    mw.util.addPortletLink('p-tb', 'javascript:speedyi_mark(\'speedyi_mncd\')', mncd_text, 'mark-commons', mncd_tooltip);
  }
}

function speedyi_mark(action) {
	qid_action = action;
	var promise = qid_getFileInfo();
	promise.done(speedyi_getFileInfo_success);
}
function speedyi_getFileInfo_success(result) {
	var template;
	var templateParms;
	var summary;
	var subst = false;
	var page = qid_getPageInfo(result);
	var templatesToRemove = [ 'untagged' ];
	switch (qid_action) {
		case "speedyi_mred":
			template = 'db-f1';
			var dupe = window.prompt('Please enter the name of the image this one is redundant to.', '');
			if (!dupe) {
				qid_setDialogMessage('No image name entered. Action cancelled.');
				return;
			}
			dupe = qid_removeNamespace(dupe);
			summary = 'Tagging for [[WP:CSD#F1|speedy deletion]]: Image is redundant to [[:Image:' + dupe + ']].';
			templateParms = '|1=' + dupe;
			break;
		case 'speedyi_mmi':
			template = 'db-f2';
			summary = 'Tagging for [[WP:CSD#F2|speedy deletion]]: Image is missing or corrupt.';
			break;
		case 'speedyi_mmtc':
			template = 'Copy to Wikimedia Commons';
			summary = 'Image is a candidate for moving to [[Commons:Main Page|Wikimedia Commons]].';
			templateParms = '|human=' + mw.config.get('wgUserName');
			break;
		case 'speedyi_mncd':
			template = 'Now commons dated';
			var commonsimg = window.prompt('Please enter the name of the corresponding image on Commons (leave empty if the same name).', '');
			if (commonsimg == null) {
				qid_setDialogMessage('Action cancelled.');
				return;
			}
			if (commonsimg == '') {
				// file not specified, use the same name
				commonsimg = mw.config.get('wgPageName');
			} else {
				templateParms = '|1=' + commonsimg;
			}
			summary = 'Image is duplicate of [[Commons:Main Page|Commons]] image [[Commons:' + commonsimg + '|]].';
			subst = true;
			// remove {{Move to Commons}} template (and its various redirects) and other now-moot maintenance templates
			templatesToRemove = [ 'untagged', 'CTWC', 'CWC', 'Commons ok', 'Copy to Commons', 'Copy to commons', 'Copy to wikimedia commons', 'CopyToCommons', 'Do move to Commons', 'MITC', 'MTC', 'Move to Commons', 'Move to Wikimedia Commons', 'Move to commons', 'Move-to-commons', 'MoveToCommons', 'To commons', 'ToCommons', 'Upload to commons', 'Rename media', 'Ifr', 'Image move', 'Media rename', 'Nondescript', 'Rename image', 'Rename-image' ];
			break;
	}
	var templateWikiText = '{{';
	if (subst)
		templateWikiText += 'subst:';
	templateWikiText += template;
	if (templateParms)
		templateWikiText += '|' + templateParms;
	templateWikiText += '}}';

	// add template to file description page
	var promise = qid_addTemplateToFilePage(page, templateWikiText, summary, templatesToRemove);
	promise.then(function() {
		if (!qid_templateAddError)
			qid_setDialogMessage('All done!')
	});
}

$(document).ready(function() {
	nfd_onload();
	mnx_onload();
	speedyi_onload();
});
/* </nowiki></pre> */