Jump to content

User:Splarka/ajaxbatchundelete.js

From Wikipedia, the free encyclopedia
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
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.
/* Ajax batch undelete thingy, version [0.0.1]
Originally from: http://en.wikipedia.org/wiki/User:Splarka/ajaxbatchundelete.js

Notes:
* It is a bit verbose, after debugging perhaps some output should be removed.
* It waits 1 second after every undelete 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.
* 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.

To do:
* Cache the token if two the same?
** Please note the delete token is not guaranteed to be static, but currently it always is.
*/

addOnloadHook(function() {
  mw.util.addPortletLink('p-tb','/wiki/Special:BlankPage?blankspecial=ajaxbu','Batch Undelete');
});

if(mw.config.get('wgCanonicalSpecialPageName') && mw.config.get('wgCanonicalSpecialPageName').toLowerCase() == 'blankpage' && queryString('blankspecial') == 'ajaxbu') {
  document.title = 'Ajax Batch Undeletion';
  addOnloadHook(abuForm);
}

function abuForm() {
  mw.util.addPortletLink('p-tb','/wiki/Special:Log/delete?user=' + encodeURIComponent(mw.config.get('wgUserName')),'My delete 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 Undeletion'));
  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
  var form = document.createElement('form');
   form.appendChild(document.createTextNode('List of pages to undelete:'));
   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','abu-textarea');
   form.appendChild(txt);
   form.appendChild(document.createElement('p'));
   var lab1 = document.createElement('label');
    lab1.setAttribute('for','abu-reason')
    lab1.appendChild(document.createTextNode('Restore reason: '));
   form.appendChild(lab1);
   var inp1 = document.createElement('input');
    inp1.style.width = '20em';
    inp1.setAttribute('type','text');
    inp1.setAttribute('id','abu-reason');
   form.appendChild(inp1);
   form.appendChild(document.createElement('p'));
   var sub1 = document.createElement('input');
    sub1.setAttribute('type','button');
    sub1.setAttribute('id','abu-startbutton');
    sub1.setAttribute('value','start');
    sub1.setAttribute('onclick','abuStart()');
   form.appendChild(sub1);
  bcon.appendChild(form);
  var pre = document.createElement('pre');
   pre.setAttribute('id','abu-output');
  bcon.appendChild(pre);
}

function abuStart() {
  document.getElementById('abu-startbutton').setAttribute('disabled','disabled');
  var out = document.getElementById('abu-output');
  var txt = document.getElementById('abu-textarea');
  var undeletes = txt.value.split('\n');
  var page = undeletes[0];
  if(page == '') {
    out.appendChild(document.createTextNode('* Done! Nothing left to do, or next line is blank.\n'));
    document.getElementById('abu-startbutton').removeAttribute('disabled');
  } else {
    var badchars = /(\#|\<|\>|\[|\]|\{|\}|\|)/;
    if(badchars.test(page)) {
      out.appendChild(document.createTextNode('! Illegal characters detected, skipping:' + page + '\n'));
      setTimeout('abuStart()',1000);
    } else {
      out.appendChild(document.createTextNode('> Attempting to undelete [[' + page + ']]\n'));
      abuGetToken(page);
    }
  }
  undeletes = undeletes.slice(1,undeletes.length);
  txt.value = undeletes.join('\n');
}

function abuGetToken(page) {
  var out = document.getElementById('abu-output');
  out.appendChild(document.createTextNode(' > Fetching undelete token for [[' + page + ']]\n'));
  var url = mw.config.get('wgScriptPath') + '/api.php?action=query&list=deletedrevs&drprop=token&drlimit=1&format=json&titles=' + encodeURIComponent(page);
  var req = sajax_init_object();
  req.open('GET', url, true);
  req.onreadystatechange = function() {
    if(req.readyState == 4 && req.status == 200) {
      eval("abuUndelete(" + req.responseText + ",'" + req.responseText.replace(/\'/g,"`") + "','" + page + "')");
    }
  }
  req.send(null);
}

function abuUndelete(obj,txt,page) {
  var out = document.getElementById('abu-output');
  if(obj['error']) {
    out.appendChild(document.createTextNode(' ! Api error: ' + obj['error']['code'] + ' - ' + obj['error']['info'] + '\n'));
    return;
  }
  if(!obj['query'] || !obj['query']['deletedrevs'] || !obj['query']['deletedrevs'][0]  || !obj['query']['deletedrevs'][0]['token']) {
    out.appendChild(document.createTextNode('  ? Unexpected response: ' + txt + '\n'));
    return;
  }
  var token = obj['query']['deletedrevs'][0]['token'];
  out.appendChild(document.createTextNode('  > Token found, attempting undelete\n'));
  var reason = document.getElementById('abu-reason').value;

  var params = 'action=undelete&format=json&token=' + encodeURIComponent(token) + '&title=' + encodeURIComponent(page) + '&reason=' + encodeURIComponent(reason);
  var url = mw.config.get('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("abuUndeleteAftermath(" + req.responseText + ",'" + req.responseText.replace(/\'/g,"`") + "')");
    }
  }
  req.send(params);
}

function abuUndeleteAftermath(obj,txt) {
  var out = document.getElementById('abu-output');

  //{"undelete":{"title":"Test 6","revisions":3,"fileversions":0,"reason":3}}
  if(obj['error']) {
    out.appendChild(document.createTextNode('   ! Api error: ' + obj['error']['code'] + ' - ' + obj['error']['info'] + '\n'));
  } else if(obj['undelete'] && obj['undelete']['title']) {
    var details = '';
    if(obj['undelete']['revisions']) details += ', ' + obj['undelete']['revisions'] + ' revisions restored'
    if(obj['undelete']['fileversions']) details += ', ' + obj['undelete']['fileversions'] + ' file versions restored'
    out.appendChild(document.createTextNode('   > Page [[' + obj['undelete']['title'] + ']] undeleted' + details + '\n'));
  } else {
    out.appendChild(document.createTextNode('   ? Unexpected response: ' + txt + '\n'));
    return;
  }
  setTimeout('abuStart()',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;
}