User:This, that and the other/masstag.js

// This, that and the other's mass tagging script // July 2011

// To make it work, use a JavaScript console to call masstag or massremove // Script depends on the following lines having been included in skin.js previously: // importStylesheet("MediaWiki:Gadget-morebits.css"); // importScript("MediaWiki:Gadget-morebits.js");

function masstag { if (mw.config.get("wgUserName") !== "TTObot") { alert("The masstag script may only be run under the User:TTObot account. If you wish to use this script to perform mass tagging tasks, please contact User:This, that and the other."); return; }	mw.loader.using(['jquery.ui'], function {		var dialog = new Morebits.simpleWindow(500, 400);		dialog.setTitle("Mass tagging");		var form = new Morebits.quickForm(masstag.callback.initialTag);		form.append({ type: 'div', label: [ Morebits.htmlNode("strong", "Notice: BAG approval applies to mass XfD tagging operations only.", "red") ]});		form.append({ type: 'textarea', name: 'list', label: 'List of pages (one per line)' });		form.append({ type: 'input', name: 'tag', label: 'Text to prepend: ', size: 60 });		form.append({ type: 'input', name: 'summary', label: 'Edit summary: ', size: 60 });		form.append({ type: 'checkbox', list: [ { name: 'skipMissing', label: 'Skip non-existent pages', checked: true }, { name: 'skipCsd', label: 'Skip speedy deletion candidates', checked: true }, { name: 'skipEdited', label: 'Skip pages with more than one revision' }, { name: 'skipBig', label: 'Skip pages bigger than the size threshold below' } ]});		form.append({ type: 'input', name: 'bigThreshold', label: 'Size threshold (bytes): ', size: 5 });		form.append({ type: 'submit' });		dialog.setContent(form.render);		dialog.display; 	}); }

function massremove { if (mw.config.get("wgUserName") !== "TTObot") { alert("The masstag script may only be run under the User:TTObot account. If you wish to use this script to perform mass tagging tasks, please contact User:This, that and the other."); return; }	mw.loader.using(['jquery.ui'], function {		var dialog = new Morebits.simpleWindow(500, 400);		dialog.setTitle("Mass tag removal");		var form = new Morebits.quickForm(masstag.callback.initialRemove);		form.append({ type: 'div', label: [ Morebits.htmlNode("strong", "Notice: BAG approval applies to mass removal of XfD tags only.", "red") ]});		form.append({ type: 'textarea', name: 'list', label: 'List of pages (one per line)' });		form.append({ type: 'input', name: 'regex', label: 'Regex to remove (case insens.): ', size: 60 });		form.append({ type: 'div', label: "^?\\s*\\{\\{tfd[^\\}]*\\}\\}\\s*?\\s*" });		form.append({ type: 'input', name: 'summary', label: 'Edit summary: ', size: 60 });		form.append({ type: 'checkbox', list: [ { name: 'skipCsd', label: 'Skip speedy deletion candidates', checked: true } ]});		form.append({ type: 'submit' });		dialog.setContent(form.render);		dialog.display; 	}); }

masstag.callback = {};

masstag.callback.initialTag = function(e) { var form = e.target; if (!form.tag.value || !form.summary.value) { alert("Tag text and edit summary are compulsory"); return; }	var params = { massremove: false, tag: form.tag.value, list: form.list.value.trimRight.split("\n"), summary: form.summary.value, skipMissing: form.skipMissing.checked, skipCsd: form.skipCsd.checked, skipEdited: form.skipEdited.checked, skipBig: form.skipBig.checked, bigThreshold: parseInt(form.bigThreshold.value, 10), resultPages: [], resultInitialContributors: [], form: form };	Morebits.simpleWindow.setButtonsEnabled(false); form.textContent = ""; var div = document.createElement("div"); div.style.height = "8em"; div.style.overflow = "auto"; div.style.padding = "4px"; div.style.border = "1px black solid"; div.style.background = "white"; form.appendChild(div); Morebits.status.init(div); masstag.callback.beginTag(params); };

masstag.callback.initialRemove = function(e) { var form = e.target; if (!form.regex.value || !form.summary.value) { alert("Removal regex and edit summary are compulsory"); return; }	var params = { massremove: true, regex: form.regex.value, list: form.list.value.trimRight.split("\n"), summary: form.summary.value, skipMissing: true, skipCsd: form.skipCsd.checked, skipEdited: false, skipBig: false, resultPages: [], resultInitialContributors: [], form: form };	Morebits.simpleWindow.setButtonsEnabled(false); form.textContent = ""; var div = document.createElement("div"); div.style.height = "8em"; div.style.overflow = "auto"; div.style.padding = "4px"; div.style.border = "1px black solid"; div.style.background = "white"; form.appendChild(div); Morebits.status.init(div); masstag.callback.beginTag(params); };

