User:Nx/Scripts/Botswitch greasemonkey.js

From RationalWiki
Jump to navigation Jump to search

Note: After saving, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Go to Menu → Settings (Opera → Preferences on a Mac) and then to Privacy & security → Clear browsing data → Cached images and files.
/*<![CDATA[*/
// ==UserScript==
// @name           botswitch
// @namespace      http://www.rationalwiki.com/User:Nx
// @description    Script to allow switching between two accounts easily on rationalwiki.com
// @include        http://rationalwiki.com/*
// @include        http://www.rationalwiki.com/*
// ==/UserScript==

//Contains switching rules, in the form of "Username" : "Username to switch to"
accounts = {
  "Nx" : "NxBot",
  "NxBot" : "Nx"
}

/*
getElementsByClass
*/

function getElementsByClass(classname,node) 
{
  function _recGet(out, element, cname)
  {
    while(element)
    {
      if (element.nodeType == 1)
      {
        if (element.className)
        {
          if (element.className.indexOf(cname) != -1)
          {
            out.push(element);
          }
        }
        _recGet(out,element.firstChild,cname)
      }
      element = element.nextSibling;
    }
  }
  
  
  if (!node) node = document.documentElement;
  var res = new Array();
  _recGet(res,node,classname);
  return res;  
}

/*
  Forms
*/

function JForm()
{
  //styles

  var s = document.createElement('style');

  s.type = 'text/css';

  s.rel = 'stylesheet';

  s.appendChild(document.createTextNode('')); //Safari sometimes borks on null

  document.getElementsByTagName('head')[0].appendChild(s);

  var ss;

  if (s.styleSheet) {ss = s.styleSheet;} //IE

  else {ss = s.sheet;}

  ss.insertRule(

    "form.jform { width:96%; " +

                  "margin:auto; " +
                  "padding:.5em; " +
                  "vertical-align:middle; " +

                  "}"

                  ,0

  );

  ss.insertRule(

    "form.jform * { font-family:sans-serif; " +
                  "vertical-align:middle; " +

                  "}"

                  ,0

  );

  this.root = document.createElement("form");
  this.root.className="jform";
  this.root.setAttribute("action","javascript:void(0)");
}

JForm.prototype.addCallback = function(callback, type)
{
  if (typeof type == 'undefined' ) type = "submit";  
  this.root.addEventListener(type,callback,false);
}

JForm.prototype.addControl = function(control)
{
  this.root.appendChild(control.element);
}

JForm.prototype.addElement = function(elem)
{
  this.root.appendChild(elem);
}

