User:Splarka/ajaxbatchmove.js
Appearance
Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump. This code will be executed when previewing this page. |
Documentation for this user script can be added at User:Splarka/ajaxbatchmove. |
/* Ajax batch move module, version [0.0.3c]
Originally from: http://wiki.riteme.site/wiki/User:Splarka/ajaxbatchmove.js
Notes:
* It is a bit verbose, after debugging perhaps some output should be removed.
* It waits 1 second after every move before starting the next.
* Can be aborted by simply deleting the contents of the textarea, or leaving the page.
* Stops when it hits a blank line, or line with no pipe.
* Nonfatal errors (skip to next line):
** Bad character or malformed line
** Bad token
** Unexpected response
* Pauses in execution can be added with a blank line.
* Not been postively tested! As of this writing API moves are broken on test.wikipedia [5:23 PM 3/13/09]
* Suppressing redirects should work, maybe. I didn't bother with move subpage/talkpage switches, too scary!
To do:
* Cache the token if two the same?
** Please note the move token is not guaranteed to be static, but currently it always is.
*/
$(function() {
mw.util.addPortletLink('p-tb','/wiki/Special:BlankPage?blankspecial=ajaxbm','Batch Move');
});
if(wgCanonicalSpecialPageName && wgCanonicalSpecialPageName.toLowerCase() == 'blankpage' && queryString('blankspecial') == 'ajaxbm') {
document.title = 'Ajax Batch Move';
addOnloadHook(abmForm);
}
function abmForm() {
mw.util.addPortletLink('p-tb','/wiki/Special:Log/move?user=' + encodeURIComponent(wgUserName),'My move log');
//subvert this Special: page to our own needs.
var con = document.getElementById('content') || document.getElementById('mw_content');
var bcon = document.getElementById('bodyContent') || document.getElementById('mw_contentholder');
var fh = getElementsByClassName(con,'h1','firstHeading')[0];
while(fh.firstChild) fh.removeChild(fh.firstChild)
fh.appendChild(document.createTextNode('Ajax Batch Move'));
for(var i=0;i<bcon.childNodes.length;i++) {
bcur = bcon.childNodes[i];
if(bcur.id != 'siteSub' && bcur.id != 'contentSub' && bcur.className != 'visualClear') {
while(bcur.firstChild) bcur.removeChild(bcur.firstChild)
if(bcur.nodeType == 3) bcur.nodeValue = '';
}
}
//generate content (this is ugly yes, but better than innerHTML and very portable; only needs wikibits.js)
var form = document.createElement('form');
form.appendChild(document.createTextNode('Enter the pages to be moved here, one per line, with the format: Old title|New title'));
form.setAttribute('action','javascript:void(0)');
form.appendChild(document.createElement('p'));
form.setAttribute('action','javascript:void(0);');
var txt = document.createElement('textarea');
txt.style.height = '20em';
txt.style.width = '50%';
txt.setAttribute('id','abm-textarea');
form.appendChild(txt);
form.appendChild(document.createElement('p'));
var lab1 = document.createElement('label');
lab1.setAttribute('for','abm-reason')
lab1.appendChild(document.createTextNode('Move reason: '));
form.appendChild(lab1);
var inp1 = document.createElement('input');
inp1.style.width = '20em';
inp1.setAttribute('type','text');
inp1.setAttribute('id','abm-reason');
form.appendChild(inp1);
var inp2 = document.createElement('input');
inp2.setAttribute('type','checkbox');
inp2.setAttribute('id','abm-redirect');
form.appendChild(inp2);
var lab2 = document.createElement('label');
lab2.setAttribute('for','abm-redirect')
lab2.appendChild(document.createTextNode('Suppress redirects'));
form.appendChild(lab2);
form.appendChild(document.createElement('p'));
var sub1 = document.createElement('input');
sub1.setAttribute('type','button');
sub1.setAttribute('id','abm-startbutton');
sub1.setAttribute('value','start');
addHandler(sub1,'click',abmStart);
form.appendChild(sub1);
bcon.appendChild(form);
var pre = document.createElement('pre');
pre.setAttribute('id','abm-output');
bcon.appendChild(pre);
}
function abmStart() {
document.getElementById('abm-startbutton').setAttribute('disabled','disabled');
var out = document.getElementById('abm-output');
var txt = document.getElementById('abm-textarea');
var moves = txt.value.split('\n');
var move = moves[0];
if(move.indexOf('|') == -1 || move == '') {
out.appendChild(document.createTextNode('* Done! Nothing left to do, or next line is blank.\n'));
document.getElementById('abm-startbutton').removeAttribute('disabled');
} else {
var badchars = /(\#|\<|\>|\[|\]|\{|\}|\|.*\|)/;
if(badchars.test(move)) {
out.appendChild(document.createTextNode('! Illegal characters detected, skipping:' + move + '\n'));
setTimeout('abmStart()',1000);
} else {
var oldtitle = move.substr(0,move.indexOf('|'));
var newtitle = move.substr(move.indexOf('|')+1);
out.appendChild(document.createTextNode('> Attempting to move [[' + oldtitle + ']] to [[' + newtitle + ']]\n'));
abdGetToken(oldtitle,newtitle);
}
}
moves = moves.slice(1,moves.length);
txt.value = moves.join('\n');
}
function abdGetToken(oldtitle,newtitle) {
var out = document.getElementById('abm-output');
out.appendChild(document.createTextNode(' > Fetching move token for [[' + oldtitle + ']]\n'));
var url = wgScriptPath + '/api.php?action=query&prop=info&indexpageids=1&intoken=move&format=json&titles=' + encodeURIComponent(oldtitle);
var req = sajax_init_object();
req.open('GET', url, true);
req.onreadystatechange = function() {
if(req.readyState == 4 && req.status == 200) {
eval("abmMove(" + req.responseText + ",'" + req.responseText.replace(/\'/g,"`") + "','" + oldtitle + "','" + newtitle + "')");
}
}
req.send(null);
}
function abmMove(obj,txt,oldtitle,newtitle) {
var out = document.getElementById('abm-output');
if(obj['error']) {
out.appendChild(document.createTextNode(' ! Api error: ' + obj['error']['code'] + ' - ' + obj['error']['info'] + '\n'));
return;
}
if(!obj['query'] || !obj['query']['pageids'] || !obj['query']['pages'][obj['query']['pageids'][0]] || !obj['query']['pages'][obj['query']['pageids'][0]]['movetoken']) {
out.appendChild(document.createTextNode(' ? Unexpected response: ' + txt + '\n'));
return;
}
var token = obj['query']['pages'][obj['query']['pageids'][0]]['movetoken'];
out.appendChild(document.createTextNode(' > Token found, attempting move\n'));
var reason = document.getElementById('abm-reason').value;
var params = 'action=move&format=json&token=' + encodeURIComponent(token) + '&from=' + encodeURIComponent(oldtitle) + '&to=' + encodeURIComponent(newtitle) + '&reason=' + encodeURIComponent(reason);
if(document.getElementById('abm-redirect').checked) params += '&noredirect=1'
var url = wgScriptPath + '/api.php';
var req = sajax_init_object();
req.open('POST', url, true);
req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
req.setRequestHeader('Content-length', params.length);
req.setRequestHeader('Connection', 'close');
req.onreadystatechange = function() {
if(req.readyState == 4 && req.status == 200) {
eval("abmMoveAftermath(" + req.responseText + ",'" + req.responseText.replace(/\'/g,"`") + "')");
}
}
req.send(params);
}
function abmMoveAftermath(obj,txt) {
var out = document.getElementById('abm-output');
//{"error":{"code":"Invalid token","info":"badtoken"}}
//{"move": {"from": "User:Splarka\/cat","to": "User:Splarka\/cattest","reason": "better name","redirectcreated": ""}}
if(obj['error']) {
out.appendChild(document.createTextNode(' ! Api error: ' + obj['error']['code'] + ' - ' + obj['error']['info'] + '\n'));
} else if(obj['move'] && obj['move']['from'] && obj['move']['to']) {
out.appendChild(document.createTextNode(' > Page [[' + obj['move']['from'] + ']] moved to [[' + obj['move']['to'] + ']]\n'));
} else {
out.appendChild(document.createTextNode(' ? Unexpected response: ' + txt + '\n'));
}
setTimeout('abmStart()',1000);
}
function queryString(p) {
var re = RegExp('[&?]' + p + '=([^&]*)');
var matches;
if (matches = re.exec(document.location)) {
try {
return decodeURI(matches[1]);
} catch (e) {
}
}
return null;
}