User:Silikonz/massmove.js

//jshint maxerr:512 var massMoveTitle = "Mass-move tool"; /*Forked version of User:Plastikspork/massmove.js that adds a link to the left column and allows adding and removing both prefixes and suffixes

Add the following line to Special:MyPage/common.js or meta:Special:MyPage/global.js to install:

mw.loader.load( '//en.wikipedia.org/w/index.php?title=User:Ahecht/Scripts/massmove.js&action=raw&ctype=text/javascript' ); //User:Ahecht/Scripts/massmove.js User:Plastikspork/massmove.js Click on "Mass move" under "Tools" to use the script.*/

mw.util.addPortletLink("p-tb", "/wiki/Special:MassMove", "Mass move", "p-massmove", "Mass move");

// Adapted from User:Animum/massdelete.js function massMoveGetValues { return {reason: document.getElementById("wpMassMoveReason").value, oldPrefix: document.getElementById("wpMassMovePrefix1").value, newPrefix: document.getElementById("wpMassMovePrefix2").value, oldSuffix: document.getElementById("wpMassMoveSuffix1").value, newSuffix: document.getElementById("wpMassMoveSuffix2").value, watch: document.getElementById("wpMassMoveWatch").value, pipeTrick: document.getElementById("wpMassMovePipeTrick").checked, leaveRedirect: document.getElementById("wpMassMoveLeaveRedirect").checked, noRatelimit: document.getElementById("wpMassMoveNoRatelimit").checked, moveTalk: document.getElementById("wpMassMoveMoveTalk").checked, moveSubPages: document.getElementById("wpMassMoveMoveSubPages").checked }; }

function massMoveReplace(s, values) { s = s.trim; if (values.pipeTrick) { s = s.replace(/^(?:\:)?(?:.*\:)?(.*?)(?:, .*)?$/,"$1").replace(/(.*?)(?: ?\(.*\))?$/, "$1"); }	if (s.substring(0,values.oldSuffix.length) == values.oldSuffix) { s = s.substring(values.oldPrefix.length); }	if (s.substring(s.length - values.oldSuffix.length) == values.oldSuffix) { s = s.substring(0, s.length - values.oldSuffix.length); }	return values.newPrefix + s + values.newSuffix; }

function massMoveGetArticles { var articles = document.getElementById("wpMassMovePages").value.split("\n"); var ret = []; var i, len; for (i = 0, len = articles.length; i < len; i++) { var s = articles[i]; s = s.trim; if (s) { ret.push(s); }	}	return ret; } function massMoveUpdatePreview { var	articles = massMoveGetArticles; if (articles.length > 0) { var values = massMoveGetValues; var preview = [articles[0] + " → " + massMoveReplace(articles[0], values)]; for (var i = 1, len = articles.length; i < len; i++) { preview.push(articles[i] + " → " + massMoveReplace(articles[i], values)); }		document.getElementById("wpMassMovePreview").value = preview.join("\n"); document.getElementById("wpMassMoveSubmit").disabled = false; } else { document.getElementById("wpMassMovePreview").value = ''; document.getElementById("wpMassMoveSubmit").disabled = true; } }