JForm.control = function(type,id,nm,data)
{
  switch(type)
  {
  case "input" :
    this.type="input";
    this.element = document.createElement("input");
    this.element.setAttribute("id",id);
    this.element.setAttribute("name",nm);
    if (typeof data == "undefined") data = {};
    if (data.type)
    {
      this.element.setAttribute("type", data.value);
    } else {
      this.element.setAttribute("type", "text");
    }
    if (data.value)
    {
      this.element.setAttribute("value", data.value);
    }
    if (data.disabled)
    {
      this.element.setAttribute("disabled", data.disabled);
    }
    if (data.readonly)
    {
      this.element.setAttribute("readonly", data.readonly);
    }
    if (data.maxlength)
    {
      this.element.setAttribute("maxlength", data.maxlength);
    }
    if (data.callback)
    {
      this.addCallback(data.callback.handler, data.callback.type);
    }
  break;
  case "text" :
    this.type="text";
    this.element = document.createElement("input");
    this.element.setAttribute("type", "text");
    this.element.setAttribute("id",id);
    this.element.setAttribute("name",nm);
    if (typeof data == "undefined") data = {};
    if (data.value)
    {
      this.element.setAttribute("value", data.value);
    }
    if (data.disabled)
    {
      this.element.setAttribute("disabled", data.disabled);
    }
    if (data.readonly)
    {
      this.element.setAttribute("readonly", data.readonly);
    }
    if (data.maxlength)
    {
      this.element.setAttribute("maxlength", data.maxlength);
    }
    if (data.callback)
    {
      this.addCallback(data.callback.handler, data.callback.type);
    }
  break;
  case "password" :
    this.type="password";
    this.element = document.createElement("input");
    this.element.setAttribute("type", "password");
    this.element.setAttribute("id",id);
    this.element.setAttribute("name",nm);
    if (typeof data == "undefined") data = {};
    if (data.value)
    {
      this.element.setAttribute("value", data.value);
    }
    if (data.disabled)
    {
      this.element.setAttribute("disabled", data.disabled);
    }
    if (data.readonly)
    {
      this.element.setAttribute("readonly", data.readonly);
    }
    if (data.maxlength)
    {
      this.element.setAttribute("maxlength", data.maxlength);
    }
    if (data.callback)
    {
      this.addCallback(data.callback.handler, data.callback.type);
    }
  break;
  case "button" :
    this.type="button";
    this.element = document.createElement("input");
    this.element.setAttribute("id",id);
    this.element.setAttribute("name",nm);
    this.element.setAttribute("type", "button");
    if (typeof data == "undefined") data = {};
    if (data.label)
    {
      this.element.setAttribute("value", data.label);
    }
    if (data.disabled)
    {
      this.element.setAttribute("disabled", data.disabled);
    }
    if (data.callback)
    {
      this.addCallback(data.callback.handler, data.callback.type);
    }
  break;
  case "label" :
    this.type="label";
    this.element = document.createElement("label");
    this.element.setAttribute("id",id);
    if (typeof data == "undefined") data = {};
    if (data.label)
    {
      this.element.innerHTML = data.label;
    }
    if (data.boundto)
    {
      this.element.setAttribute("for", data.boundto);
    }
  break;
  case "checkbox" :
    this.type="checkbox";
    this.element = document.createElement("input");
    this.element.setAttribute("id",id);
    this.element.setAttribute("name",nm);
    this.element.setAttribute("type", "checkbox");
    if (typeof data == "undefined") data = {};
    if (data.label)
    {
      this.element.setAttribute("value", data.label);
    }
    if (data.disabled)
    {
      this.element.setAttribute("disabled", data.disabled);
    }
    if (data.checked)
    {
      this.element.setAttribute("checked", data.checked);
    }
    if (data.callback)
    {
      this.addCallback(data.callback.handler, data.callback.type);
    }
  break;
  }
}

JForm.control.prototype.addCallback = function(callback, type)
{
  if (typeof type == 'undefined' )
  {
    switch(this.type)
    {
    case "input" :
      type = "keyup";
    break;
    case "button" :
      type = "click";
    break;
    case "checkbox" :
      type = "change";
    break;
    }
  }
  this.element.addEventListener(type,callback,false);
}

/*
  Javascript Windowing system
*/


var focused = null;

var maxfocus = 100;

var windows = [];

var defaultleft = 20;

var defaulttop = 20;



function JWindow(title, width, height, left, top, resizable)