masstag.callback.beginTag = function(params) { if (params.list.length === 0) { masstag.callback.finishUp(params); return; }	var query = { action: 'query', prop: 'info|revisions', rvprop: 'user|timestamp|flags|content', titles: params.list[0] };	var api = new Morebits.wiki.api("Fetching page data", query, masstag.callback.processTag, new Status("Loading " + params.list[0])); api.params = params; window.setTimeout(function { api.post; }, 6000); // throttling to prevent overly frequent editing };

masstag.callback.processTag = function(apiobj) { var params = apiobj.params; var $xml = $(apiobj.responseXML); var $page = $xml.find("page"); if ($page.attr("missing") === "" && params.skipMissing) { params.resultPages.push({ title: params.list[0], result: "Page does not exist", red: true }); } else { if ($page.attr("redirect") === "") { params.resultPages.push({ title: params.list[0], result: "Page is a redirect", red: true }); } else { if ($xml.find("rev").text.indexOf("{{db") !== -1 && params.skipCsd) { params.resultPages.push({ title: params.list[0], result: "Page may be a speedy deletion candidate", red: true }); } else { if ($page.attr("new") !== "" && params.skipEdited) { params.resultPages.push({ title: params.list[0], result: "Page has more than one revision", red: true }); } else { if (params.skipBig && $page.attr("length") > params.bigThreshold) { params.resultPages.push({ title: params.list[0], result: "Page is too long (" + $page.attr("length") + " bytes)", red: true }); } else { // do it						var page = new Morebits.wiki.page(params.list[0]); var editsuccess = function(apiresult) { page.getStatusElement.info("Done"); params.resultPages.push({ title: params.oldtitle, result: "Success" }); masstag.callback.beginTag(params); };						var editerror = function(apiresult) { page.getStatusElement.error(apiresult.errorText); params.resultPages.push({ title: params.oldtitle, result: "API error (" + apiresult.errorText + ")", red: true }); masstag.callback.beginTag(params); };						if (params.massremove) { page.load(function(pageresult) {								var text = pageresult.getPageText;								var newText = text.replace(new RegExp(params.regex, "i"), "");								if (text === newText) {									page.getStatusElement.warn("Regex did not match");									params.resultPages.push({ title: params.list[0], result: "Regex did not match; page skipped" });									params.list = params.list.slice(1);									masstag.callback.beginTag(params);									return;								}								page.setPageText(newText);								page.setEditSummary(params.summary);								page.setCreateOption("nocreate");								params.oldtitle = params.list[0];								params.list = params.list.slice(1);								page.save(editsuccess, editerror);							}); } else { page.setPrependText(params.tag); page.setEditSummary(params.summary); page.setCreateOption(params.skipMissing ? "nocreate" : "recreate"); params.oldtitle = params.list[0]; params.list = params.list.slice(1); page.prepend(editsuccess, editerror); if ($page.attr("missing") !== "") { page.lookupCreator(function(pageobj) {									if (params.resultInitialContributors.indexOf(pageobj.getCreator) === -1) {										params.resultInitialContributors.push(pageobj.getCreator);									}								}); }						}						return; }				}			}		}	}	params.list = params.list.slice(1); masstag.callback.beginTag(apiobj.params); };

masstag.callback.finishUp = function(params) { var success = [], failed = []; params.form.appendChild(Morebits.htmlNode("h3", "1. Results")); $.each(params.resultPages, function(k, v) {		var div = Morebits.htmlNode("div", "", v.red ? "red" : null);		var a = Morebits.htmlNode("a", v.title);		a.href = "/wiki/" + v.title;		div.appendChild(a);		div.appendChild(document.createTextNode(": " + v.result));		params.form.appendChild(div);		(v.red ? failed : success).push(v.title);	}); if (!params.massremove) { params.form.appendChild(Morebits.htmlNode("h3", "2. Initial contributors")); $.each(params.resultInitialContributors, function(k, v) {			params.form.appendChild(Morebits.htmlNode("div", v));		}); }	params.form.appendChild(Morebits.htmlNode("h3", (params.massremove ? "2" : "3") + "a. Summary: successful pages (" + success.length + " total)")); $.each(success, function(k, v) {		params.form.appendChild(Morebits.htmlNode("div", v));	}); params.form.appendChild(Morebits.htmlNode("h3", (params.massremove ? "2" : "3") + "b. Summary: failed pages (" + failed.length + " total)")); $.each(failed, function(k, v) {		params.form.appendChild(Morebits.htmlNode("div", v));	}); };