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.

/* <nowiki>

 * Some of this code comes from RMCDbot and the UI is based on Evad37's XFDcloser

 */

var $box;

var form, interfaceWindow;

var moves = [];

var badMoves = [];

var overwritePages = [];

var associatedPagesChecked = 0;

var basePages = 0;

$.when(

	window.Morebits || mw.loader.getScript('https://en.wikipedia.org/?title=MediaWiki:Gadget-morebits.js&action=raw&ctype=text/javascript'),

	$.ready,

	importStylesheet( 'MediaWiki:Gadget-morebits.css' )

).then(function(){

	

	//var form, interfaceWindow;

	var moveGroups = {};

	var loaded = false;

	var noSubpageNamespaces = 0, 6, 8, 14, 446];

	/*var moves = [];

	var badMoves = [];

	var overwritePages = [];

	var associatedPagesChecked = 0;

	var basePages = 0;*/

	var defaultConfig = {

		relistSummary: "Relisted requested move using [[User:Danski454/RMcloser|RMcloser]]",

		loadDiff: true,

		outcomes: {

			"moved": {

				wikitext:"'''moved''' ",

				summary: "Closed requested move as moved using [[User:Danski454/RMcloser|RMcloser]]"

			},

			"not moved": {

				wikitext:"'''not moved''' ",

				summary: "Closed requested move as not moved using [[User:Danski454/RMcloser|RMcloser]]"

			},

			"no consensus": {

				wikitext:"'''no consensus''' ",

				summary: "Closed requested move as no consensus using [[User:Danski454/RMcloser|RMcloser]]"

			},

			"withdrawn": {

				wikitext:"'''withdrawn''' ",

				summary: "Closed requested move as withdrawn using [[User:Danski454/RMcloser|RMcloser]]"

			}

		},

		customOutcomeSummary: "Closed requested move using [[User:Danski454/RMcloser|RMcloser]]",

		customSuffix: null,

		overwriteMode: "auto" //off, swap, delete

	};

	

	function makeLink(target, text=null){

		console.log('makeLink');

		if (!text) {

			text = target;

		}

		return '<a href="/wiki/' + target.replace(/ /g, '_') + '">' + text + '</a>';

	}

	

	function display(){

		console.log('display');

		if (moves.length === 0) {

			//no moves

			form.append({

				type: 'div',

				label: 'Unable to get pages'

			});

		} else if (badMoves.indexOf(':*') !== -1) {

			//something has gone wrong

			form.append({

				type: 'div',

				label: 'Unable to validate moves'

			});

		} else {

			var baseGroups = [];

			for (var i = 0; i < moves.length; i++) {

				if (moveGroupsmovesi][2]]) {

					moveGroupsmovesi][2]].moves.push(movesi]);

					if (overwritePages.indexOf(movesi][1]) !== -1) {

						//we are overwriting a redirect

						moveGroupsmovesi][2]].overwrite = true;

					}

				} else {

					moveGroupsmovesi][2]] = {

						moves: movesi]],

						overwrite: overwritePages.indexOf(movesi][1]) !== -1,

						bad: badMoves.indexOf(movesi][2]) !== -1

					};

					if (/^(:\/|t\/|t:)/.test(movesi][2])) {

						var parent = movesi][2].slice(2);

						moveGroupsmovesi][2]].parent = parent;

						if (!moveGroupsparent]) {

							moveGroupsparent = {

								moves: [],

								overwrite: overwritePages.indexOf(parent) !== -1,

								bad: badMoves.indexOf(parent) !== -1,

								children: movesi][2]]

							};

							baseGroups.push(parent);

						} else {

							moveGroupsparent].children.push(movesi][2]);

						}

					} else {

						baseGroups.push(movesi][2]);

						moveGroupsmovesi][2]].children = [];

					}

				}

			}

			var movefield = form.append({

				type: 'field',

				label: 'Moves'

			});

			var moveList = [];

			for (var j = 0; j < baseGroups.length; j++) {

				var source = moveGroupsbaseGroupsj]].moves0][0];

				var target = moveGroupsbaseGroupsj]].moves0][1];

				var flag = '';

				if (moveGroupsbaseGroupsj]].bad) {

					flag = ' [cannot move]';

				} else if (moveGroupsbaseGroupsj]].overwrite) {

					if ((getConfig('overwriteMode') === 'delete' ||

						getConfig('overwriteMode') === 'auto') &&

						Morebits.userIsInGroup("sysop")) {

						flag = ' [will delete target]';

					} else {

						flag = ' [swap]';

					}

				}

				moveList.push({

					name: 'moves-' + baseGroupsj],

					label: source + ' → ' + target + flag,

					checked: !moveGroupsbaseGroupsj]].bad,

					disabled: moveGroupsbaseGroupsj]].bad

				});

				if (moveGroupsbaseGroupsj]].children.length) {

					moveListmoveList.length-1].subgroup = {

						type: 'checkbox',

						list: []

					};

					for (var k = 0; k < moveGroupsbaseGroupsj]].children.length; k++) {

						var cflag = '';

						if (moveGroupsmoveGroupsbaseGroupsj]].childrenk]].bad) {

							cflag = ' [cannot move]';

						} else if (moveGroupsmoveGroupsbaseGroupsj]].childrenk]].overwrite) {

							if ((getConfig('overwriteMode') === 'delete' ||

								getConfig('overwriteMode') === 'auto') &&

								Morebits.userIsInGroup("sysop")) {

								cflag = ' [will delete target]';

							} else {

								cflag = ' [swap]';

							}

						}

						if (moveGroupsbaseGroupsj]].childrenk].charAt(1) === '/') {

							//subpages

							var pages = moveGroupsmoveGroupsbaseGroupsj]].childrenk]].moves.length.toString();

							if (moveGroupsbaseGroupsj]].childrenk].charAt(0) === 't') {

								pages = pages + ' talk';

							}

							var subpageMoves = [];

							for (var l = 0; l < moveGroupsmoveGroupsbaseGroupsj]].childrenk]].moves.length; l++) {

								var move = moveGroupsmoveGroupsbaseGroupsj]].childrenk]].movesl];

								subpageMoves.push(move0 + ' → ' + move1]);

							}

							subpageMoves = subpageMoves.join('\n');

							moveListmoveList.length-1].subgroup.list.push({

								name: 'moves-' + moveGroupsbaseGroupsj]].childrenk],

								label: pages + ' subpage(s)' + cflag,

								checked: !moveGroupsmoveGroupsbaseGroupsj]].childrenk]].bad,

								disabled: moveGroupsmoveGroupsbaseGroupsj]].childrenk]].bad,

								subgroup: {

									type: 'div',

									label: subpageMoves

								}

							});

						} else {

							//talk

							var talk = moveGroups't:' + baseGroupsj]].moves0][0];

							var talkTarget = moveGroups't:' + baseGroupsj]].moves0][1];

							moveListmoveList.length-1].subgroup.list.push({

								name: 'moves-t:' + baseGroupsj],

								label: talk + ' → ' + talkTarget + cflag,

								checked: !moveGroups't:' + baseGroupsj]].bad,

								disabled: moveGroups't:' + baseGroupsj]].bad

							});

						}

					}

				}

			}

			movefield.append({

				type: 'checkbox',

				name: 'moves',

				list: moveList

			});

		}

		form.append({

			type: 'submit',

			label: 'Close Discussion'

		});

		var result = form.render();

		interfaceWindow.setContent(result);

		interfaceWindow.display();

	}

	

	function getValidMoves(){

		console.log('getValidMoves');

		var sysop = Morebits.userIsInGroup("sysop");

		var te = sysop || Morebits.userIsInGroup("templateeditor");

		var extconfirmed = sysop || Morebits.userIsInGroup("extendedconfirmed");

		var overwrite = (sysop || Morebits.userIsInGroup("extendedmover")) &&

			getConfig("overwriteMode") !== "off";

		checkTitles(moves, true, extconfirmed, sysop, te, overwrite, display);

	}

	

	function getBaseMove(title, index = 0){

		console.log('getBaseMove');

		var f = moves.filter(function(t){return tindex === title;});

		if (f.length > 0) {

			return f0][2];

		}

		return null;

	}

	

	function startClose(e){

		console.log('startClose');

	}

	

	function closeDiscussion(outcome, comment){

		console.log('closeDiscussion');

		var outcomes = getConfig("outcomes");

		var suffix = getConfig("customSuffix");

		var top, summary;

		var bottom = "{{subst:RMbottom}}";

		if (suffix === null) {

			if (mw.config.get("wgUserGroups").indexOf("sysop") !== -1) {

				suffix = "";//sysops don't need a suffix

			} else if (mw.config.get("wgUserGroups").indexOf("extendedmover") !== -1) {

				suffix = " {{subst:RMpmc}}";

			} else {

				suffix = " {{subst:RMnac}}";

			}

		}

		if (outcomesoutcome]) {

			top = "{{subst:RMtop|" + outcomesoutcome].wikitext + comment

				+ suffix + "}}";

			summary = outcomesoutcome].summary;

		} else {

			top = "{{subst:RMtop|" + comment + suffix + "}}";

			summary = getConfig("customOutcomeSummary");

		}

		var re = /((=+)[^\n]+\2\s*\n(?:[^\n]|\n[^=])*\n?)\{\{\s?(?:requested move\/dated?|movereq)\s?\}\}\s*((?:[^=]|[^\n=]=|\2=+)+)/i;

		$.ajax({

			url: mw.config.get("wgServer") + mw.config.get("wgScriptPath") + 

			"/api.php?action=query&format=json&prop=revisions&titles=" + 

			mw.config.get("wgPageName") + "&rvprop=ids%7Ccontent&rvslots=main",

			dataType: "json",

			success: function(data){

				for (var page in data.query.pages) {

					var text = data.query.pagespage].revisions0].slots.main"*"];

					text = text.replace(re, "$1" + top + "$3\n" + bottom + "\n");

					$.ajax({

						url: mw.util.wikiScript('api'),

						type: 'POST',

						dataType: 'json',

						data: {

							format: 'json',

							action: 'edit',

							title: mw.config.get('wgPageName'),

							text: text, 

							summary: summary,

							token: mw.user.tokens.get('editToken')

						}

					})

					.done(function(data){

						if (data && data. && data..result && data..result == 'Success') {

							if (getConfig("loadDiff")) {

								if (data..oldrevid !== null && data..newrevid !== undefined){

									window.location.href = mw.config.get('wgScript') + '?diff=' + data..newrevid + '&oldid=' + data..oldrevid;//load diff

								} else {

									alert("Unable to load diff");

								}

							}

						} else {

							alert('Edit failed');

						}

					})

					.fail(function(){

						alert('Edit failed');

					});

				}

			},

			error: function(){

				alert('Edit failed');

			}

		});

	}

	

	function confirmRelist(){

		console.log('confirmRelist');

		if (confirm("Press OK to relist")) {

			relist();

		}

	}

	

	function getConfig(option){

		console.log('getConfig');

		if (typeof(window.RMcloserConfig) === "object" && window.RMcloserConfig

			&& window.RMcloserConfigoption !== undefined) {

			if (defaultConfigoption === undefined) {

				// if user did not set an option, error would occur

				console.warn("Config option '" + option + "' has no default setting.");

			}

			return window.RMcloserConfigoption];

		} else if (defaultConfigoption !== undefined) {

			return defaultConfigoption];

		} else {

			throw Error("Config option '" + option + "' has no default setting and has not been set by the user.");

		}

	}

	

	function relist(){

		console.log('relist');

		$("#RMcloser-relist-button").off("click");

		$.ajax({

			url: mw.config.get("wgServer") + mw.config.get("wgScriptPath") + 

			"/api.php?action=query&format=json&prop=revisions&titles=" + 

			mw.config.get("wgPageName") + "&rvprop=ids%7Ccontent&rvslots=main",

			dataType: "json",

			success: function(data){

				for (var page in data.query.pages) {

					var text = data.query.pagespage].revisions0].slots.main"*"];

					//regex based on RMCD bot's source code

					var re = /\{\{\s?(requested[_ ]move\/dated?|movereq)\s?\}\}.*?([0-2]\d):([0-5]\d),\s(\d{1,2})\s(\w*)\s(\d{4})\s\([A-Z]{3}\)[^\n\r]*/is;

					text = text.replace(re, "$&{{subst:relisting}}");

					$.ajax({

						url: mw.util.wikiScript('api'),

						type: 'POST',

						dataType: 'json',

						data: {

							format: 'json',

							action: 'edit',

							title: mw.config.get('wgPageName'),

							text: text, 

							summary: getConfig("relistSummary"),

							token: mw.user.tokens.get('editToken')

						}

					})

					.done(function(data){

						if (data && data. && data..result && data..result == 'Success') {

							if (getConfig("loadDiff")) {

								if (data..oldrevid !== null && data..newrevid !== undefined){

									window.location.href = mw.config.get('wgScript') + '?diff=' + data..newrevid + '&oldid=' + data..oldrevid;//load diff

								} else {

									alert("Unable to load diff");

								}

							}

						} else {

							alert('Edit failed');

						}

					})

					.fail(function(){

						alert('Edit failed');

					});

				}

			},

			error: function(){

				alert('Edit failed');

			}

		});

	}

	

	function getAssociatedPages(title, target){

		console.log('getAssociatedPages');

		var titleObj = new mw.Title(title);

		var ns = titleObj.getNamespaceId();

		var pageName = titleObj.getMainText();

		if (ns < 0) {

			associatedPagesChecked += 2;

			if (associatedPagesChecked >= 0) { getValidMoves(); }

			return;

		}

		if (noSubpageNamespaces.indexOf(ns) === -1) {

			$.ajax({

				url: mw.config.get("wgServer") + mw.config.get("wgScriptPath") + 

				"/api.php?action=query&format=json&list=allpages&requestid=" + 

				encodeURIComponent(title) + "%7C" + encodeURIComponent(target) + 

				"&apprefix=" + encodeURIComponent(pageName) + "%2F&apnamespace=" + 

				ns.toString() + "&aplimit=101",

				dataType: "json",

				success: function(data){

					if (data.query.allpages.length > 100) {

						//too many subpages

						associatedPagesChecked++;

						if (associatedPagesChecked >= 0) { getValidMoves(); }

						return;

					}

					var base, target = data.requestid.split("|");

					for (var i = 0; i < data.query.allpages.length; i++) {

						moves.push([data.query.allpagesi].title, 

						data.query.allpagesi].title.replace(base, target), ":/" + base]);

					}

					associatedPagesChecked++;

					if (associatedPagesChecked >= 0) { getValidMoves(); }

				}

			});

		} else associatedPagesChecked++;

		if (ns % 2 === 0) {

			var titleTalk = titleObj.getTalkPage().getPrefixedText();

			var targetTalk = new mw.Title(target).getTalkPage().getPrefixedText();

			$.ajax({

				url: mw.config.get("wgServer") + mw.config.get("wgScriptPath") + 

				"/api.php?action=query&format=json&list=allpages&requestid=" + 

				encodeURIComponent(titleTalk) + "%7C" + encodeURIComponent(targetTalk) + 

				"%7C" + encodeURIComponent(title) + "&prop=info&titles=" +

				encodeURIComponent(titleTalk) +

				"&apprefix=" + encodeURIComponent(pageName) + "%2F&apnamespace=" + 

				(ns+1).toString() + "&aplimit=101",

				dataType: "json",

				success: function(data){

					if (data.query.allpages.length > 100) {

						//too many subpages

						associatedPagesChecked++;

						if (associatedPagesChecked >= 0) { getValidMoves(); }

						return;

					}

					var base, target, subject = data.requestid.split("|");

					for (var i = 0; i < data.query.allpages.length; i++) {

						moves.push([data.query.allpagesi].title, 

						data.query.allpagesi].title.replace(base, target), "t/" + subject]);

					}

					for (var id in data.query.pages) {

						if (id !== "-1") {

							//talk page itself exists

							moves.push([base, target, "t:" + subject]);

						}

					}

					associatedPagesChecked++;

					if (associatedPagesChecked >= 0) { getValidMoves(); }

				}

			});

		} else associatedPagesChecked++;

		if (associatedPagesChecked >= 0) { getValidMoves(); }

	}

	

	function generateButtons(){

		console.log('generateButtons');

		if (loaded) return;

		loaded = true;

		$("#RMcloser-close-button").after('loading').remove();

		interfaceWindow = new Morebits.simpleWindow(

			Math.min(900, Math.floor(window.innerWidth*0.8)),

			Math.floor(window.innerHeight*0.9)

		);

		interfaceWindow.setTitle( 'RMcloser' );

		interfaceWindow.addFooterLink('script documentation', 'User:Danski454/RMcloser');

		form = new Morebits.quickForm(startClose);

		var closurefield = form.append({

			type: 'field',

			label: 'Closure'

		});

		var outcomes = getConfig('outcomes');

		var outcomesList = [{value:'', label:'other', selected: true}];

		for (var o in outcomes) {

			outcomesList.push({value:o, label:o});

		}

		closurefield.append({

			type: 'select',

			label: 'Outcome',

			name: 'type',

			list: outcomesList

		});

		closurefield.append({

			type: 'textarea',

			name: 'comment',

			label: 'Additional comments',

			rows: 2,

			cols: 50

		});

		if($box.next().is("p")){

			//single item

			var match = $box.next().text().match(/(.+) → (.+) –/);

			if (match) {

				associatedPagesChecked = -2;//count up to zero, one for talk, one for subject

				moves.push([match1], match2], match1]]);

				getAssociatedPages(match1], match2])

			} else {

				display();

			}

		} else if ($box.next().is("ul")){

			associatedPagesChecked = $box.next().children().length * -2;

			$box.next().children().each(function(){

				var match = $(this).text().match(/(.+) → (.+)/);

				if (match) {

					moves.push([match1], match2], match1]]);

					getAssociatedPages(match1], match2])

				} else {

					associatedPagesChecked += 2;

					if (associatedPagesChecked >= 0) { getValidMoves(); }

				}

			});

		} else {

			display();

		}

	}

	

	function start(){

		console.log('start');

		mw.loader.load( '//en.wikipedia.org/?title=User:Danski454/RMcloser.css&action=raw&ctype=text/css', 'text/css' );

		if (mw.config.get("wgNamespaceNumber") % 2 === 0) {

			return;//we are not on a talk page

		}

		var boxes = 0;

		$(".tmbox-move").each(function(index){

			var $this = $(this);

			var $b = $this.find("td.mbox-text b");

			if($b.text().match(/^It has been proposed in this section that /)) {

				boxes++;

				$box = $this;

			}

		});

		if (boxes !== 1) {

			//we do not have exactly one RM, exiting

			return;

		}

		if (mw.config.get("wgUserGroups").indexOf("autoconfirmed") === -1 && 

			mw.config.get("wgUserGroups").indexOf("confirmed") === -1 && 

			mw.config.get("wgUserGroups").indexOf("sysop") === -1) {

			//must be autoconfirmed

			console.warn("You must be autoconfirmed to use RMcloser");

			return;

		}

		//add button

		$box.find(".mbox-text").children(":last").children().append(' • <a href="#=!=" class="external text" role="button" id="RMcloser-close-button">close</a> • <a href="#=!=" class="external text" role="button" id="RMcloser-relist-button">relist</a>');

		$("#RMcloser-close-button").click(generateButtons);

		$("#RMcloser-relist-button").click(confirmRelist);

	}

	

	function checkTitles(titlepairs, tboverride, extconfirmed, sysop, te, overwrite, next){

		console.log('checkTitles');

		var titles = [];

		var sources = [];

		var targets = [];

		var checked = 0;

		var protdone = false;

		var redirsToCheck = [];

		for (var i = 0; i < titlepairs.length; i++) {

			var source = titlepairsi][0];

			var target = titlepairsi][1];

			if (titles.indexOf(source) !== -1) {

				badMoves.push(titlepairsi][2]);

				console.log(448);

				checked += 2;

				continue;

			}

			if (titles.indexOf(target) !== -1) {

				console.log(452);

				badMoves.push(titlepairsi][2]);

				checked += 2;

				continue;

			}

			titles.push(source);

			sources.push(sources);

			targets.push(target);

			titles.push(target);

			/*$.ajax({

				url: mw.config.get("wgServer") + mw.config.get("wgScriptPath") + 

				"/api.php?action=titleblacklist&format=json&tbtitle=" + 

				encodeURIComponent(target) + "&tbaction=move&tbnooverride=1",

				dataType: "json",

				success: function(data){

					checked++;

					if (data.error) {

						console.log("Could not get titleblacklist data for " + target);

					} else if (data.titleblacklist.result === "blacklisted") {

						if (tboverride) {

							console.log(target + " matches the titleblacklist");

						} else {

							console.warn(target + " matches the titleblacklist");

							//issues.push({title:target, role:"target", 

								message:target + " matches the titleblacklist"});

						}

					}

					if (checked >= titlepairs.length * 2 && protdone) {

						next();

					}

				},

				error: function() {

					checked++;

					console.log("Could not get titleblacklist data for " + target);

					if (checked >= titlepairs.length * 2 && protdone) {

						next();

					}

				}

			});

			$.ajax({

				url: mw.config.get("wgServer") + mw.config.get("wgScriptPath") + 

				"/api.php?action=titleblacklist&format=json&tbtitle=" + 

				encodeURIComponent(source) + "&tbaction=edit&tbnooverride=1",

				dataType: "json",

				success: function(data){

					checked++;

					if (data.error) {

						console.log("Could not get titleblacklist data for " + source);

						return;

					} else if (data.titleblacklist.result === "blacklisted") {

						if (tboverride) {

							console.log(source + " matches the titleblacklist");

						} else {

							console.warn(source + " matches the titleblacklist");

							//issues.push({title:source, role:"source", 

								message:source + " matches the titleblacklist"});

						}

					}

					if (checked >= titlepairs.length * 2 && protdone) {

						next();

					}

				},

				error: function() {

					checked++;

					console.log("Could not get titleblacklist data for " + source);

					if (checked >= titlepairs.length * 2 && protdone) {

						next();

					}

				}

			});// */

		}

		var loops = 0;

		while (titles.length){

			loops++;

			var titlesToCheck;

			if (titles.length > 50) {

				titlesToCheck = titles.slice(0, 50);

				titles.splice(0, 50);

			} else {

				titlesToCheck = titles;

				titles = [];

			}

			titlesToCheck = encodeURIComponent(titlesToCheck.join("|"));

			$.ajax({

				url: mw.config.get("wgServer") + mw.config.get("wgScriptPath") + 

				"/api.php?action=query&format=json&prop=info&titles=" + 

				titlesToCheck + "&inprop=protection",

				dataType: "json",

				success: function(data){

					var pages = data.query.pages;

					for(var page in pages){

						if (page0 === "-" && sources.indexOf(pagespage].title) !== -1) {

							//source does not exist

							console.log(543);

							badMoves.push(getBaseMove(pagespage].title));

						}

						if (page0 !== "-" && targets.indexOf(pagespage].title) !== -1) {

							redirsToCheck.push(pagespage].title);

						}

						for (var i = 0; i < pagespage].protection.length; i++) {

							if (pagespage].protectioni].type === "move" || 

								pagespage].protectioni].type === "create") {

								if ((pagespage].protectioni].level === "sysop" && !sysop) ||

									(pagespage].protectioni].level === "templateeditor" && !te) ||

									(pagespage].protectioni].level === "extendedconfirmed" && !extconfirmed)) {

									console.log(554);

									badMoves.push(getBaseMove(pagespage].title) ||

										getBaseMove(pagespage].title, 1));

								}

							}

						}

					}

					loops--;

					if (!loops && !titles.length) {

						checkRedirects(overwrite, next, titlepairs, redirsToCheck);

					}

				},

				error: function() {

					loops--;

					console.warn("Could not get protection/existence data for many pages.");

					badMoves.push(':*');

					if (!loops && !titles.length) {

						checkRedirects(overwrite, next, titlepairs, redirsToCheck);

					}

				}

			});

		}

	}

	

	function checkRedirects(overwrite, next, titlepairs, titles){

		console.log('checkRedirects');

		var latestRevisions = {};

		var todo = titles.length;

		if (titles.length === 0) {

			//nothing to do

			next();

		}

		while(titles.length){

			var titlesToCheck;

			if (titles.length > 50) {

				titlesToCheck = titles.slice(0, 50);

				titles.splice(0, 50);

			} else {

				titlesToCheck = titles;

				titles = [];

			}

			titlesToCheck = encodeURIComponent(titlesToCheck.join("|"));

			console.log('AJAX1');

			$.ajax({

				url: mw.config.get("wgServer") + mw.config.get("wgScriptPath") + 

				"/api.php?action=query&format=json&prop=revisions&titles=" + 

				titlesToCheck + "&rvprop=ids%7Ccontent&rvslots=main",

				dataType: "json",

				success: function(data){

					console.log('success1');

					var pages = data.query.pages;

					for(var page in pages){

						latestRevisionspage = pagespage];

						console.log('AJAX2');

						$.ajax({

							url: mw.config.get("wgServer") + mw.config.get("wgScriptPath") + 

							"/api.php?action=query&format=json&prop=revisions&pageids=" + 

							page + "&rvprop=ids%7Ccontent&rvslots=main&rvlimit=1&rvdir=newer",

							dataType: "json",

							success: function(data){

								console.log('success2');

								var pages = data.query.pages;

								var redirectRegExp = /^\s*#REDIRECT\s*\[\[ *([^\][<>|{}#\n]+?) *(?:#[^\][<>|{}\n]*)?]]/i;

								for(var page in pages){

									console.log(todo);

									if (!(pagespage].revisions0].slots.main"*"].match(redirectRegExp) && 

									latestRevisionspage].revisions0].slots.main"*"].match(redirectRegExp))){

										todo--;

										//either current or first revision is not a redir

										console.log(611);

										badMoves.push(getBaseMove(pagespage].title, 1));

									} else if (pagespage].revisions0].revid !== latestRevisionspage].revisions0].revid && !overwrite) {

										// page has non trivial history we cannot overwrite

										todo--;

										console.log(616);

										badMoves.push(getBaseMove(pagespage].title, 1));

									} else {

										var target = latestRevisionspage].revisions0].slots.main"*"].match(redirectRegExp)[1].replace("_", " ");

										target = target.replace(/^./, target.charAt(0).toUpperCase());

										var correct = false;

										for (var i = 0; i < titlepairs.length; i++) {

											if (titlepairsi][0 === target && titlepairsi][1 === pagespage].title){

												correct = true;

												break;

											}

										}

										if (!correct) {

											//does not redirect to source

											todo--;

											console.log(629);

											badMoves.push(getBaseMove(pagespage].title, 1));

										} else if (pagespage].revisions0].revid !== latestRevisionspage].revisions0].revid) {

											overwritePages.push(pagespage].title);

											console.log('AJAX3');

											$.ajax({

												url: mw.config.get("wgServer") + mw.config.get("wgScriptPath") + 

												"/api.php?action=query&format=json&prop=revisions&pageids=" + 

												page + "&rvprop=ids&rvslots=main&rvlimit=1&rvtag=mw-removed-redirect",

												dataType: "json",

												success: function(data){

													console.log('success3');

													var pages = data.query.pages;

													for(var x in pages){

														if(pagesx].revisions &&

														pagesx].revisions.length){

															console.log(642);

															badMoves.push(getBaseMove(pagespage].title, 1));

														}

													}

													todo--;

													if (todo === 0) {

														next();

													}

												},

												error: function() {

													todo--;

													console.warn("Could not get a page's history.");

													if (todo === 0) {

														next();

													}

												}

											});

										} else {

											todo--;

										}

									}

									if (todo === 0) {

										next();

									}

								}

							},

							error: function() {

								todo--;

								console.warn("Could not get a page's history.");

								if (todo === 0) {

									next();

								}

							}

						});

					}

				},

				error: function() {

					console.log(678);

					badMoves.push(':*');

					todo-=50;

					if (todo <= 0) {

						next();

					}

				}

			});

		}

	}

	

	//everything is ready

	start();

	

});