{

  //styles

  var s = document.createElement('style');

  s.type = 'text/css';

  s.rel = 'stylesheet';

  s.appendChild(document.createTextNode('')); //Safari sometimes borks on null

  document.getElementsByTagName('head')[0].appendChild(s);

  var ss;

  if (s.styleSheet) {ss = s.styleSheet;} //IE

  else {ss = s.sheet;}

  

  ss.insertRule(

    ".jwindow_frame { position:fixed; " +

                     "display:block; " +

                     "background-color:lightblue; " +

                     "border:4px solid DodgerBlue; " +

                     "z-index:99; " +

                     "}"

                     ,0

  );

  ss.insertRule(

    ".jwindow_frame .titlebar { position:absolute; " +

                               "left:0px; " +

                               "top:0px; " +

                               "background-color:DodgerBlue; " +

                               "color:White; " +

                               "cursor:move; " +

                               "height:20px; " +

                               "width:100%; " +

                               "}"

                               ,0

  );

  ss.insertRule(

    ".jwindow_frame .shadebutton { position:absolute; " +

                                   "right:21px; " +

                                   "top:0px; " +

                                   "background-color:yellow; " +

                                   "color:black; " +
                                   "text-align:center; " +
                                   "vertical-align:middle; " +

                                   "cursor:pointer; " +

                                   "height:18px; " +

                                   "width:18px; " +

                                   "}"

                                   ,0

  );

  ss.insertRule(

    ".jwindow_frame .closebutton { position:absolute; " +

                                   "right:0px; " +

                                   "top:0px; " +

                                   "background-color:red; " +

                                   "color:black; " +
                                   "text-align:center; " +
                                   "vertical-align:middle; " +

                                   "cursor:pointer; " +

                                   "height:18px; " +

                                   "width:18px; " +

                                   "}"

                                   ,0

  );

  ss.insertRule(

    ".jwindow_frame .clientarea { position:absolute; " +

                                   "right:0px; " +

                                   "top:20px; " +
                                   "width:100%; " +

                                   "background-color:transparent; " +
                                   "overflow:auto; " +

                                   "}"

                                   ,0

  );  



  

  //default values

  if (typeof width == 'undefined' ) width = 400;

  if (typeof height == 'undefined' ) height = 300;

  if (typeof left == 'undefined' ) left = defaultleft;

  if (typeof top == 'undefined' ) top = defaulttop;

  if (typeof title == 'undefined' ) title = 'Untitled';
  if (typeof resizable == 'undefined' ) resizable = 'true';  


  this.resizable = resizable;

  this.nu = true;

  this.title = title;

  

  this.frameThickness = 4;

  this.dir = "";

  this.state = "inactive";

  this.shaded = false;

  

  this.frame = document.createElement('div');

  this.titlebar = document.createElement('div');

  this.shadebutton = document.createElement('div');

  this.closebutton = document.createElement('div');
  this.clientarea = document.createElement('div');

  

  this.frame.className = 'jwindow_frame';

  this.titlebar.className = 'titlebar';

  this.shadebutton.className = 'shadebutton';

  this.closebutton.className = 'closebutton';
  this.clientarea.className = 'clientarea';

  this.shadebutton.innerHTML = '-';

  this.closebutton.innerHTML = 'x';

  

  this.titlebar.textContent = this.title;

  this.frame.appendChild(this.titlebar);

  this.frame.appendChild(this.shadebutton);

  this.frame.appendChild(this.closebutton);
  this.frame.appendChild(this.clientarea);

  this.closebutton.title = "Close";

  this.shadebutton.title = "Shade";
  this.setWidth(width);

  this.setHeight(height);

  this.setLeft(left);

  this.setTop(top);

  

  var self = this;

  

  this.frame.addEventListener('mousedown',function(e) {self.focus(); /*e.preventDefault();*/ return false;},false);

  this.frame.addEventListener('mousedown',function(e) {self.initRes(e); return false;},false);

  this.titlebar.addEventListener('mousedown',function(e) {self.initMove(e); return false;},false);

  this.shadebutton.addEventListener('mousedown',function(e) {self.shade(e); return false;},false);

  this.closebutton.addEventListener('mousedown',function(e) {if (e.preventDefault) {e.preventDefault();} self.close(); return false;},false);

  

  window.addEventListener('mousemove',function(e) {self.handleEvent(e);},false);

  window.addEventListener('mouseup',function(e) {self.handleEvent(e);},false);

  window.addEventListener('mouseover',function(e) {self.handleEvent(e);},false);

  window.addEventListener('mousedown',function(e) {self.handleEvent(e);},false);

  

  windows.push(this);

  this.focus();

}



JWindow.prototype.display = function()

{

  if (this.nu)

  {

    this.nu = false;

    defaulttop += 32;

    defaultleft += 32;

    if (window.innerHeight != null && defaulttop > window.innerHeight)

    {

      defaulttop = 20;

    }

  }

  document.body.appendChild(this.frame);

}



JWindow.prototype.close = function()

{

  document.body.removeChild(this.frame);

}



JWindow.prototype.setTitle = function(title)