jQuery(document).ready(function($) {	var config = mw.config.get(['wgNamespaceNumber', 'wgTitle', 'wgUserGroups', 'skin']);	function now {		return new Date.getTime;	}

function doMassMove { var articles = massMoveGetArticles; if (!articles.length) { return; }		var api = new mw.Api, values = massMoveGetValues, moved = 0, failed = [], error = [], deferreds = [], lastMoved = 0, onSuccess = function { moved++; console.log(now + ": Moved " + moved); mw.notify("Success! " + moved + " pages moved.", {type: 'success', tag: 'status', autoHide: true}); };		function delay(len) { return function { return $.Deferred(function (deferred) {					var interval = lastMoved + config.wait - now;					if ( (len <= config.hits) || ((lastMoved + config.wait - now) < 0) || values.noRatelimit ) {						interval = 0;					}					console.log(now + ': Waiting ' + interval + 'ms...');					setTimeout(function { console.log(now + ': Done waiting.'); deferred.resolve; }, interval);				}); };		}		function makeMoveFunc(article) { return function { return $.Deferred(function (deferred) {					var options = {						format: 'json',						action: 'move',						watchlist: values.watch,						from: article,						to: massMoveReplace(article, values),						reason: values.reason + ' (' + massMoveTitle + ')'					};					if (!values.leaveRedirect) {						options.noredirect = ;					}					if (values.moveTalk) {						options.movetalk = ;					}					if (values.moveSubPages) {						options.movesubpages = '';					}					console.log(now + ": Moving " + options.from + "→" + options.to);					mw.notify("Moving " + options.from + " → " + options.to, {type: 'info', tag: 'status', autoHide: true});					lastMoved = now;					var promise = api.postWithEditToken(options);					promise.done(onSuccess);					promise.fail(function (code, obj) { failed.push(article); error.push(obj.error.info); console.warn(now + ": Move failed (" + obj.error.info + ")."); mw.notify("Move failed: " + obj.error.info, {type: 'error', autoHide: true}); });					promise.always(function { deferred.resolve; });				});			};		}

// Make a chain of deferred objects. We chain them rather than execute them in		// parallel so that we don't make 1000 simultaneous move requests and bring the // site down. We use deferred objects rather than the promise objects returned // from the API request so that the chain continues even if some articles gave // errors. var deferred = makeMoveFunc(articles[0]); for (var i = 1, len = articles.length; i < len; i++) { deferred = deferred.then(delay(len)); deferred = deferred.then(makeMoveFunc(articles[i])); }

// Show the output and do cleanup once all the requests are done. $.when(deferred).then(function {			console.log(now + ": Done! Moved " + moved);			if (failed.length) {				mw.notify("Done. " + moved + " pages moved, " + failed.length + " errors.", {type: 'warn', tag: 'mainNotify', autoHide: false});				var $failedList = $('');				for(var x = 0; x < failed.length; x++) {					// Link the titles in the "failed" array					var failedTitle = mw.Title.newFromText(failed[x]);					var $failedItem = $('');					if (failedTitle) {						$failedItem.append( $('') .attr('href', failedTitle.getUrl) .text(failed[x]) );					} else {						$failedItem.text(failed[x]);					}					$failedItem.append(document.createTextNode(': ' + error[x]));					$failedList.append($failedItem);				}				$('#wpMassMoveFailedContainer')					.append($(' '))					.append($('') .text('Failed moves:') )					.append($failedList);			} else {				mw.notify("Done. " + moved + " pages moved.", {type: 'success', tag: 'mainNotify', autoHide: false});			}			document.getElementById("wpMassMoveSubmit").value = "Move";			$("*", "#wpMassMove").not("#wpMassMovePreview").prop('disabled',false);		}); } 	function getWait { config.hits=8; // default rate limit is 8/minute config.seconds=60; // default rate limit is 8/minute config.wait = Math.ceil(config.seconds/config.hits) * 1000; new mw.Api.get({   		meta: 'userinfo',    		uiprop: 'ratelimits'		}).fail(function(code, error) {			console.warn(error);			doMassMove;		}).done( function(d) {			if (d && d.query && d.query.userinfo && d.query.userinfo.ratelimits && d.query.userinfo.ratelimits.move)			{				for (const property in d.query.userinfo.ratelimits.move) {					var rlm = d.query.userinfo.ratelimits.move[property];					if (rlm && rlm.hits && rlm.seconds) {						console.log(property + " rate limit: " + rlm.hits + " moves every " + rlm.seconds + " seconds.");						var thisWait = Math.ceil(rlm.seconds/rlm.hits) * 1000;						if (thisWait < config.wait) {							config.hits = rlm.hits;							config.seconds = rlm.seconds;							config.wait = thisWait;							console.log("Calculated " + config.wait + "-millisecond wait between queries");						}					}				}			}			mw.notify("Rate limit: " + config.hits + " moves every " + config.seconds + " seconds.", {type: 'info', tag: 'mainNotify', autoHide: false});			doMassMove;		}); }	function massMoveForm { wpMassMoveStyle = document.createElement('style'); wpMassMoveStyle.type = 'text/css'; document.getElementsByTagName('head')[0].appendChild(wpMassMoveStyle); wpMassMoveStyle = document.styleSheets[document.styleSheets.length-1]; if (typeof(wpMassMoveStyle.media) === 'string') { //IE compatability wpMassMoveStyle.addRule('td.mincol', 'width:1%; white-space:nowrap;'); wpMassMoveStyle.addRule('td.maxcol', 'width:auto'); } else if (typeof(wpMassMoveStyle.media) === 'object') { //Modern browsers wpMassMoveStyle.insertRule('td.mincol {width:1%; white-space:nowrap;}', wpMassMoveStyle.cssRules.length); wpMassMoveStyle.insertRule('td.maxcol {width:auto;}', wpMassMoveStyle.cssRules.length); }		document.getElementById(config.bodyContent).innerHTML = config.wpMassMoveIntro + '' + ' ' +			'

' +				'Pages to move (one on each line, please): ' +					' ' + '

' +				'

Preview: ' +					' ' + '

' + ' ';		document.getElementById("wpMassMoveSubmit").addEventListener("click", function (e) {			$('#wpMassMoveFailedContainer').empty;			$("*", "#wpMassMove").prop('disabled',true);			document.getElementById("wpMassMoveSubmit").value = "Moving...";			getWait;		}); }	function massMoveError { document.getElementById(config.bodyContent).innerHTML = config.wpMassMoveIntro + 'For more information, please feel free to contact the script author!'; }	if(mw.config.get('wgNamespaceNumber') === -1 		&& (mw.config.get('wgTitle') === "Massmove" || mw.config.get('wgTitle') === "MassMove")	) { document.getElementsByTagName("h1")[0].textContent = massMoveTitle; document.title = massMoveTitle + " - Wikipedia, the free encyclopedia"; config.wpMassMoveIntro = ' From Wikipedia, the free encyclopedia ' + ' Adapted from Plastikspork\'s mass-move tool, which is in turn adapted from Animum\'s mass-delete tool and Timotheus Canens\'s mass-edit tool ' + ' ' + 'Your user groups are: ' + mw.config.get('wgUserGroups') + '

';

if (config.skin == 'modern') { config.bodyContent = 'mw_contentholder'; } else if (config.skin == 'cologneblue') { config.bodyContent = 'article'; } else { config.bodyContent = 'bodyContent'; }		$.when( $.ready, mw.loader.using(['mediawiki.util'])).done( massMoveForm ); } });