//</nowiki>
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.

/* <nowiki>

 * Some of this code comes from RMCDbot and the UI is based on Evad37's XFDcloser

 */

var $box;

var form, interfaceWindow;

var moves = [];

var badMoves = [];

var overwritePages = [];

var associatedPagesChecked = 0;

var basePages = 0;

$.when(

	window.Morebits || mw.loader.getScript('https://en.wikipedia.org/?title=MediaWiki:Gadget-morebits.js&action=raw&ctype=text/javascript'),

	$.ready,

	importStylesheet( 'MediaWiki:Gadget-morebits.css' )

).then(function(){

	

	//var form, interfaceWindow;

	var moveGroups = {};

	var loaded = false;

	var noSubpageNamespaces = 0, 6, 8, 14, 446];

	/*var moves = [];

	var badMoves = [];

	var overwritePages = [];

	var associatedPagesChecked = 0;

	var basePages = 0;*/

	var defaultConfig = {

		relistSummary: "Relisted requested move using [[User:Danski454/RMcloser|RMcloser]]",

		loadDiff: true,

		outcomes: {

			"moved": {

				wikitext:"'''moved''' ",

				summary: "Closed requested move as moved using [[User:Danski454/RMcloser|RMcloser]]"

			},

			"not moved": {

				wikitext:"'''not moved''' ",

				summary: "Closed requested move as not moved using [[User:Danski454/RMcloser|RMcloser]]"

			},

			"no consensus": {

				wikitext:"'''no consensus''' ",

				summary: "Closed requested move as no consensus using [[User:Danski454/RMcloser|RMcloser]]"

			},

			"withdrawn": {

				wikitext:"'''withdrawn''' ",

				summary: "Closed requested move as withdrawn using [[User:Danski454/RMcloser|RMcloser]]"

			}

		},

		customOutcomeSummary: "Closed requested move using [[User:Danski454/RMcloser|RMcloser]]",

		customSuffix: null,

		overwriteMode: "auto" //off, swap, delete

	};

	

	function makeLink(target, text=null){

		console.log('makeLink');

		if (!text) {

			text = target;

		}

		return '<a href="/wiki/' + target.replace(/ /g, '_') + '">' + text + '</a>';

	}

	

	function display(){

		console.log('display');

		if (moves.length === 0) {

			//no moves

			form.append({

				type: 'div',

				label: 'Unable to get pages'

			});

		} else if (badMoves.indexOf(':*') !== -1) {

			//something has gone wrong

			form.append({

				type: 'div',

				label: 'Unable to validate moves'

			});

		} else {

			var baseGroups = [];

			for (var i = 0; i < moves.length; i++) {

				if (moveGroupsmovesi][2]]) {

					moveGroupsmovesi][2]].moves.push(movesi]);

					if (overwritePages.indexOf(movesi][1]) !== -1) {

						//we are overwriting a redirect

						moveGroupsmovesi][2]].overwrite = true;

					}

				} else {

					moveGroupsmovesi][2]] = {

						moves: movesi]],

						overwrite: overwritePages.indexOf(movesi][1]) !== -1,

						bad: badMoves.indexOf(movesi][2]) !== -1

					};

					if (/^(:\/|t\/|t:)/.test(movesi][2])) {

						var parent = movesi][2].slice(2);

						moveGroupsmovesi][2]].parent = parent;

						if (!moveGroupsparent]) {

							moveGroupsparent = {

								moves: [],

								overwrite: overwritePages.indexOf(parent) !== -1,

								bad: badMoves.indexOf(parent) !== -1,

								children: movesi][2]]

							};

							baseGroups.push(parent);

						} else {

							moveGroupsparent].children.push(movesi][2]);

						}

					} else {

						baseGroups.push(movesi][2]);

						moveGroupsmovesi][2]].children = [];

					}

				}

			}

			var movefield = form.append({

				type: 'field',

				label: 'Moves'

			});

			var moveList = [];

			for (var j = 0; j < baseGroups.length; j++) {

				var source = moveGroupsbaseGroupsj]].moves0][0];

				var target = moveGroupsbaseGroupsj]].moves0][1];

				var flag = '';

				if (moveGroupsbaseGroupsj]].bad) {

					flag = ' [cannot move]';

				} else if (moveGroupsbaseGroupsj]].overwrite) {

					if ((getConfig('overwriteMode') === 'delete' ||

						getConfig('overwriteMode') === 'auto') &&

						Morebits.userIsInGroup("sysop")) {

						flag = ' [will delete target]';

					} else {

						flag = ' [swap]';

					}

				}

				moveList.push({

					name: 'moves-' + baseGroupsj],

					label: source + ' → ' + target + flag,

					checked: !moveGroupsbaseGroupsj]].bad,

					disabled: moveGroupsbaseGroupsj]].bad

				});

				if (moveGroupsbaseGroupsj]].children.length) {

					moveListmoveList.length-1].subgroup = {

						type: 'checkbox',

						list: []

					};

					for (var k = 0; k < moveGroupsbaseGroupsj]].children.length; k++) {

						var cflag = '';

						if (moveGroupsmoveGroupsbaseGroupsj]].childrenk]].bad) {

							cflag = ' [cannot move]';

						} else if (moveGroupsmoveGroupsbaseGroupsj]].childrenk]].overwrite) {

							if ((getConfig('overwriteMode') === 'delete' ||

								getConfig('overwriteMode') === 'auto') &&

								Morebits.userIsInGroup("sysop")) {

								cflag = ' [will delete target]';

							} else {

								cflag = ' [swap]';

							}

						}

						if (moveGroupsbaseGroupsj]].childrenk].charAt(1) === '/') {

							//subpages

							var pages = moveGroupsmoveGroupsbaseGroupsj]].childrenk]].moves.length.toString();

							if (moveGroupsbaseGroupsj]].childrenk].charAt(0) === 't') {

								pages = pages + ' talk';

							}

							var subpageMoves = [];

							for (var l = 0; l < moveGroupsmoveGroupsbaseGroupsj]].childrenk]].moves.length; l++) {

								var move = moveGroupsmoveGroupsbaseGroupsj]].childrenk]].movesl];

								subpageMoves.push(move0 + ' → ' + move1]);

							}

							subpageMoves = subpageMoves.join('\n');

							moveListmoveList.length-1].subgroup.list.push({

								name: 'moves-' + moveGroupsbaseGroupsj]].childrenk],

								label: pages + ' subpage(s)' + cflag,

								checked: !moveGroupsmoveGroupsbaseGroupsj]].childrenk]].bad,

								disabled: moveGroupsmoveGroupsbaseGroupsj]].childrenk]].bad,

								subgroup: {

									type: 'div',

									label: subpageMoves

								}

							});

						} else {

							//talk

							var talk = moveGroups't:' + baseGroupsj]].moves0][0];

							var talkTarget = moveGroups't:' + baseGroupsj]].moves0][1];

							moveListmoveList.length-1].subgroup.list.push({

								name: 'moves-t:' + baseGroupsj],

								label: talk + ' → ' + talkTarget + cflag,

								checked: !moveGroups't:' + baseGroupsj]].bad,

								disabled: moveGroups't:' + baseGroupsj]].bad

							});

						}

					}

				}

			}

			movefield.append({

				type: 'checkbox',

				name: 'moves',

				list: moveList

			});

		}

		form.append({

			type: 'submit',

			label: 'Close Discussion'

		});

		var result = form.render();

		interfaceWindow.setContent(result);

		interfaceWindow.display();

	}

	

	function getValidMoves(){

		console.log('getValidMoves');

		var sysop = Morebits.userIsInGroup("sysop");

		var te = sysop || Morebits.userIsInGroup("templateeditor");

		var extconfirmed = sysop || Morebits.userIsInGroup("extendedconfirmed");

		var overwrite = (sysop || Morebits.userIsInGroup("extendedmover")) &&

			getConfig("overwriteMode") !== "off";

		checkTitles(moves, true, extconfirmed, sysop, te, overwrite, display);

	}

	

	function getBaseMove(title, index = 0){

		console.log('getBaseMove');

		var f = moves.filter(function(t){return tindex === title;});

		if (f.length > 0) {

			return f0][2];

		}

		return null;

	}

	

	function startClose(e){

		console.log('startClose');

	}

	

	function closeDiscussion(outcome, comment){

		console.log('closeDiscussion');

		var outcomes = getConfig("outcomes");

		var suffix = getConfig("customSuffix");

		var top, summary;

		var bottom = "{{subst:RMbottom}}";

		if (suffix === null) {

			if (mw.config.get("wgUserGroups").indexOf("sysop") !== -1) {

				suffix = "";//sysops don't need a suffix

			} else if (mw.config.get("wgUserGroups").indexOf("extendedmover") !== -1) {

				suffix = " {{subst:RMpmc}}";

			} else {

				suffix = " {{subst:RMnac}}";

			}

		}

		if (outcomesoutcome]) {

			top = "{{subst:RMtop|" + outcomesoutcome].wikitext + comment

				+ suffix + "}}";

			summary = outcomesoutcome].summary;

		} else {

			top = "{{subst:RMtop|" + comment + suffix + "}}";

			summary = getConfig("customOutcomeSummary");

		}

		var re = /((=+)[^\n]+\2\s*\n(?:[^\n]|\n[^=])*\n?)\{\{\s?(?:requested move\/dated?|movereq)\s?\}\}\s*((?:[^=]|[^\n=]=|\2=+)+)/i;

		$.ajax({

			url: mw.config.get("wgServer") + mw.config.get("wgScriptPath") + 

			"/api.php?action=query&format=json&prop=revisions&titles=" + 

			mw.config.get("wgPageName") + "&rvprop=ids%7Ccontent&rvslots=main",

			dataType: "json",

			success: function(data){

				for (var page in data.query.pages) {

					var text = data.query.pagespage].revisions0].slots.main"*"];

					text = text.replace(re, "$1" + top + "$3\n" + bottom + "\n");

					$.ajax({

						url: mw.util.wikiScript('api'),

						type: 'POST',

						dataType: 'json',

						data: {

							format: 'json',

							action: 'edit',

							title: mw.config.get('wgPageName'),

							text: text, 

							summary: summary,

							token: mw.user.tokens.get('editToken')

						}

					})

					.done(function(data){

						if (data && data. && data..result && data..result == 'Success') {

							if (getConfig("loadDiff")) {

								if (data..oldrevid !== null && data..newrevid !== undefined){

									window.location.href = mw.config.get('wgScript') + '?diff=' + data..newrevid + '&oldid=' + data..oldrevid;//load diff

								} else {

									alert("Unable to load diff");

								}

							}

						} else {

							alert('Edit failed');

						}

					})

					.fail(function(){

						alert('Edit failed');

					});

				}

			},

			error: function(){

				alert('Edit failed');

			}

		});

	}

	

	function confirmRelist(){

		console.log('confirmRelist');

		if (confirm("Press OK to relist")) {

			relist();

		}

	}

	

	function getConfig(option){

		console.log('getConfig');

		if (typeof(window.RMcloserConfig) === "object" && window.RMcloserConfig

			&& window.RMcloserConfigoption !== undefined) {

			if (defaultConfigoption === undefined) {

				// if user did not set an option, error would occur

				console.warn("Config option '" + option + "' has no default setting.");

			}

			return window.RMcloserConfigoption];

		} else if (defaultConfigoption !== undefined) {

			return defaultConfigoption];

		} else {

			throw Error("Config option '" + option + "' has no default setting and has not been set by the user.");

		}

	}

	

	function relist(){

		console.log('relist');

		$("#RMcloser-relist-button").off("click");

		$.ajax({

			url: mw.config.get("wgServer") + mw.config.get("wgScriptPath") + 

			"/api.php?action=query&format=json&prop=revisions&titles=" + 

			mw.config.get("wgPageName") + "&rvprop=ids%7Ccontent&rvslots=main",

			dataType: "json",

			success: function(data){

				for (var page in data.query.pages) {

					var text = data.query.pagespage].revisions0].slots.main"*"];

					//regex based on RMCD bot's source code

					var re = /\{\{\s?(requested[_ ]move\/dated?|movereq)\s?\}\}.*?([0-2]\d):([0-5]\d),\s(\d{1,2})\s(\w*)\s(\d{4})\s\([A-Z]{3}\)[^\n\r]*/is;

					text = text.replace(re, "$&{{subst:relisting}}");

					$.ajax({

						url: mw.util.wikiScript('api'),

						type: 'POST',

						dataType: 'json',

						data: {

							format: 'json',

							action: 'edit',

							title: mw.config.get('wgPageName'),

							text: text, 

							summary: getConfig("relistSummary"),

							token: mw.user.tokens.get('editToken')

						}

					})

					.done(function(data){

						if (data && data. && data..result && data..result == 'Success') {

							if (getConfig("loadDiff")) {

								if (data..oldrevid !== null && data..newrevid !== undefined){

									window.location.href = mw.config.get('wgScript') + '?diff=' + data..newrevid + '&oldid=' + data..oldrevid;//load diff

								} else {

									alert("Unable to load diff");

								}

							}

						} else {

							alert('Edit failed');

						}

					})

					.fail(function(){

						alert('Edit failed');

					});

				}

			},

			error: function(){

				alert('Edit failed');

			}

		});

	}

	

	function getAssociatedPages(title, target){

		console.log('getAssociatedPages');

		var titleObj = new mw.Title(title);

		var ns = titleObj.getNamespaceId();

		var pageName = titleObj.getMainText();

		if (ns < 0) {

			associatedPagesChecked += 2;

			if (associatedPagesChecked >= 0) { getValidMoves(); }

			return;

		}

		if (noSubpageNamespaces.indexOf(ns) === -1) {

			$.ajax({

				url: mw.config.get("wgServer") + mw.config.get("wgScriptPath") + 

				"/api.php?action=query&format=json&list=allpages&requestid=" + 

				encodeURIComponent(title) + "%7C" + encodeURIComponent(target) + 

				"&apprefix=" + encodeURIComponent(pageName) + "%2F&apnamespace=" + 

				ns.toString() + "&aplimit=101",

				dataType: "json",

				success: function(data){

					if (data.query.allpages.length > 100) {

						//too many subpages

						associatedPagesChecked++;

						if (associatedPagesChecked >= 0) { getValidMoves(); }

						return;

					}

					var base, target = data.requestid.split("|");

					for (var i = 0; i < data.query.allpages.length; i++) {

						moves.push([data.query.allpagesi].title, 

						data.query.allpagesi].title.replace(base, target), ":/" + base]);

					}

					associatedPagesChecked++;

					if (associatedPagesChecked >= 0) { getValidMoves(); }

				}

			});

		} else associatedPagesChecked++;

		if (ns % 2 === 0) {

			var titleTalk = titleObj.getTalkPage().getPrefixedText();

			var targetTalk = new mw.Title(target).getTalkPage().getPrefixedText();

			$.ajax({

				url: mw.config.get("wgServer") + mw.config.get("wgScriptPath") + 

				"/api.php?action=query&format=json&list=allpages&requestid=" + 

				encodeURIComponent(titleTalk) + "%7C" + encodeURIComponent(targetTalk) + 

				"%7C" + encodeURIComponent(title) + "&prop=info&titles=" +

				encodeURIComponent(titleTalk) +

				"&apprefix=" + encodeURIComponent(pageName) + "%2F&apnamespace=" + 

				(ns+1).toString() + "&aplimit=101",

				dataType: "json",

				success: function(data){

					if (data.query.allpages.length > 100) {

						//too many subpages

						associatedPagesChecked++;

						if (associatedPagesChecked >= 0) { getValidMoves(); }

						return;

					}

					var base, target, subject = data.requestid.split("|");

					for (var i = 0; i < data.query.allpages.length; i++) {

						moves.push([data.query.allpagesi].title, 

						data.query.allpagesi].title.replace(base, target), "t/" + subject]);

					}

					for (var id in data.query.pages) {

						if (id !== "-1") {

							//talk page itself exists

							moves.push([base, target, "t:" + subject]);

						}

					}

					associatedPagesChecked++;

					if (associatedPagesChecked >= 0) { getValidMoves(); }

				}

			});

		} else associatedPagesChecked++;

		if (associatedPagesChecked >= 0) { getValidMoves(); }

	}

	

	function generateButtons(){

		console.log('generateButtons');

		if (loaded) return;

		loaded = true;

		$("#RMcloser-close-button").after('loading').remove();

		interfaceWindow = new Morebits.simpleWindow(

			Math.min(900, Math.floor(window.innerWidth*0.8)),

			Math.floor(window.innerHeight*0.9)

		);

		interfaceWindow.setTitle( 'RMcloser' );

		interfaceWindow.addFooterLink('script documentation', 'User:Danski454/RMcloser');

		form = new Morebits.quickForm(startClose);

		var closurefield = form.append({

			type: 'field',

			label: 'Closure'

		});

		var outcomes = getConfig('outcomes');

		var outcomesList = [{value:'', label:'other', selected: true}];

		for (var o in outcomes) {

			outcomesList.push({value:o, label:o});

		}

		closurefield.append({

			type: 'select',

			label: 'Outcome',

			name: 'type',

			list: outcomesList

		});

		closurefield.append({

			type: 'textarea',

			name: 'comment',

			label: 'Additional comments',

			rows: 2,

			cols: 50

		});

		if($box.next().is("p")){

			//single item

			var match = $box.next().text().match(/(.+) → (.+) –/);

			if (match) {

				associatedPagesChecked = -2;//count up to zero, one for talk, one for subject

				moves.push([match1], match2], match1]]);

				getAssociatedPages(match1], match2])

			} else {

				display();

			}

		} else if ($box.next().is("ul")){

			associatedPagesChecked = $box.next().children().length * -2;

			$box.next().children().each(function(){

				var match = $(this).text().match(/(.+) → (.+)/);

				if (match) {

					moves.push([match1], match2], match1]]);

					getAssociatedPages(match1], match2])

				} else {

					associatedPagesChecked += 2;

					if (associatedPagesChecked >= 0) { getValidMoves(); }

				}

			});

		} else {

			display();

		}

	}

	

	function start(){

		console.log('start');

		mw.loader.load( '//en.wikipedia.org/?title=User:Danski454/RMcloser.css&action=raw&ctype=text/css', 'text/css' );

		if (mw.config.get("wgNamespaceNumber") % 2 === 0) {

			return;//we are not on a talk page

		}

		var boxes = 0;

		$(".tmbox-move").each(function(index){

			var $this = $(this);

			var $b = $this.find("td.mbox-text b");

			if($b.text().match(/^It has been proposed in this section that /)) {

				boxes++;

				$box = $this;

			}

		});

		if (boxes !== 1) {

			//we do not have exactly one RM, exiting

			return;

		}

		if (mw.config.get("wgUserGroups").indexOf("autoconfirmed") === -1 && 

			mw.config.get("wgUserGroups").indexOf("confirmed") === -1 && 

			mw.config.get("wgUserGroups").indexOf("sysop") === -1) {

			//must be autoconfirmed

			console.warn("You must be autoconfirmed to use RMcloser");

			return;

		}

		//add button

		$box.find(".mbox-text").children(":last").children().append(' • <a href="#=!=" class="external text" role="button" id="RMcloser-close-button">close</a> • <a href="#=!=" class="external text" role="button" id="RMcloser-relist-button">relist</a>');

		$("#RMcloser-close-button").click(generateButtons);

		$("#RMcloser-relist-button").click(confirmRelist);

	}

	

	function checkTitles(titlepairs, tboverride, extconfirmed, sysop, te, overwrite, next){

		console.log('checkTitles');

		var titles = [];

		var sources = [];

		var targets = [];

		var checked = 0;

		var protdone = false;

		var redirsToCheck = [];

		for (var i = 0; i < titlepairs.length; i++) {

			var source = titlepairsi][0];

			var target = titlepairsi][1];

			if (titles.indexOf(source) !== -1) {

				badMoves.push(titlepairsi][2]);

				console.log(448);

				checked += 2;

				continue;

			}

			if (titles.indexOf(target) !== -1) {

				console.log(452);

				badMoves.push(titlepairsi][2]);

				checked += 2;

				continue;

			}

			titles.push(source);

			sources.push(sources);

			targets.push(target);

			titles.push(target);

			/*$.ajax({

				url: mw.config.get("wgServer") + mw.config.get("wgScriptPath") + 

				"/api.php?action=titleblacklist&format=json&tbtitle=" + 

				encodeURIComponent(target) + "&tbaction=move&tbnooverride=1",

				dataType: "json",

				success: function(data){

					checked++;

					if (data.error) {

						console.log("Could not get titleblacklist data for " + target);

					} else if (data.titleblacklist.result === "blacklisted") {

						if (tboverride) {

							console.log(target + " matches the titleblacklist");

						} else {

							console.warn(target + " matches the titleblacklist");

							//issues.push({title:target, role:"target", 

								message:target + " matches the titleblacklist"});

						}

					}

					if (checked >= titlepairs.length * 2 && protdone) {

						next();

					}

				},

				error: function() {

					checked++;

					console.log("Could not get titleblacklist data for " + target);

					if (checked >= titlepairs.length * 2 && protdone) {

						next();

					}

				}

			});

			$.ajax({

				url: mw.config.get("wgServer") + mw.config.get("wgScriptPath") + 

				"/api.php?action=titleblacklist&format=json&tbtitle=" + 

				encodeURIComponent(source) + "&tbaction=edit&tbnooverride=1",

				dataType: "json",

				success: function(data){

					checked++;

					if (data.error) {

						console.log("Could not get titleblacklist data for " + source);

						return;

					} else if (data.titleblacklist.result === "blacklisted") {

						if (tboverride) {

							console.log(source + " matches the titleblacklist");

						} else {

							console.warn(source + " matches the titleblacklist");

							//issues.push({title:source, role:"source", 

								message:source + " matches the titleblacklist"});

						}

					}

					if (checked >= titlepairs.length * 2 && protdone) {

						next();

					}

				},

				error: function() {

					checked++;

					console.log("Could not get titleblacklist data for " + source);

					if (checked >= titlepairs.length * 2 && protdone) {

						next();

					}

				}

			});// */

		}

		var loops = 0;

		while (titles.length){

			loops++;

			var titlesToCheck;

			if (titles.length > 50) {

				titlesToCheck = titles.slice(0, 50);

				titles.splice(0, 50);

			} else {

				titlesToCheck = titles;

				titles = [];

			}

			titlesToCheck = encodeURIComponent(titlesToCheck.join("|"));

			$.ajax({

				url: mw.config.get("wgServer") + mw.config.get("wgScriptPath") + 

				"/api.php?action=query&format=json&prop=info&titles=" + 

				titlesToCheck + "&inprop=protection",

				dataType: "json",

				success: function(data){

					var pages = data.query.pages;

					for(var page in pages){

						if (page0 === "-" && sources.indexOf(pagespage].title) !== -1) {

							//source does not exist

							console.log(543);

							badMoves.push(getBaseMove(pagespage].title));

						}

						if (page0 !== "-" && targets.indexOf(pagespage].title) !== -1) {

							redirsToCheck.push(pagespage].title);

						}

						for (var i = 0; i < pagespage].protection.length; i++) {

							if (pagespage].protectioni].type === "move" || 

								pagespage].protectioni].type === "create") {

								if ((pagespage].protectioni].level === "sysop" && !sysop) ||

									(pagespage].protectioni].level === "templateeditor" && !te) ||

									(pagespage].protectioni].level === "extendedconfirmed" && !extconfirmed)) {

									console.log(554);

									badMoves.push(getBaseMove(pagespage].title) ||

										getBaseMove(pagespage].title, 1));

								}

							}

						}

					}

					loops--;

					if (!loops && !titles.length) {

						checkRedirects(overwrite, next, titlepairs, redirsToCheck);

					}

				},

				error: function() {

					loops--;

					console.warn("Could not get protection/existence data for many pages.");

					badMoves.push(':*');

					if (!loops && !titles.length) {

						checkRedirects(overwrite, next, titlepairs, redirsToCheck);

					}

				}

			});

		}

	}

	

	function checkRedirects(overwrite, next, titlepairs, titles){

		console.log('checkRedirects');

		var latestRevisions = {};

		var todo = titles.length;

		if (titles.length === 0) {

			//nothing to do

			next();

		}

		while(titles.length){

			var titlesToCheck;

			if (titles.length > 50) {

				titlesToCheck = titles.slice(0, 50);

				titles.splice(0, 50);

			} else {

				titlesToCheck = titles;

				titles = [];

			}

			titlesToCheck = encodeURIComponent(titlesToCheck.join("|"));

			console.log('AJAX1');

			$.ajax({

				url: mw.config.get("wgServer") + mw.config.get("wgScriptPath") + 

				"/api.php?action=query&format=json&prop=revisions&titles=" + 

				titlesToCheck + "&rvprop=ids%7Ccontent&rvslots=main",

				dataType: "json",

				success: function(data){

					console.log('success1');

					var pages = data.query.pages;

					for(var page in pages){

						latestRevisionspage = pagespage];

						console.log('AJAX2');

						$.ajax({

							url: mw.config.get("wgServer") + mw.config.get("wgScriptPath") + 

							"/api.php?action=query&format=json&prop=revisions&pageids=" + 

							page + "&rvprop=ids%7Ccontent&rvslots=main&rvlimit=1&rvdir=newer",

							dataType: "json",

							success: function(data){

								console.log('success2');

								var pages = data.query.pages;

								var redirectRegExp = /^\s*#REDIRECT\s*\[\[ *([^\][<>|{}#\n]+?) *(?:#[^\][<>|{}\n]*)?]]/i;

								for(var page in pages){

									console.log(todo);

									if (!(pagespage].revisions0].slots.main"*"].match(redirectRegExp) && 

									latestRevisionspage].revisions0].slots.main"*"].match(redirectRegExp))){

										todo--;

										//either current or first revision is not a redir

										console.log(611);

										badMoves.push(getBaseMove(pagespage].title, 1));

									} else if (pagespage].revisions0].revid !== latestRevisionspage].revisions0].revid && !overwrite) {

										// page has non trivial history we cannot overwrite

										todo--;

										console.log(616);

										badMoves.push(getBaseMove(pagespage].title, 1));

									} else {

										var target = latestRevisionspage].revisions0].slots.main"*"].match(redirectRegExp)[1].replace("_", " ");

										target = target.replace(/^./, target.charAt(0).toUpperCase());

										var correct = false;

										for (var i = 0; i < titlepairs.length; i++) {

											if (titlepairsi][0 === target && titlepairsi][1 === pagespage].title){

												correct = true;

												break;

											}

										}

										if (!correct) {

											//does not redirect to source

											todo--;

											console.log(629);

											badMoves.push(getBaseMove(pagespage].title, 1));

										} else if (pagespage].revisions0].revid !== latestRevisionspage].revisions0].revid) {

											overwritePages.push(pagespage].title);

											console.log('AJAX3');

											$.ajax({

												url: mw.config.get("wgServer") + mw.config.get("wgScriptPath") + 

												"/api.php?action=query&format=json&prop=revisions&pageids=" + 

												page + "&rvprop=ids&rvslots=main&rvlimit=1&rvtag=mw-removed-redirect",

												dataType: "json",

												success: function(data){

													console.log('success3');

													var pages = data.query.pages;

													for(var x in pages){

														if(pagesx].revisions &&

														pagesx].revisions.length){

															console.log(642);

															badMoves.push(getBaseMove(pagespage].title, 1));

														}

													}

													todo--;

													if (todo === 0) {

														next();

													}

												},

												error: function() {

													todo--;

													console.warn("Could not get a page's history.");

													if (todo === 0) {

														next();

													}

												}

											});

										} else {

											todo--;

										}

									}

									if (todo === 0) {

										next();

									}

								}

							},

							error: function() {

								todo--;

								console.warn("Could not get a page's history.");

								if (todo === 0) {

									next();

								}

							}

						});

					}

				},

				error: function() {

					console.log(678);

					badMoves.push(':*');

					todo-=50;

					if (todo <= 0) {

						next();

					}

				}

			});

		}

	}

	

	//everything is ready

	start();

	

});

//</nowiki>

Videos

Youtube | Vimeo | Bing

Websites

Google | Yahoo | Bing

Encyclopedia

Google | Yahoo | Bing

Facebook