{

  this.title = title;

  this.titlebar.textContent = this.title;

}



JWindow.prototype.setWidth = function(width)

{

  this.width = width;

  this.frame.style.width = this.width + "px";

}



JWindow.prototype.setHeight = function(height)

{

  this.height = height;

  this.frame.style.height = this.height + "px";
  this.clientarea.style.height = (this.height - 20) + "px";

}



JWindow.prototype.setTop = function(top)

{if (typeof title == 'undefined' ) title = 'Untitled';

  this.top = top;

  this.frame.style.top = this.top + "px";

}



JWindow.prototype.setLeft = function(left)

{

  this.left = left;

  this.frame.style.left = this.left + "px";

}

JWindow.prototype.setResizable = function(res)
{
  this.resizable = res;
}



function focussortfunc(a, b)

{

  if (a.frame.style.zIndex < b.frame.style.zIndex)

  {

    return -1;

  } else if (a.frame.style.zIndex > b.frame.style.zIndex)

  {

    return 1;

  } else

  {

    return 0;

  }

}



JWindow.prototype.focus = function()

{

  if (this.frame.style.zIndex != maxfocus)

  {

    this.frame.style.zIndex = ++maxfocus;

  }

  if (maxfocus > 500)

  {

    windows.sort(focussortfunc);

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

    {

      windows[i].frame.style.zIndex = 100+i;

    }

  }

}



JWindow.prototype.shade = function(e)

{

  e.preventDefault();

  if (this.shaded)

  {
    this.setHeight(this.oldH);

    this.shaded = false;

    this.shadebutton.title = "Shade";

  } else {

    this.oldH = this.height;
    this.setHeight(20);

    this.shaded = true;

    this.shadebutton.title = "Unshade";

  }

}



JWindow.prototype.move = function(x,y)

{

  if (x < 0 || y < 0 || x > window.innerWidth || y > window.innerHeight) return;

  this.left = (x - this.moveOffsetX);

  this.top = (y - this.moveOffsetY);

  this.frame.style.left = this.left + "px";

  this.frame.style.top = this.top + "px";

}





JWindow.prototype.resize = function(x,y)

{

  var minsize = 100;

  var newX = this.left;

  var newY = this.top;

  var newH = 0;

  var newW = 0;

  if (this.dir.indexOf("w") != -1)

  {

    newX = x - this.resOffsetX;

    newW = this.resStartX - x;

  } else if (this.dir.indexOf("e") != -1)

  {

    newW = x - this.resStartX;

  }

  if (this.dir.indexOf("n") != -1)

  {

    newY = y - this.resOffsetY;

    newH = this.resStartY - y;

  } else if (this.dir.indexOf("s") != -1)

  {

    newH = y - this.resStartY;

  }

  

  var W = +this.width + newW;

  var H = +this.height + newH;

  

  if (W > minsize)

  {

    this.resStartX = x;
    this.setLeft(newX);

    this.setWidth(W);

  }

  if (H > minsize)

  {

    this.resStartY = y;
    this.setTop(newY)
    this.setHeight(H);

  }

}



JWindow.prototype.initMove = function(e)

{

  if (e.preventDefault) {e.preventDefault();}

  this.moveOffsetX = e.clientX - this.left/*this.frame.offsetLeft*/;

  this.moveOffsetY = e.clientY - this.top/*this.frame.offsetTop*/;

  this.frame.style.opacity = "0.5";

  this.state = "moving";

}



JWindow.prototype.getDirection = function(x,y)

{
  if (!this.resizable) {return ""}

  var xRel = x - this.left/*this.frame.offsetLeft*/;

  var yRel = y - this.top/*this.frame.offsetTop*/;

  var xDir = "";

  var yDir = "";

  

  if (yRel >=0 && xRel >=0 && this.height-yRel+8 > 0 && this.width-xRel+8 > 0)

  {

    if (yRel <= 4) {yDir = "n";}

    if (xRel <= 4) {xDir = "w";}

    if (this.height-yRel+8 <= 4) {yDir="s";}

    if (this.width-xRel+8 <= 4) {xDir="e";}

  }

  if (this.shaded) {yDir = ""};

  return yDir+xDir;

}





