User:Holly Cheng/dev quickimgdelete.js

/* */ /* quickimgdelete.js * Current version: 2.4.1 * ======================================= * Created by 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 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 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("/\/;"); 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 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 = ''; // add template wikitext to page var templatePromise = qid_addTemplateToFilePage(page, templateWikiText, summary, [ 'untagged' ]); promises.push(templatePromise); // build the log template wikitext var logWikiText = '' + 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 += ' ' + ''; // add listing to log page logPage += logDate; logSummary = 'Adding ' + mw.config.get('wgPageName') + ' (using 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' + 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 = '''; 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 =  + 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 speedy deletion: Image is redundant to Image:' + dupe + '.'; templateParms = '|1=' + dupe; break; case 'speedyi_mmi': template = 'db-f2'; summary = 'Tagging for speedy deletion: Image is missing or corrupt.'; break; case 'speedyi_mmtc': template = 'Copy to Wikimedia Commons'; summary = 'Image is a candidate for moving to 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 image ' + commonsimg + '.'; subst = true; // remove 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 = '';

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