JWindow.prototype.initRes = function(e)

{ 

  if (this.dir != "")

  {

    this.state = "resizing";

    this.resOffsetX = e.clientX - this.left/*this.frame.offsetLeft*/;

    this.resOffsetY = e.clientY - this.top/*this.frame.offsetTop*/;

    this.resStartX = e.clientX;

    this.resStartY = e.clientY;

    this.frame.style.opacity = "0.5";
    if (e.preventDefault) {e.preventDefault();}

  }

}





JWindow.prototype.handleEvent = function(e)

{

  //if (e.preventDefault) {e.preventDefault();}

  if (this.state == "inactive")

  {

    this.dir = this.getDirection(e.clientX,e.clientY);

    if (this.dir == "") 
    {
      this.frame.style.cursor="default";
    } else {
      this.frame.style.cursor=this.dir+"-resize";
      if (e.preventDefault) {e.preventDefault();}
    }

  }

  //moving

  if (this.state == "moving" && e.type == "mouseup")

  {

    this.frame.style.opacity = "1";

    this.state = "inactive";
    if (e.preventDefault) {e.preventDefault();}

    return;

  }

  if (this.state == "moving" && e.type == "mousemove")

  {

    this.move(e.clientX, e.clientY);
    if (e.preventDefault) {e.preventDefault();}

    return;

  }

  //resizing

  if (this.state == "resizing" && e.type == "mouseup")

  {

    this.frame.style.opacity = "1";

    this.state = "inactive";

    this.dir = this.getDirection(e.clientX,e.clientY);

    if (this.dir == "") {this.frame.style.cursor="default";}

      else {this.frame.style.cursor=this.dir+"-resize";}
    if (e.preventDefault) {e.preventDefault();}

    return;

  }

  if (this.state == "resizing" && e.type == "mousemove")

  {

    this.resize(e.clientX, e.clientY);
    if (e.preventDefault) {e.preventDefault();}

    return;

  }

}

JWindow.prototype.addElement = function(elem)
{
  this.clientarea.appendChild(elem);
}

JWindow.prototype.removeElement = function(elem)
{
  this.clientarea.removeChild(elem);
}

JWindow.prototype.removeAt = function(position)
{
  this.clientarea.removeChild(this.clientarea.childNodes[position]);
}

JWindow.prototype.insertElement = function(elem, position)
{
  this.clientarea.insertBefore(elem,this.clientarea.childNodes[position]);
}

JWindow.prototype.clear = function()
{
  while (this.content.hasChildNodes())
  {
    this.content.removeChild(this.content.firstChild);
  }
}


/*
  end JWindow
*/


Botswitch = {};
var botswitch_altacc;
var botswitch_wgUserName;

Botswitch.switchacc = function(u,p)
{
  var req = false;
  if (window.XMLHttpRequest) {
    req = new XMLHttpRequest();
  }
  else if (window.ActiveXObject) {
    req = new ActiveXObject("Microsoft.XMLHTTP");
  }
  if (req)
  {
    //log out
    req.open("GET", "http://rationalwiki.com/wiki/index.php?title=Special:Userlogout&action=raw&ctype=text/javascript", false);
    //req.send(null);
    //log in
    req.overrideMimeType('text/xml');
    req.open("POST", "http://rationalwiki.com/wiki/api.php?action=login&lgname=" + encodeURIComponent(u) + "&lgpassword=" + encodeURIComponent(p) + "&format=xml",false);
    req.send(null)
    //errors
    var res = req.responseXML;
    var error = res.evaluate("//login/@result"
                                , res, null, XPathResult.STRING_TYPE, null ).stringValue;
    if (error == "EmptyPass" || error == "WrongPass")
    {
      GM_setValue("botswitch_pass_"+botswitch_altacc,"");
      alert("Wrong password, cookie deleted");
    } else if (error == "NoName" || error == "Illegal" || error == "NotExists")
    {
      alert("Wrong username, did you set botswitch_altacc?")
    } else if (error == "Throttled")
    {
      alert("You've logged in too many times in a short time.");
    } else {
      //success
      if (botswitch_wgUserName != botswitch_altacc)
      {
        var userlink = document.getElementById("pt-userpage");
        var swnotice = document.createElement("li");
        swnotice.id = "pt-switchnotice";
        swnotice.style.textTransform = "none";
        swnotice.innerHTML = " - switched to <a " + "href=" + "'/wiki/User:" + encodeURIComponent(botswitch_altacc) + "' title='My user page'>" + botswitch_altacc + "</a>";
        userlink.parentNode.insertBefore(swnotice,userlink.nextSibling);
        botswitch_altacc = botswitch_wgUserName;
      } else {
        botswitch_altacc = botswitch_altacc_ori;
        var swnotice = document.getElementById("pt-switchnotice");
        if (swnotice)
        {
          swnotice.parentNode.removeChild(swnotice);
        }
      }
    }
  }
}

Botswitch.passOk = function(wind)
{
  var pass = document.getElementById("pass").value;
  var checked = document.getElementById("savepass").checked;
  wind.close();
  if (checked)
  {
    GM_setValue("botswitch_pass_"+botswitch_altacc,pass,30);
  }
  Botswitch.switchacc(botswitch_altacc,pass);
}

Botswitch.askPass = function()
{
  var passwindow = new JWindow();
  passwindow.setWidth(280);
  passwindow.setHeight(140);
  passwindow.setResizable(false);
  passwindow.setTitle("Password");
  passwindow.setLeft(window.innerWidth/2-140/2);
  passwindow.setTop(window.innerHeight/2-280/2);

  var passform = new JForm();
  passform.addControl(new JForm.control("label","nameLabel","nameLabel",{label:"Username: "+botswitch_altacc,boundto:"uname"}));
  passform.addElement(document.createElement("br"));
  passform.addControl(new JForm.control("label","passLabel","passLabel",{label:"Password: ",boundto:"pass"}));
  passform.addControl(new JForm.control("password","pass","pass",{}));
  passform.addElement(document.createElement("br"));
  passform.addControl(new JForm.control("checkbox","savepass","savepass"));
  passform.addControl(new JForm.control("label","saveLabel","saveLabel",{label:" save password",boundto:"savepass"}));
  passform.addElement(document.createElement("br"));
  passform.addControl(new JForm.control("button","passok","passok",{label:"Ok",callback:{handler:function() { Botswitch.passOk(passwindow); }}}));
  passwindow.addElement(passform.root);
  passwindow.display();
}

Botswitch.init = function()
{
  //get pass from cookie
  var pass;
  if ((pass = GM_getValue("botswitch_pass_"+botswitch_altacc,null)) == null || pass == "")
  {
    //no pass set
    Botswitch.askPass();
  } else {
    //renew cookie
    GM_setValue("botswitch_pass_"+botswitch_altacc,pass,30);
    //switch account
    Botswitch.switchacc(botswitch_altacc,pass);
  }
}

Botswitch.insertlink = function()
{
  var logoutlink = document.getElementById("pt-logout");
  if (logoutlink)
  {
    var switchlink = document.createElement("li");
    switchlink.id = "pt-switch";
    var switcha = document.createElement("a");
    switcha.innerHTML = "Switch";
    switcha.title = "Switch";
    switcha.style.cursor = "pointer";
    switcha.addEventListener("click", Botswitch.init, true);
    switchlink.appendChild(switcha);
    logoutlink.parentNode.appendChild(switchlink);
  }
}

function init()
{
  var unameli = document.getElementById("pt-userpage");
  var uname = unameli.firstChild.innerHTML;
  botswitch_wgUserName = uname;
  botswitch_altacc = accounts[uname];
  botswitch_altacc_ori = botswitch_altacc;
  Botswitch.insertlink();
}

window.addEventListener("load", function(e) {
  init();
}, false);
/*]]>*/