<commit_before>function FirefoxDriver(server, id) {
    this.server = server;
    this.context = new Context();
    this.id = id;
    this.mouseSpeed = 1;
}

FirefoxDriver.prototype.get = function(respond, url) {
    var self = this;
    this.context.frameId = "?";

    // Check to see if the given url is the same as the current one, but
    // with a different anchor tag.
    var current = Utils.getBrowser(this.context).contentWindow.location
    var ioService = Utils.getService("@mozilla.org/network/io-service;1", "nsIIOService");
    var currentUri = ioService.newURI(current, "", null);
    var futureUri = ioService.newURI(url, "", currentUri);

    var loadEventExpected = true;

    if (currentUri && futureUri &&
        currentUri.prePath == futureUri.prePath &&
        currentUri.filePath == futureUri.filePath) {
        // Looks like we're at the same url with a ref
        // Being clever and checking the ref was causing me headaches. Brute force for now
        loadEventExpected = futureUri.path.indexOf("#") == -1;
    }

    if (loadEventExpected) {
        new WebLoadingListener(this, function(event) {
            // TODO: Rescue the URI and response code from the event
            var responseText = "";
            respond.context = self.context;
            respond.response = responseText;
            respond.send();
        });
    }

    Utils.getBrowser(this.context).loadURI(url);

    if (!loadEventExpected) {
        respond.context = self.context;
        respond.send();
    }
}

FirefoxDriver.prototype.close = function(respond) {
    // Grab all the references we'll need. Once we call close all this might go away
    var wm = Utils.getService("@mozilla.org/appshell/window-mediator;1", "nsIWindowMediator");
    var appService = Utils.getService("@mozilla.org/toolkit/app-startup;1", "nsIAppStartup");
    var forceQuit = Components.interfaces.nsIAppStartup.eForceQuit;
    var server = this.server;

    var lastWindow;
    var allWindows = wm.getEnumerator("navigator:browser");

    // Here we go!
    try {
        var browser = Utils.getBrowser(this.context);
        browser.contentWindow.close();
    } catch(e) {
        dump(e);
    }

    // If we're on a Mac we might have closed all the windows but not quit, so ensure that we do actually quit :)
    var allWindows = wm.getEnumerator("navigator:browser");
    if (!allWindows.hasMoreElements()) {
        appService.quit(forceQuit);
        return;  // The client should catch the fact that the socket suddenly closes
    }

    // If we're still running, return
    respond.context = this.context;
    respond.send();
}

FirefoxDriver.prototype.executeScript = function(respond, script) {
  var context = this.context;
  var window = Utils.getBrowser(this.context).contentWindow;

  var parameters = [];
  var runScript;
  // Pre 2.0.0.15
  if (window['alert'] && !window.wrappedJSObject) {
    runScript = function(scriptSrc) {
      var document = window.document;

      var __webdriverFunction = eval(script);

      with (window) {
        return __webdriverFunction.apply(window, parameters);
      }
    };
  } else {
    runScript = function(scriptSrc) {
      window = window.wrappedJSObject;
      var sandbox = new Components.utils.Sandbox(window);
      sandbox.window = window;
      sandbox.window.__webdriverParams = parameters;
      sandbox.document = sandbox.window.document;
      sandbox.unsafeWindow = window;
      sandbox.__proto__ = window;

      scriptSrc = "var __webdriverFunc = " + scriptSrc + "; __webdriverFunc.apply(window, __webdriverParams);";
      return Components.utils.evalInSandbox(scriptSrc, sandbox);
    };
  }

  try {
    var scriptSrc = "function(){" + script.shift() + "}";

    var convert = script.shift();
    while (convert && convert.length > 0) {
      var t = convert.shift();

      if (t['type'] == "ELEMENT") {
        t['value'] = Utils.getElementAt(t['value'], context);
      }

      parameters.push(t['value']);
    }

    var result = runScript(scriptSrc, parameters);

    Utils.dumpn("Result is: " + result);

    // Sophisticated.
    if (result && result['tagName']) {
      respond.setField('resultType', "ELEMENT");
      respond.response = Utils.addToKnownElements(result, this.context);
    } else if (result) {
      respond.setField('resultType', "OTHER");
      respond.response = result;
    } else {
      respond.setField('resultType', "NULL");
    }

  } catch (e) {
    respond.isError = true;
    respond.response = e;
  }
  respond.send();
};

FirefoxDriver.prototype.getCurrentUrl = function(respond) {
    respond.context = this.context;
    respond.response = "" + Utils.getBrowser(this.context).contentWindow.location;
    respond.send();
}

FirefoxDriver.prototype.title = function(respond) {
    var browser = Utils.getBrowser(this.context);
    respond.context = this.context;
    respond.response = browser.contentTitle;
    respond.send();
};

FirefoxDriver.prototype.getPageSource = function(respond) {
    var source = Utils.getDocument(this.context).getElementsByTagName("html")[0].innerHTML;

    respond.context = this.context;
    respond.response = "" + source + "";
    respond.send();
};

FirefoxDriver.prototype.selectElementUsingXPath = function(respond, xpath) {
    var doc = Utils.getDocument(this.context);
    var result = doc.evaluate(xpath, doc, null, Components.interfaces.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;

    respond.context = this.context;

    if (result) {
        respond.response = Utils.addToKnownElements(result, this.context);
    } else {
        respond.isError = true;
        respond.response = "Unable to locate element using " + xpath;
    }

    respond.send();
};

FirefoxDriver.prototype.selectElementUsingClassName = function(respond, name) {
    var doc = Utils.getDocument(this.context);

    if (doc["getElementsByClassName"]) {
      var elements = doc.getElementsByClassName(name);
      respond.context = this.context;

      if (elements.length) {
        respond.response = Utils.addToKnownElements(elements[0], this.context);
      } else {
        respond.isError = true;
        respond.response = "Unable to find element with class name '" + name + "'";
      }

      respond.send();
    } else {
      this.selectElementUsingXPath(respond, "//*[contains(concat(' ',normalize-space(@class),' '),' " + name + " ')]");
    }
};

FirefoxDriver.prototype.selectElementsUsingClassName = function(respond, name) {
    var doc = Utils.getDocument(this.context)

    if (doc["getElementsByClassName"]) {
      var result = doc.getElementsByClassName(name);

      var response = "";
      for (var i = 0; i < result.length; i++) {
          var element = result[i];
          var index = Utils.addToKnownElements(element, this.context);
          response += index + ",";
      }
      // Strip the trailing comma
      response = response.substring(0, response.length - 1);

      respond.context = this.context;
      respond.response = response;
      respond.send();
    } else {
      this.selectElementsUsingXPath(respond, "//*[contains(concat(' ',normalize-space(@class),' '),' " + name + " ')]");
    }
};

FirefoxDriver.prototype.selectElementUsingLink = function(respond, linkText) {
    var allLinks = Utils.getDocument(this.context).getElementsByTagName("A");
    var index;
    for (var i = 0; i < allLinks.length && !index; i++) {
        var text = Utils.getText(allLinks[i], true);
        if (linkText == text) {
            index = Utils.addToKnownElements(allLinks[i], this.context);
        }
    }

    respond.context = this.context;

    if (index !== undefined) {
        respond.response = index;
    } else {
        respond.isError = true;
        respond.response = "Unable to find element with link text '" + linkText + "'";
    }

    respond.send();
};

FirefoxDriver.prototype.selectElementById = function(respond, id) {
    var doc = Utils.getDocument(this.context);
    var element = doc.getElementById(id);

    respond.context = this.context;

    if (element) {
        respond.response = Utils.addToKnownElements(element, this.context);
    } else {
        respond.isError = true;
        respond.response = "Unable to find element with id '" + id + "'";
    }

    respond.send();
}

FirefoxDriver.prototype.selectElementsUsingXPath = function(respond, xpath) {
    var doc = Utils.getDocument(this.context)
    var result = doc.evaluate(xpath, doc, null, Components.interfaces.nsIDOMXPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
    var response = "";
    var element = result.iterateNext();
    while (element) {
        var index = Utils.addToKnownElements(element, this.context);
        response += index + ",";
        element = result.iterateNext();
    }
    // Strip the trailing comma
    response = response.substring(0, response.length - 1);

    respond.context = this.context;
    respond.response = response;
    respond.send();
};

FirefoxDriver.prototype.switchToFrame = function(respond, frameId) {
    var browser = Utils.getBrowser(this.context);
    var frameDoc = Utils.findDocumentInFrame(browser, frameId[0]);

    if (frameDoc) {
        this.context = new Context(this.context.windowId, frameId[0]);
        respond.context = this.context.toString();
        respond.send();
    } else {
        respond.isError = true;
        respond.response = "Cannot find frame with id: " + frameId;
        respond.send();
    }
}

FirefoxDriver.prototype.switchToDefaultContent = function(respond) {
    this.context.frameId = "?";
    respond.context = this.context.toString();
    respond.send();
}

FirefoxDriver.prototype.switchToActiveElement = function(respond) {
  var doc = Utils.getDocument(this.context);

  var element;
  if (doc["activeElement"]) {
    dump("Active element is present\n");
    element = doc.activeElement;
  } else {
    var commandDispatcher = Utils.getBrowser(this.context).ownerDocument.commandDispatcher;

    doc = Utils.getDocument(this.context);
    element = commandDispatcher.focusedElement;

    if (element && Utils.getDocument(this.context) != element.ownerDocument)
      element = null;
  }

  // Default to the body
  if (!element) {
    element = Utils.getDocument(this.context).body;
  }

  respond.response = Utils.addToKnownElements(element, this.context);
  respond.send();
};

FirefoxDriver.prototype.goBack = function(respond) {
    var browser = Utils.getBrowser(this.context);

    if (browser.canGoBack) {
      browser.goBack();
    }

    respond.context = this.context;
    respond.send();
}

FirefoxDriver.prototype.goForward = function(respond) {
    var browser = Utils.getBrowser(this.context);

    if (browser.canGoForward) {
      browser.goForward();
    }

    respond.context = this.context;
    respond.send();
}

FirefoxDriver.prototype.addCookie = function(respond, cookieString) {
    var cookie;
    cookie = eval('(' + cookieString[0] + ')');

    if (cookie.expiry) {
        cookie.expiry = new Date(cookie.expiry);
    } else {
        var date = new Date();
        date.setYear(2030);
        cookie.expiry = date;
    }

    cookie.expiry = cookie.expiry.getTime() / 1000; // Stored in seconds

    if (!cookie.domain) {
        var location = Utils.getBrowser(this.context).contentWindow.location
        cookie.domain = location.hostname; // + ":" + location.port;
    }

    var cookieManager = Utils.getService("@mozilla.org/cookiemanager;1", "nsICookieManager2");

    // The signature for "add" is different in firefox 3 and 2. We should sniff the browser version and call the right
    // version of the method, but for now we'll use brute-force.
    try {
      cookieManager.add(cookie.domain, cookie.path, cookie.name, cookie.value, cookie.secure, false, cookie.expiry);
    } catch(e) {
      cookieManager.add(cookie.domain, cookie.path, cookie.name, cookie.value, cookie.secure, false, false, cookie.expiry);
    }

    respond.context = this.context;
    respond.send();
}

FirefoxDriver.prototype.getCookie = function(respond) {
    var cookieManager = Utils.getService("@mozilla.org/cookiemanager;1", "nsICookieManager2");
    var toReturn = "";

    var location = Utils.getBrowser(this.context).contentWindow.location;
    var isForCurrentHost = function(c) {
        try {
            return location.hostname.indexOf(c.host) != -1;
        } catch(e) {
            return false;
        }
    }

    var isForCurrentPath = function(c) {
        try {
        	return location.pathname.indexOf(c.path) != -1;
        } catch(e) {
        	return false;
        }
    }

    var cookieToString = function(c) {
      return c.name + "=" + c.value + ";" + "domain=" + c.host + ";"
          + "path=" + c.path + ";" + "expires=" + c.expires + ";"
          +(c.isSecure ? "secure ;" : "");
    }

    var allCookies = cookieManager.enumerator;

    while (allCookies.hasMoreElements()) {
      var cookie = allCookies.getNext();

      cookie = cookie.QueryInterface(Components.interfaces.nsICookie)
      if (isForCurrentHost(cookie) && isForCurrentPath(cookie)) {
        toReturn += cookieToString(cookie) + "\n";
      }
    }

    respond.context = this.context;
    respond.response = toReturn;
    respond.send();
}

FirefoxDriver.prototype.deleteCookie = function(respond, cookieString) {
    var cookie = eval('(' + cookieString + ')');

    if (!cookie.domain) {
        var location = Utils.getBrowser(this.context).contentWindow.location
        cookie.domain = location.hostname; // + ":" + location.port;
    }

    if (!cookie.path) {
        cookie.path = "/";
    }

    var cookieManager = Utils.getService("@mozilla.org/cookiemanager;1", "nsICookieManager");
    cookieManager.remove(cookie.domain, cookie.name, cookie.path, false);

    respond.context = this.context;
    respond.send();
}

FirefoxDriver.prototype.setMouseSpeed = function(respond, speed) {
    this.mouseSpeed = speed;
    respond.context = this.context;
    respond.send();
};

FirefoxDriver.prototype.getMouseSpeed = function(respond, speed) {
    respond.context = this.context;
    respond.response = "" + this.mouseSpeed;
    respond.send();
};
<commit_msg>SimonStewart: Fixing JS execution on Firefox pre 2.0.0.15<commit_after>function FirefoxDriver(server, id) {
    this.server = server;
    this.context = new Context();
    this.id = id;
    this.mouseSpeed = 1;
}

FirefoxDriver.prototype.get = function(respond, url) {
    var self = this;
    this.context.frameId = "?";

    // Check to see if the given url is the same as the current one, but
    // with a different anchor tag.
    var current = Utils.getBrowser(this.context).contentWindow.location
    var ioService = Utils.getService("@mozilla.org/network/io-service;1", "nsIIOService");
    var currentUri = ioService.newURI(current, "", null);
    var futureUri = ioService.newURI(url, "", currentUri);

    var loadEventExpected = true;

    if (currentUri && futureUri &&
        currentUri.prePath == futureUri.prePath &&
        currentUri.filePath == futureUri.filePath) {
        // Looks like we're at the same url with a ref
        // Being clever and checking the ref was causing me headaches. Brute force for now
        loadEventExpected = futureUri.path.indexOf("#") == -1;
    }

    if (loadEventExpected) {
        new WebLoadingListener(this, function(event) {
            // TODO: Rescue the URI and response code from the event
            var responseText = "";
            respond.context = self.context;
            respond.response = responseText;
            respond.send();
        });
    }

    Utils.getBrowser(this.context).loadURI(url);

    if (!loadEventExpected) {
        respond.context = self.context;
        respond.send();
    }
}

FirefoxDriver.prototype.close = function(respond) {
    // Grab all the references we'll need. Once we call close all this might go away
    var wm = Utils.getService("@mozilla.org/appshell/window-mediator;1", "nsIWindowMediator");
    var appService = Utils.getService("@mozilla.org/toolkit/app-startup;1", "nsIAppStartup");
    var forceQuit = Components.interfaces.nsIAppStartup.eForceQuit;
    var server = this.server;

    var lastWindow;
    var allWindows = wm.getEnumerator("navigator:browser");

    // Here we go!
    try {
        var browser = Utils.getBrowser(this.context);
        browser.contentWindow.close();
    } catch(e) {
        dump(e);
    }

    // If we're on a Mac we might have closed all the windows but not quit, so ensure that we do actually quit :)
    var allWindows = wm.getEnumerator("navigator:browser");
    if (!allWindows.hasMoreElements()) {
        appService.quit(forceQuit);
        return;  // The client should catch the fact that the socket suddenly closes
    }

    // If we're still running, return
    respond.context = this.context;
    respond.send();
}

FirefoxDriver.prototype.executeScript = function(respond, script) {
  var context = this.context;
  var window = Utils.getBrowser(this.context).contentWindow;

  var parameters = [];
  var runScript;
  // Pre 2.0.0.15
  if (window['alert'] && !window.wrappedJSObject) {
    runScript = function(scriptSrc) {
      var document = window.document;
      var __webdriverParams = parameters;

      scriptSrc = "var __webdriverFunc = " + scriptSrc + "; __webdriverFunc.apply(window, __webdriverParams);";
      var __webdriverEval = eval;

      with (window) {
        return __webdriverEval(scriptSrc);
      }
    };
  } else {
    runScript = function(scriptSrc) {
      window = window.wrappedJSObject;
      var sandbox = new Components.utils.Sandbox(window);
      sandbox.window = window;
      sandbox.window.__webdriverParams = parameters;
      sandbox.document = sandbox.window.document;
      sandbox.unsafeWindow = window;
      sandbox.__proto__ = window;

      scriptSrc = "var __webdriverFunc = " + scriptSrc + "; __webdriverFunc.apply(window, __webdriverParams);";
      return Components.utils.evalInSandbox(scriptSrc, sandbox);
    };
  }

  try {
    var scriptSrc = "function(){" + script.shift() + "}";

    var convert = script.shift();
    while (convert && convert.length > 0) {
      var t = convert.shift();

      if (t['type'] == "ELEMENT") {
        t['value'] = Utils.getElementAt(t['value'], context);
      }

      parameters.push(t['value']);
    }

    var result = runScript(scriptSrc, parameters);

    Utils.dumpn("Result is: " + result);

    // Sophisticated.
    if (result && result['tagName']) {
      respond.setField('resultType', "ELEMENT");
      respond.response = Utils.addToKnownElements(result, this.context);
    } else if (result) {
      respond.setField('resultType', "OTHER");
      respond.response = result;
    } else {
      respond.setField('resultType', "NULL");
    }

  } catch (e) {
    respond.isError = true;
    respond.response = e;
  }
  respond.send();
};

FirefoxDriver.prototype.getCurrentUrl = function(respond) {
    respond.context = this.context;
    respond.response = "" + Utils.getBrowser(this.context).contentWindow.location;
    respond.send();
}

FirefoxDriver.prototype.title = function(respond) {
    var browser = Utils.getBrowser(this.context);
    respond.context = this.context;
    respond.response = browser.contentTitle;
    respond.send();
};

FirefoxDriver.prototype.getPageSource = function(respond) {
    var source = Utils.getDocument(this.context).getElementsByTagName("html")[0].innerHTML;

    respond.context = this.context;
    respond.response = "" + source + "";
    respond.send();
};

FirefoxDriver.prototype.selectElementUsingXPath = function(respond, xpath) {
    var doc = Utils.getDocument(this.context);
    var result = doc.evaluate(xpath, doc, null, Components.interfaces.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;

    respond.context = this.context;

    if (result) {
        respond.response = Utils.addToKnownElements(result, this.context);
    } else {
        respond.isError = true;
        respond.response = "Unable to locate element using " + xpath;
    }

    respond.send();
};

FirefoxDriver.prototype.selectElementUsingClassName = function(respond, name) {
    var doc = Utils.getDocument(this.context);

    if (doc["getElementsByClassName"]) {
      var elements = doc.getElementsByClassName(name);
      respond.context = this.context;

      if (elements.length) {
        respond.response = Utils.addToKnownElements(elements[0], this.context);
      } else {
        respond.isError = true;
        respond.response = "Unable to find element with class name '" + name + "'";
      }

      respond.send();
    } else {
      this.selectElementUsingXPath(respond, "//*[contains(concat(' ',normalize-space(@class),' '),' " + name + " ')]");
    }
};

FirefoxDriver.prototype.selectElementsUsingClassName = function(respond, name) {
    var doc = Utils.getDocument(this.context)

    if (doc["getElementsByClassName"]) {
      var result = doc.getElementsByClassName(name);

      var response = "";
      for (var i = 0; i < result.length; i++) {
          var element = result[i];
          var index = Utils.addToKnownElements(element, this.context);
          response += index + ",";
      }
      // Strip the trailing comma
      response = response.substring(0, response.length - 1);

      respond.context = this.context;
      respond.response = response;
      respond.send();
    } else {
      this.selectElementsUsingXPath(respond, "//*[contains(concat(' ',normalize-space(@class),' '),' " + name + " ')]");
    }
};

FirefoxDriver.prototype.selectElementUsingLink = function(respond, linkText) {
    var allLinks = Utils.getDocument(this.context).getElementsByTagName("A");
    var index;
    for (var i = 0; i < allLinks.length && !index; i++) {
        var text = Utils.getText(allLinks[i], true);
        if (linkText == text) {
            index = Utils.addToKnownElements(allLinks[i], this.context);
        }
    }

    respond.context = this.context;

    if (index !== undefined) {
        respond.response = index;
    } else {
        respond.isError = true;
        respond.response = "Unable to find element with link text '" + linkText + "'";
    }

    respond.send();
};

FirefoxDriver.prototype.selectElementById = function(respond, id) {
    var doc = Utils.getDocument(this.context);
    var element = doc.getElementById(id);

    respond.context = this.context;

    if (element) {
        respond.response = Utils.addToKnownElements(element, this.context);
    } else {
        respond.isError = true;
        respond.response = "Unable to find element with id '" + id + "'";
    }

    respond.send();
}

FirefoxDriver.prototype.selectElementsUsingXPath = function(respond, xpath) {
    var doc = Utils.getDocument(this.context)
    var result = doc.evaluate(xpath, doc, null, Components.interfaces.nsIDOMXPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
    var response = "";
    var element = result.iterateNext();
    while (element) {
        var index = Utils.addToKnownElements(element, this.context);
        response += index + ",";
        element = result.iterateNext();
    }
    // Strip the trailing comma
    response = response.substring(0, response.length - 1);

    respond.context = this.context;
    respond.response = response;
    respond.send();
};

FirefoxDriver.prototype.switchToFrame = function(respond, frameId) {
    var browser = Utils.getBrowser(this.context);
    var frameDoc = Utils.findDocumentInFrame(browser, frameId[0]);

    if (frameDoc) {
        this.context = new Context(this.context.windowId, frameId[0]);
        respond.context = this.context.toString();
        respond.send();
    } else {
        respond.isError = true;
        respond.response = "Cannot find frame with id: " + frameId;
        respond.send();
    }
}

FirefoxDriver.prototype.switchToDefaultContent = function(respond) {
    this.context.frameId = "?";
    respond.context = this.context.toString();
    respond.send();
}

FirefoxDriver.prototype.switchToActiveElement = function(respond) {
  var doc = Utils.getDocument(this.context);

  var element;
  if (doc["activeElement"]) {
    dump("Active element is present\n");
    element = doc.activeElement;
  } else {
    var commandDispatcher = Utils.getBrowser(this.context).ownerDocument.commandDispatcher;

    doc = Utils.getDocument(this.context);
    element = commandDispatcher.focusedElement;

    if (element && Utils.getDocument(this.context) != element.ownerDocument)
      element = null;
  }

  // Default to the body
  if (!element) {
    element = Utils.getDocument(this.context).body;
  }

  respond.response = Utils.addToKnownElements(element, this.context);
  respond.send();
};

FirefoxDriver.prototype.goBack = function(respond) {
    var browser = Utils.getBrowser(this.context);

    if (browser.canGoBack) {
      browser.goBack();
    }

    respond.context = this.context;
    respond.send();
}

FirefoxDriver.prototype.goForward = function(respond) {
    var browser = Utils.getBrowser(this.context);

    if (browser.canGoForward) {
      browser.goForward();
    }

    respond.context = this.context;
    respond.send();
}

FirefoxDriver.prototype.addCookie = function(respond, cookieString) {
    var cookie;
    cookie = eval('(' + cookieString[0] + ')');

    if (cookie.expiry) {
        cookie.expiry = new Date(cookie.expiry);
    } else {
        var date = new Date();
        date.setYear(2030);
        cookie.expiry = date;
    }

    cookie.expiry = cookie.expiry.getTime() / 1000; // Stored in seconds

    if (!cookie.domain) {
        var location = Utils.getBrowser(this.context).contentWindow.location
        cookie.domain = location.hostname; // + ":" + location.port;
    }

    var cookieManager = Utils.getService("@mozilla.org/cookiemanager;1", "nsICookieManager2");

    // The signature for "add" is different in firefox 3 and 2. We should sniff the browser version and call the right
    // version of the method, but for now we'll use brute-force.
    try {
      cookieManager.add(cookie.domain, cookie.path, cookie.name, cookie.value, cookie.secure, false, cookie.expiry);
    } catch(e) {
      cookieManager.add(cookie.domain, cookie.path, cookie.name, cookie.value, cookie.secure, false, false, cookie.expiry);
    }

    respond.context = this.context;
    respond.send();
}

FirefoxDriver.prototype.getCookie = function(respond) {
    var cookieManager = Utils.getService("@mozilla.org/cookiemanager;1", "nsICookieManager2");
    var toReturn = "";

    var location = Utils.getBrowser(this.context).contentWindow.location;
    var isForCurrentHost = function(c) {
        try {
            return location.hostname.indexOf(c.host) != -1;
        } catch(e) {
            return false;
        }
    }

    var isForCurrentPath = function(c) {
        try {
        	return location.pathname.indexOf(c.path) != -1;
        } catch(e) {
        	return false;
        }
    }

    var cookieToString = function(c) {
      return c.name + "=" + c.value + ";" + "domain=" + c.host + ";"
          + "path=" + c.path + ";" + "expires=" + c.expires + ";"
          +(c.isSecure ? "secure ;" : "");
    }

    var allCookies = cookieManager.enumerator;

    while (allCookies.hasMoreElements()) {
      var cookie = allCookies.getNext();

      cookie = cookie.QueryInterface(Components.interfaces.nsICookie)
      if (isForCurrentHost(cookie) && isForCurrentPath(cookie)) {
        toReturn += cookieToString(cookie) + "\n";
      }
    }

    respond.context = this.context;
    respond.response = toReturn;
    respond.send();
}

FirefoxDriver.prototype.deleteCookie = function(respond, cookieString) {
    var cookie = eval('(' + cookieString + ')');

    if (!cookie.domain) {
        var location = Utils.getBrowser(this.context).contentWindow.location
        cookie.domain = location.hostname; // + ":" + location.port;
    }

    if (!cookie.path) {
        cookie.path = "/";
    }

    var cookieManager = Utils.getService("@mozilla.org/cookiemanager;1", "nsICookieManager");
    cookieManager.remove(cookie.domain, cookie.name, cookie.path, false);

    respond.context = this.context;
    respond.send();
}

FirefoxDriver.prototype.setMouseSpeed = function(respond, speed) {
    this.mouseSpeed = speed;
    respond.context = this.context;
    respond.send();
};

FirefoxDriver.prototype.getMouseSpeed = function(respond, speed) {
    respond.context = this.context;
    respond.response = "" + this.mouseSpeed;
    respond.send();
};
<|endoftext|>


<commit_before>module.exports = function() {
    // ʽǰʱ
    var fullTime = new Date();
    var year = fullTime.getFullYear();
    var month = fullTime.getMonth() < 9 ? '0' + (parseInt(fullTime.getMonth()) + 1) : parseInt(fullTime.getMonth()) + 1;
    var day = fullTime.getDay() < 10 ? '0' + fullTime.getDay() : fullTime.getDay();
    var hour = fullTime.getHours() < 10 ? "0" + fullTime.getHours() : fullTime.getHours();
    var minute = fullTime.getMinutes() < 10 ? '0' + fullTime.getMinutes() : fullTime.getMinutes();
    var second = fullTime.getSeconds() < 10 ? '0' + fullTime.getSeconds() : fullTime.getSeconds();

    return year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second;
};<commit_msg>修复获取日期错误bug<commit_after>module.exports = function() {
    // ʽǰʱ
    var fullTime = new Date();
    var year = fullTime.getFullYear();
    var month = fullTime.getMonth() < 9 ? '0' + (parseInt(fullTime.getMonth()) + 1) : parseInt(fullTime.getMonth()) + 1;
    var day = fullTime.getDate() < 10 ? '0' + fullTime.getDate() : fullTime.getDate();
    var hour = fullTime.getHours() < 10 ? "0" + fullTime.getHours() : fullTime.getHours();
    var minute = fullTime.getMinutes() < 10 ? '0' + fullTime.getMinutes() : fullTime.getMinutes();
    var second = fullTime.getSeconds() < 10 ? '0' + fullTime.getSeconds() : fullTime.getSeconds();

    return year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second;
};<|endoftext|>


<commit_before>/**
 * Invoked by: EventBridge rule
 *
 * Handles GitHub events that have been forwarded from the webhook endpoint.
 * This function handles the start of the build process for default branches and
 * pull requests (for repositories that are designed to work with CodeBuild).
 * Broadly, it does the following:
 * 1. Check to make sure this event should trigger a build
 * 2. Trigger a build with the necessary details about GitHub repository and
 *    commit for the event as overrides on the build parameters
 *
 * This Lambda should not be considered to be entirely or even mostly
 * responsible for the configuration of CodeBuild environment. It should only
 * worry about the parts of the configuration that result from the events
 * the function is intended to handle.
 */

const https = require('https');
const fs = require('fs');
const AWS = require('aws-sdk');

const codebuild = new AWS.CodeBuild({ apiVersion: '2016-10-06' });
const s3 = new AWS.S3({ apiVersion: '2006-03-01' });

/** @typedef { import('aws-lambda').SNSEvent } SNSEvent */
/** @typedef { import('@octokit/types').Endpoints["GET /repos/{owner}/{repo}"]["response"]["data"] } ReposGetResponseData } */
/** @typedef { import('@octokit/types').Endpoints["GET /repos/{owner}/{repo}/contents/{path}"]["response"]["data"] } ReposGetContentResponseData } */
/** @typedef { import('@octokit/types').Endpoints["GET /repos/{owner}/{repo}/pulls/{pull_number}"]["response"]["data"] } PullsGetResponseData } */

/**
 * @typedef {object} GitHubPushWebhookPayload
 * @property {!string} ref
 * @property {!string} before
 * @property {!string} after
 * @property {!ReposGetResponseData} repository
 */

/**
 * @typedef {object} GitHubPullRequestWebhookPayload
 * @property {!string} action
 * @property {!number} number
 * @property {!ReposGetResponseData} repository
 * @property {!PullsGetResponseData} pull_request
 */

const PR_ACTION_TRIGGERS = [
  'opened',
  'reopened',
  'synchronize',
  'ready_for_review',
];
const USER_AGENT = 'PRX/Infrastructure (github-event-handler)';
const GITHUB_HEADERS = {
  Authorization: `token ${process.env.GITHUB_ACCESS_TOKEN}`,
  Accept: 'application/vnd.github.v3+json',
  'User-Agent': USER_AGENT,
};

/**
 * @param {*} event
 * @returns {event is GitHubPullRequestWebhookPayload}
 */
function eventIsPullRequest(event) {
  if (Object.prototype.hasOwnProperty.call(event, 'pull_request')) {
    return true;
  }

  return false;
}

/**
 * `startBuild` returns a Build object
 * https://docs.aws.amazon.com/codebuild/latest/APIReference/API_Build.html
 * @param {string} ciContentsResponse - The response from the GitHub repository contents API for buildspec.yml
 * @param {GitHubPullRequestWebhookPayload|GitHubPushWebhookPayload} event
 */
async function triggerBuild(ciContentsResponse, event) {
  console.log('Starting CodeBuild run');

  // ciContentsResponse is the JSON body response from a Contents API request
  // to GitHub for a buildspec.yml file in the project that triggered the
  // webhook event. It contains a base 64 encoded string which is the contents
  // of that file.
  /** @type {ReposGetContentResponseData} */
  const ghData = JSON.parse(ciContentsResponse);
  // TODO Not sure why it thinks ghData.content doesn't exist
  // @ts-ignore
  const buildspec = Buffer.from(ghData.content, 'base64').toString('utf8');

  // Only trigger builds for repositories where the buildspec appears to be
  // be designed for use with CI. Look for an `PRX_` string as a test.
  if (!buildspec.includes('PRX_')) {
    console.log('Skipping unsupported buildspec.yml');
    return;
  }

  const commitRef = eventIsPullRequest(event)
    ? event.pull_request.head.sha
    : event.after;

  const environmentVariables = [
    {
      name: 'PRX_REPO',
      value: event.repository.full_name, // e.g. PRX/MyApp
    },
    {
      name: 'PRX_COMMIT',
      value: commitRef,
    },
  ];

  if (eventIsPullRequest(event)) {
    // Pull requests are test-only builds. The pull request number is not
    // used by the build process, but needs to be passed along to the
    // callback for setting the GitHub status.

    event.repository.clone_url;

    const num = event.pull_request.number;
    const title = event.pull_request.title;
    const branch = event.pull_request.head.ref;
    const baseBranch = event.pull_request.base.ref;
    const author = event.pull_request.user.login;
    const action = event.action;
    environmentVariables.push({ name: 'PRX_GITHUB_PR', value: `${num}` });
    environmentVariables.push({ name: 'PRX_GITHUB_PR_TITLE', value: title });
    environmentVariables.push({
      name: 'PRX_GITHUB_PR_BASE_BRANCH',
      value: baseBranch,
    });
    environmentVariables.push({ name: 'PRX_GITHUB_PR_AUTHOR', value: author });
    environmentVariables.push({ name: 'PRX_GITHUB_ACTION', value: action });
    environmentVariables.push({ name: 'PRX_BRANCH', value: branch });
    environmentVariables.push({ name: 'PRX_CI_PUBLISH', value: 'false' });
  } else {
    // All other events should be code pushes to the default branch. These
    // should get tested and published. The buildspec.yml file will contain
    // environment variables that allow the post_build.sh script to
    // determine where and how to handle successful builds (e.g. where to
    // push the code, etc).

    const branch = (event.ref || 'unknown').replace(/^refs\/heads\//, '');
    const before = event.before;
    const after = event.after;
    environmentVariables.push({ name: 'PRX_BRANCH', value: branch });
    environmentVariables.push({ name: 'PRX_CI_PUBLISH', value: 'true' });
    environmentVariables.push({ name: 'PRX_GITHUB_BEFORE', value: before });
    environmentVariables.push({ name: 'PRX_GITHUB_AFTER', value: after });
  }

  await codebuild
    .startBuild({
      projectName: process.env.CODEBUILD_PROJECT_NAME,
      sourceTypeOverride: 'GITHUB',
      sourceLocationOverride: event.repository.clone_url,
      sourceVersion: eventIsPullRequest(event)
        ? `pr/${event.pull_request.number}`
        : event.after,
      buildspecOverride: buildspec,
      environmentVariablesOverride: environmentVariables,
    })
    .promise();

  console.log('CodeBuild started');
}

/**
 * Hits the GitHub repot contents API to determine if the commit that triggered
 * event supports the PRX CI system by looking for a buildspec.yml file
 * https://docs.github.com/en/free-pro-team@latest/rest/reference/repos#contents
 * @param {GitHubPullRequestWebhookPayload|GitHubPushWebhookPayload} event
 * @returns {Promise<string|false>} The JSON response
 */
function getBuildspecContentJson(event) {
  return new Promise((resolve, reject) => {
    console.log('Getting buildspec contents');

    // Get request properties
    const repo = event.repository.full_name;
    const path = 'buildspec.yml';
    const ref = eventIsPullRequest(event)
      ? event.pull_request.head.sha
      : event.after;

    // Setup request options
    const options = {
      host: 'api.github.com',
      path: `/repos/${repo}/contents/${path}?ref=${ref}`,
      method: 'GET',
      headers: GITHUB_HEADERS,
    };

    options.headers['Content-Length'] = Buffer.byteLength('');

    // Request with response handler
    console.log(`Calling contents API: ${options.path}`);
    const req = https.request(options, (res) => {
      res.setEncoding('utf8');

      let json = '';
      res.on('data', (chunk) => {
        console.log(chunk);
        json += chunk;
      });
      res.on('end', () => {
        switch (res.statusCode) {
          case 200:
            console.log('Found CodeBuild support');
            resolve(json);
            break;
          case 404:
            console.log('No CodeBuild support!');
            resolve(false);
            break;
          default:
            console.error(`Request failed ${res.statusCode}!`);
            console.error(json);
            reject(new Error('Contents request failed!'));
        }
      });
    });

    req.setTimeout(1000, () => {
      console.log('========= request timed out');
    });

    // Generic request error handling
    req.on('error', (e) => reject(e));

    req.write('');
    req.end();
  });
}

/**
 *
 * @param {GitHubPullRequestWebhookPayload|GitHubPushWebhookPayload} event
 */
async function handleCiEvent(event) {
  const buildspecContentJson = await getBuildspecContentJson(event);

  if (buildspecContentJson) {
    await triggerBuild(buildspecContentJson, event);

    console.log('Done');
  }
}

/**
 * We'll want to trigger a build when actions on the pull request represent
 * a change that requires CI, such as opening, synchornizing, or moving from
 * draft to ready for review.
 * https://docs.github.com/en/free-pro-team@latest/developers/webhooks-and-events/webhook-events-and-payloads#pull_request
 * @param {GitHubPullRequestWebhookPayload} event
 */
async function handlePullRequestEvent(event) {
  console.log('Handling pull_request event');

  if (PR_ACTION_TRIGGERS.includes(event.action)) {
    console.log(`With action: ${event.action}`);
    await handleCiEvent(event);
  }
}

/**
 * Push events will get delivered for any branch. For pushes to pull requests,
 * there will be an additional `pull_request` event that we will use to trigger
 * the build, so this only needs to proceed if the event is for the default
 * branch.
 * https://docs.github.com/en/free-pro-team@latest/developers/webhooks-and-events/webhook-events-and-payloads#push
 * @param {GitHubPushWebhookPayload} event
 */
async function handlePushEvent(event) {
  console.log('Handling push event');

  if (event.ref === `refs/heads/${event.repository.default_branch}`) {
    console.log('Push event was for default branch');
    await handleCiEvent(event);
  }
}

/**
 * @param {*} event
 * @returns {Promise<void>}
 */
exports.handler = async (event) => {
  console.log(JSON.stringify(event));

  const githubEvent = event['detail-type'];
  const githubEventObj = event.detail;

  switch (githubEvent) {
    case 'push':
      await handlePushEvent(githubEventObj);
      break;
    case 'pull_request':
      await handlePullRequestEvent(githubEventObj);
      break;
    default:
      console.log('Ignoring this event type!');
  }
};
<commit_msg>Build PRs when unlocked<commit_after>/**
 * Invoked by: EventBridge rule
 *
 * Handles GitHub events that have been forwarded from the webhook endpoint.
 * This function handles the start of the build process for default branches and
 * pull requests (for repositories that are designed to work with CodeBuild).
 * Broadly, it does the following:
 * 1. Check to make sure this event should trigger a build
 * 2. Trigger a build with the necessary details about GitHub repository and
 *    commit for the event as overrides on the build parameters
 *
 * This Lambda should not be considered to be entirely or even mostly
 * responsible for the configuration of CodeBuild environment. It should only
 * worry about the parts of the configuration that result from the events
 * the function is intended to handle.
 */

const https = require('https');
const AWS = require('aws-sdk');

const codebuild = new AWS.CodeBuild({ apiVersion: '2016-10-06' });

/** @typedef { import('aws-lambda').SNSEvent } SNSEvent */
/** @typedef { import('@octokit/types').Endpoints["GET /repos/{owner}/{repo}"]["response"]["data"] } ReposGetResponseData } */
/** @typedef { import('@octokit/types').Endpoints["GET /repos/{owner}/{repo}/contents/{path}"]["response"]["data"] } ReposGetContentResponseData } */
/** @typedef { import('@octokit/types').Endpoints["GET /repos/{owner}/{repo}/pulls/{pull_number}"]["response"]["data"] } PullsGetResponseData } */

/**
 * @typedef {object} GitHubPushWebhookPayload
 * @property {!string} ref
 * @property {!string} before
 * @property {!string} after
 * @property {!ReposGetResponseData} repository
 */

/**
 * @typedef {object} GitHubPullRequestWebhookPayload
 * @property {!string} action
 * @property {!number} number
 * @property {!ReposGetResponseData} repository
 * @property {!PullsGetResponseData} pull_request
 */

const PR_ACTION_TRIGGERS = [
  'opened',
  'reopened',
  'synchronize',
  'ready_for_review',
  'unlocked',
];
const USER_AGENT = 'PRX/Infrastructure (github-event-handler)';
const GITHUB_HEADERS = {
  Authorization: `token ${process.env.GITHUB_ACCESS_TOKEN}`,
  Accept: 'application/vnd.github.v3+json',
  'User-Agent': USER_AGENT,
};

/**
 * @param {*} event
 * @returns {event is GitHubPullRequestWebhookPayload}
 */
function eventIsPullRequest(event) {
  if (Object.prototype.hasOwnProperty.call(event, 'pull_request')) {
    return true;
  }

  return false;
}

/**
 * `startBuild` returns a Build object
 * https://docs.aws.amazon.com/codebuild/latest/APIReference/API_Build.html
 * @param {string} ciContentsResponse - The response from the GitHub repository contents API for buildspec.yml
 * @param {GitHubPullRequestWebhookPayload|GitHubPushWebhookPayload} event
 */
async function triggerBuild(ciContentsResponse, event) {
  console.log('Starting CodeBuild run');

  // ciContentsResponse is the JSON body response from a Contents API request
  // to GitHub for a buildspec.yml file in the project that triggered the
  // webhook event. It contains a base 64 encoded string which is the contents
  // of that file.
  /** @type {ReposGetContentResponseData} */
  const ghData = JSON.parse(ciContentsResponse);
  // TODO Not sure why it thinks ghData.content doesn't exist
  // @ts-ignore
  const buildspec = Buffer.from(ghData.content, 'base64').toString('utf8');

  // Only trigger builds for repositories where the buildspec appears to be
  // be designed for use with CI. Look for an `PRX_` string as a test.
  if (!buildspec.includes('PRX_')) {
    console.log('Skipping unsupported buildspec.yml');
    return;
  }

  const commitRef = eventIsPullRequest(event)
    ? event.pull_request.head.sha
    : event.after;

  const environmentVariables = [
    {
      name: 'PRX_REPO',
      value: event.repository.full_name, // e.g. PRX/MyApp
    },
    {
      name: 'PRX_COMMIT',
      value: commitRef,
    },
  ];

  if (eventIsPullRequest(event)) {
    // Pull requests are test-only builds. The pull request number is not
    // used by the build process, but needs to be passed along to the
    // callback for setting the GitHub status.

    event.repository.clone_url;

    const num = event.pull_request.number;
    const title = event.pull_request.title;
    const branch = event.pull_request.head.ref;
    const baseBranch = event.pull_request.base.ref;
    const author = event.pull_request.user.login;
    const action = event.action;
    environmentVariables.push({ name: 'PRX_GITHUB_PR', value: `${num}` });
    environmentVariables.push({ name: 'PRX_GITHUB_PR_TITLE', value: title });
    environmentVariables.push({
      name: 'PRX_GITHUB_PR_BASE_BRANCH',
      value: baseBranch,
    });
    environmentVariables.push({ name: 'PRX_GITHUB_PR_AUTHOR', value: author });
    environmentVariables.push({ name: 'PRX_GITHUB_ACTION', value: action });
    environmentVariables.push({ name: 'PRX_BRANCH', value: branch });
    environmentVariables.push({ name: 'PRX_CI_PUBLISH', value: 'false' });
  } else {
    // All other events should be code pushes to the default branch. These
    // should get tested and published. The buildspec.yml file will contain
    // environment variables that allow the post_build.sh script to
    // determine where and how to handle successful builds (e.g. where to
    // push the code, etc).

    const branch = (event.ref || 'unknown').replace(/^refs\/heads\//, '');
    const before = event.before;
    const after = event.after;
    environmentVariables.push({ name: 'PRX_BRANCH', value: branch });
    environmentVariables.push({ name: 'PRX_CI_PUBLISH', value: 'true' });
    environmentVariables.push({ name: 'PRX_GITHUB_BEFORE', value: before });
    environmentVariables.push({ name: 'PRX_GITHUB_AFTER', value: after });
  }

  await codebuild
    .startBuild({
      projectName: process.env.CODEBUILD_PROJECT_NAME,
      sourceTypeOverride: 'GITHUB',
      sourceLocationOverride: event.repository.clone_url,
      sourceVersion: eventIsPullRequest(event)
        ? `pr/${event.pull_request.number}`
        : event.after,
      buildspecOverride: buildspec,
      environmentVariablesOverride: environmentVariables,
    })
    .promise();

  console.log('CodeBuild started');
}

/**
 * Hits the GitHub repot contents API to determine if the commit that triggered
 * event supports the PRX CI system by looking for a buildspec.yml file
 * https://docs.github.com/en/free-pro-team@latest/rest/reference/repos#contents
 * @param {GitHubPullRequestWebhookPayload|GitHubPushWebhookPayload} event
 * @returns {Promise<string|false>} The JSON response
 */
function getBuildspecContentJson(event) {
  return new Promise((resolve, reject) => {
    console.log('Getting buildspec contents');

    // Get request properties
    const repo = event.repository.full_name;
    const path = 'buildspec.yml';
    const ref = eventIsPullRequest(event)
      ? event.pull_request.head.sha
      : event.after;

    // Setup request options
    const options = {
      host: 'api.github.com',
      path: `/repos/${repo}/contents/${path}?ref=${ref}`,
      method: 'GET',
      headers: GITHUB_HEADERS,
    };

    options.headers['Content-Length'] = Buffer.byteLength('');

    // Request with response handler
    console.log(`Calling contents API: ${options.path}`);
    const req = https.request(options, (res) => {
      res.setEncoding('utf8');

      let json = '';
      res.on('data', (chunk) => {
        console.log(chunk);
        json += chunk;
      });
      res.on('end', () => {
        switch (res.statusCode) {
          case 200:
            console.log('Found CodeBuild support');
            resolve(json);
            break;
          case 404:
            console.log('No CodeBuild support!');
            resolve(false);
            break;
          default:
            console.error(`Request failed ${res.statusCode}!`);
            console.error(json);
            reject(new Error('Contents request failed!'));
        }
      });
    });

    req.setTimeout(1000, () => {
      console.log('========= request timed out');
    });

    // Generic request error handling
    req.on('error', (e) => reject(e));

    req.write('');
    req.end();
  });
}

/**
 *
 * @param {GitHubPullRequestWebhookPayload|GitHubPushWebhookPayload} event
 */
async function handleCiEvent(event) {
  const buildspecContentJson = await getBuildspecContentJson(event);

  if (buildspecContentJson) {
    await triggerBuild(buildspecContentJson, event);

    console.log('Done');
  }
}

/**
 * We'll want to trigger a build when actions on the pull request represent
 * a change that requires CI, such as opening, synchornizing, or moving from
 * draft to ready for review.
 * https://docs.github.com/en/free-pro-team@latest/developers/webhooks-and-events/webhook-events-and-payloads#pull_request
 * @param {GitHubPullRequestWebhookPayload} event
 */
async function handlePullRequestEvent(event) {
  console.log('Handling pull_request event');

  if (PR_ACTION_TRIGGERS.includes(event.action)) {
    console.log(`With action: ${event.action}`);
    await handleCiEvent(event);
  }
}

/**
 * Push events will get delivered for any branch. For pushes to pull requests,
 * there will be an additional `pull_request` event that we will use to trigger
 * the build, so this only needs to proceed if the event is for the default
 * branch.
 * https://docs.github.com/en/free-pro-team@latest/developers/webhooks-and-events/webhook-events-and-payloads#push
 * @param {GitHubPushWebhookPayload} event
 */
async function handlePushEvent(event) {
  console.log('Handling push event');

  if (event.ref === `refs/heads/${event.repository.default_branch}`) {
    console.log('Push event was for default branch');
    await handleCiEvent(event);
  }
}

/**
 * @param {*} event
 * @returns {Promise<void>}
 */
exports.handler = async (event) => {
  console.log(JSON.stringify(event));

  const githubEvent = event['detail-type'];
  const githubEventObj = event.detail;

  switch (githubEvent) {
    case 'push':
      await handlePushEvent(githubEventObj);
      break;
    case 'pull_request':
      await handlePullRequestEvent(githubEventObj);
      break;
    default:
      console.log('Ignoring this event type!');
  }
};
<|endoftext|>


<commit_before>/**
 * Patterns registry - Central registry and scan logic for patterns
 *
 * Copyright 2012-2013 Simplon B.V.
 * Copyright 2012-2013 Florian Friesdorf
 * Copyright 2013 Marko Durkovic
 * Copyright 2013 Rok Garbas
 */

/*
 * changes to previous patterns.register/scan mechanism
 * - if you want initialised class, do it in init
 * - init returns set of elements actually initialised
 * - handle once within init
 * - no turnstile anymore
 * - set pattern.jquery_plugin if you want it
 */
define([
    "jquery",
    "./core/logger",
    "./utils",
    // below here modules that are only loaded
    "./compat"
], function($, logger, utils) {
    var log = logger.getLogger("registry"),
        jquery_plugin = utils.jquery_plugin;

    var registry = {
        patterns: {},
        // as long as the registry is not initialized, pattern
        // registration just registers a pattern. Once init is called,
        // the DOM is scanned. After that registering a new pattern
        // results in rescanning the DOM only for this pattern.
        initialized: false,
        init: function() {
            $(document).ready(function() {
                log.info('loaded: ' + Object.keys(registry.patterns).sort().join(', '));
                registry.scan(document.body);
                registry.initialized = true;
                log.info('finished initial scan.');
            });
        },

        scan: function(content, do_not_catch_init_exception, patterns) {
            var $content = $(content),
                all = [], allsel,
                pattern, $match, plog, name;

            // If no list of patterns was specified, we scan for all
            // patterns
            patterns = patterns || registry.patterns;

            // selector for all patterns
            for (name in patterns) {
                pattern = registry.patterns[name];
                if (pattern.transform)
                    try {
                        pattern.transform($content);
                    } catch (e) {
                        log.critical("Transform error for pattern" + name, e);
                    }
                if (pattern.trigger)
                    all.push(pattern.trigger);
            }
            allsel = all.join(",");

            // Find all elements that belong to any pattern.
            $match = $content.find(allsel);
            if ($content.is(allsel))
                $match = $match.add($content);
            $match = $match.filter(function() { return $(this).parents('pre').length === 0; });
            $match = $match.filter(":not(.cant-touch-this)");

            // walk list backwards and initialize patterns inside-out.
            //
            // XXX: If patterns would only trigger via classes, we
            // could iterate over an element classes and trigger
            // patterns in order.
            //
            // Advantages: Order of pattern initialization controled
            // via order of pat-classes and more efficient.
            $match.toArray().reduceRight(function(acc, el) {
                var $el = $(el);

                for (var name in registry.patterns) {
                    pattern = registry.patterns[name];
                    plog = logger.getLogger("pat." + name);

                    if ($el.is(pattern.trigger)) {
                        plog.debug("Initialising:", $el);
                        try {
                            pattern.init($el);
                            plog.debug("done.");
                        } catch (e) {
                            if (do_not_catch_init_exception) {
                              throw e;
                            } else {
                              plog.error("Caught error:", e);
                            }
                        }
                    }
                }
            }, null);
        },

        // XXX: differentiate between internal and custom patterns
        // _register vs register
        register: function(pattern) {
            if (!pattern.name) {
                log.error("Pattern lacks name:", pattern);
                return false;
            }

            if (registry.patterns[pattern.name]) {
                log.error("Already have a pattern called: " + pattern.name);
                return false;
            }

            // register pattern to be used for scanning new content
            registry.patterns[pattern.name] = pattern;

            // register pattern as jquery plugin
            if (pattern.jquery_plugin) {
                var pluginName = ("pat-" + pattern.name)
                        .replace(/-([a-zA-Z])/g, function(match, p1) {
                            return p1.toUpperCase();
                        });
                $.fn[pluginName] = jquery_plugin(pattern);
                // BBB 2012-12-10
                $.fn[pluginName.replace(/^pat/, "pattern")] = jquery_plugin(pattern);
            }

            log.debug("Registered pattern:", pattern.name, pattern);

            if (registry.initialized) {
                registry.scan(document.body, false, [pattern.name]);
            }
            return true;
        }
    };

    $(document) .on("patterns-injected.patterns", function(ev) {
        registry.scan(ev.target);
        $(ev.target).trigger("patterns-injected-scanned");
    });

    return registry;
});
// jshint indent: 4, browser: true, jquery: true, quotmark: double
// vim: sw=4 expandtab
<commit_msg>fix scan for specific scans<commit_after>/**
 * Patterns registry - Central registry and scan logic for patterns
 *
 * Copyright 2012-2013 Simplon B.V.
 * Copyright 2012-2013 Florian Friesdorf
 * Copyright 2013 Marko Durkovic
 * Copyright 2013 Rok Garbas
 */

/*
 * changes to previous patterns.register/scan mechanism
 * - if you want initialised class, do it in init
 * - init returns set of elements actually initialised
 * - handle once within init
 * - no turnstile anymore
 * - set pattern.jquery_plugin if you want it
 */
define([
    "jquery",
    "./core/logger",
    "./utils",
    // below here modules that are only loaded
    "./compat"
], function($, logger, utils) {
    var log = logger.getLogger("registry"),
        jquery_plugin = utils.jquery_plugin;

    var registry = {
        patterns: {},
        // as long as the registry is not initialized, pattern
        // registration just registers a pattern. Once init is called,
        // the DOM is scanned. After that registering a new pattern
        // results in rescanning the DOM only for this pattern.
        initialized: false,
        init: function() {
            $(document).ready(function() {
                log.info('loaded: ' + Object.keys(registry.patterns).sort().join(', '));
                registry.scan(document.body);
                registry.initialized = true;
                log.info('finished initial scan.');
            });
        },

        scan: function(content, do_not_catch_init_exception, patterns) {
            var $content = $(content),
                all = [], allsel,
                pattern, $match, plog, name;

            // If no list of patterns was specified, we scan for all
            // patterns
            patterns = patterns || Object.keys(registry.patterns);

            // selector for all patterns
            patterns.forEach(function(name) {
                pattern = registry.patterns[name];
                if (pattern.transform)
                    try {
                        pattern.transform($content);
                    } catch (e) {
                        log.critical("Transform error for pattern" + name, e);
                    }
                if (pattern.trigger)
                    all.push(pattern.trigger);
            });
            allsel = all.join(",");

            // Find all elements that belong to any pattern.
            $match = $content.find(allsel);
            if ($content.is(allsel))
                $match = $match.add($content);
            $match = $match.filter(function() { return $(this).parents('pre').length === 0; });
            $match = $match.filter(":not(.cant-touch-this)");

            // walk list backwards and initialize patterns inside-out.
            //
            // XXX: If patterns would only trigger via classes, we
            // could iterate over an element classes and trigger
            // patterns in order.
            //
            // Advantages: Order of pattern initialization controled
            // via order of pat-classes and more efficient.
            $match.toArray().reduceRight(function(acc, el) {
                var $el = $(el);

                for (var name in registry.patterns) {
                    pattern = registry.patterns[name];
                    plog = logger.getLogger("pat." + name);

                    if ($el.is(pattern.trigger)) {
                        plog.debug("Initialising:", $el);
                        try {
                            pattern.init($el);
                            plog.debug("done.");
                        } catch (e) {
                            if (do_not_catch_init_exception) {
                              throw e;
                            } else {
                              plog.error("Caught error:", e);
                            }
                        }
                    }
                }
            }, null);
        },

        // XXX: differentiate between internal and custom patterns
        // _register vs register
        register: function(pattern) {
            if (!pattern.name) {
                log.error("Pattern lacks name:", pattern);
                return false;
            }

            if (registry.patterns[pattern.name]) {
                log.error("Already have a pattern called: " + pattern.name);
                return false;
            }

            // register pattern to be used for scanning new content
            registry.patterns[pattern.name] = pattern;

            // register pattern as jquery plugin
            if (pattern.jquery_plugin) {
                var pluginName = ("pat-" + pattern.name)
                        .replace(/-([a-zA-Z])/g, function(match, p1) {
                            return p1.toUpperCase();
                        });
                $.fn[pluginName] = jquery_plugin(pattern);
                // BBB 2012-12-10
                $.fn[pluginName.replace(/^pat/, "pattern")] = jquery_plugin(pattern);
            }

            log.debug("Registered pattern:", pattern.name, pattern);

            if (registry.initialized) {
                registry.scan(document.body, false, [pattern.name]);
            }
            return true;
        }
    };

    $(document) .on("patterns-injected.patterns", function(ev) {
        registry.scan(ev.target);
        $(ev.target).trigger("patterns-injected-scanned");
    });

    return registry;
});
// jshint indent: 4, browser: true, jquery: true, quotmark: double
// vim: sw=4 expandtab
<|endoftext|>


<commit_before>//Load modules
const pgp = require("pg-promise")();
const LiskAPI = require("./LiskAPI.js");

//Config and helpers
const config = require('../config.json');
const { lskAsBeddows, beddowsAsLsk, log, voteCheck, getLocalVoteWeight, clearVoteList } = require('./helpers');

class Pool {
	//Constructor
	constructor(){
		//Connet to PostgesDB
		this.db = pgp("postgres://"+config.db.dbuser+":"+config.db.dbpass+"@"+config.db.dbhost+":"+config.db.dbport+"/"+config.db.dbname);

		//Static data
		this.address = config.pool.delegateAddress;
		this.poolFees = config.pool.poolfees;
		this.poolFeesPayout = config.payouts.poolfees;
		this.minVote = config.pool.minVote;
		this.maxVote = config.pool.maxVote;
		this.showMore = config.pool.showmore;
		this.poolname = config.pool.name;
		this.network = config.blockchain.network;
		this.payTime = config.pool.paytime;
		this.payMin = config.payouts.minpay;

		//Dunamic data
		this.votesCount = 0;

		//Loger
		this.loger = log;

		//API
		this.api = new LiskAPI(config);

		//Init
		this.Init();
	}

	//Init
	Init(){
		if(this.address){
			this.api.getAccInfo()
			.then(res => {
				//Get delegate data
				this.name = res.username;
				this.balance = Number(res.balance);
				this.rank = res.rank;
				this.selfVote = Number(res.selfVote);
				this.totalVote = Number(res.totalVote);
				this.lastForgedHeight = res.lastForgedHeight;

				//Load stats
				this.updPoolFees();
				this.updVoters();

				//Start processing
				this.processing();
			})
			.catch(error => {
				this.loger("ERR", error);
			});
		} else {
			this.loger("ERR", "Check 'config.json' delegate address not set");
		}
	}

	//Pool data processing
	processing(){
		setInterval(() => {
			this.api.getAccInfo()
			.then(res => {
				this.balance = Number(res.balance);
				this.rank = res.rank;
				this.selfVote = Number(res.selfVote);
				this.totalVote = Number(res.totalVote);

				this.distributeReward();
				this.updPoolStat();
				this.updVoters();
				this.updVotersStats();
			});
		}, 60000);
	}

	//Distribute reward for all voters and pool
	distributeReward(){
		this.api.getLastForgedHeight()
		.then(block => {
			if(this.lastForgedHeight < block.height){
				const reward = Number(block.reward);
				const poolReward = Math.round(reward / 100 * this.poolFees);
				const votersReward = reward - poolReward;
				this.lastForgedHeight = block.height;

				//Voters update balance
				this.db.any("SELECT * FROM voters")
				.then(rdata => {
					let updData = [];

					if(rdata.length){
						for(var i = 0; i < rdata.length; i++){
							var bal = Number(rdata[i].balance) + Number(Math.round(votersReward / 100 * rdata[i].poolpercent)),
									total = Number(rdata[i].total) + Number(Math.round(votersReward / 100 * rdata[i].poolpercent));

							updData.push({
								'id': rdata[i].id,
								'balance': bal,
								'total': total
							});
						}

						if(updData.length){
							this.db.result(pgp.helpers.update(updData, ['?id', 'balance', 'total'], 'voters') + ' WHERE v.id = t.id')
							.then(rdata => {
								this.loger("INF", "Pool forged a new block! Height: "+block.height+" | Voter's reward: "+beddowsAsLsk(votersReward));
							})
							.catch(error => {
								this.loger("ERR", error.message || error);
							});
						}
					}
				})
				.catch(error => {
					this.loger("ERR", error.message || error);
				});

				//Pool update balance
				this.db.any("SELECT * FROM poolfees")
				.then(rdata => {
					var updData = [];

					if(rdata.length){
						for(var i = 0; i < rdata.length; i++){
							var bal = Number(rdata[i].balance) + Number(Math.round(poolReward / 100 * rdata[i].percent));

							updData.push({
								'id': rdata[i].id,
								'balance': bal
							});
						}

						if(updData.length){
							this.db.result(pgp.helpers.update(updData, ['?id', 'balance'], 'poolfees') + ' WHERE v.id = t.id')
							.then(rdata => {
								this.loger("INF", "Pool forged a new block! Height: "+block.height+" | Pool reward: "+beddowsAsLsk(poolReward));
							})
							.catch(error => {
								this.loger("ERR", error.message || error);
							});
						}
					} else {
						this.loger("WAR", "Account for payouts poolfees not set!");
					}
				})
				.catch(error => {
					this.loger("ERR", error.message || error);
				});
			} else {
				this.loger("INF", "No new block. Height: "+block.height);
			}
		})
		.catch(error => {
			this.loger("ERR", error.message);
		});
	}

	//##POOL##//
	//Update pool fees payouts
	updPoolFees(){
		const poolfeesList = this.poolFeesPayout;
		let addAddrs = [];
		let oldBalance = 0;

		if(poolfeesList.length){
			//Get full fees balance from old addresses
			this.db.any("SELECT sum(balance) as total FROM poolfees")
			.then(rdata => {
				//If not old balanses
				if(rdata[0].total !== NaN && rdata[0].total !== undefined){
					oldBalance = Number(rdata[0].total);
				}

				//Remove old addresses
				this.db.result('DELETE FROM poolfees')
				.then(rdata => {
					//Load poolfees addresses from config
					for(let i=0; i<poolfeesList.length; i++){
						if(poolfeesList[i].address && Number(poolfeesList[i].percent)>0){
							addAddrs.push({
								'address': poolfeesList[i].address,
								'balance': Number(oldBalance * poolfeesList[i].percent / 100),
								'percent': poolfeesList[i].percent
							});
						}
					}

					//Update poolfees table
					if(addAddrs.length){
						this.db.result(pgp.helpers.insert(addAddrs, ['address', 'balance', 'percent'], 'poolfees'))
						.then(rdata => {
							this.loger("INF", "Add/Change fee addresses.");
						})
						.catch(error => {
							this.loger("ERR", error.message || error);
						});
					} else {
						this.loger("WAR", "Poolfees address set not correct in config. Missed 'address' or 'percent'!");
					}
				});
			})
			.catch(error => {
				this.loger("ERR", error.message || error);
			});
		} else {
			this.loger("WAR", "Poolfees address not set in config!");
		}
	}
	//Update pool statistic
	updPoolStat(){
		if(this.votesCount){
			const pStats = {
				"rank": this.rank,
				"balance": this.balance,
				"vcount": this.votesCount,
				"total_vote": this.totalVote,
				"self_vote": this.selfVote,
				"timestamp": Date.now()
			};

			//Update pool statistics history
			this.db.result(pgp.helpers.insert(pStats, null, 'pool_history'))
			.then(rdata => {
				this.loger("INF", "Updating pool statistics.");
			})
			.catch(error => {
				this.loger("ERR", "Update pool statistics error: "+error.message || error);
			});
		}
	}

	//##VOTERS##//
	//Update voters list
	updVoters(){
		let addVoters = [];
		let updVoters = [];
		let delVoters = [];

		this.api.getVotesList()
		.then(res => {
			const clrVoteList = clearVoteList(res);
			const voteWeight = getLocalVoteWeight(clrVoteList);

			this.db.any("SELECT * FROM voters")
			.then(rdata => {
				this.votesCount = rdata.length;

				if(clrVoteList.length){
					if(rdata.length){
						let dbVoteList = [];
						//Remove unvoted
						for(var i=0; i < rdata.length; i++){
							let find = clrVoteList.filter(x => x.address === rdata[i].address);
							if(find.length){
								dbVoteList.push(rdata[i]);
							} else {
								delVoters.push("DELETE FROM voters WHERE id="+rdata[i].id);
								this.votesCount--;
							}
						}

						for(var i=0; i < clrVoteList.length; i++){
							//Check if vote exist db or not
							let find = dbVoteList.filter(x => x.address === clrVoteList[i].address);

							if(find.length){;
								if(voteCheck(clrVoteList[i])){
									//Update voter data
									updVoters.push({
										"address": clrVoteList[i].address,
										"vote": Number(clrVoteList[i].amount),
										"username": clrVoteList[i].username,
										"poolpercent": parseFloat((clrVoteList[i].amount / voteWeight * 100).toFixed(2)),
									});
								} else {
									//Remove voter
									delVoters.push("DELETE FROM voters WHERE id="+find[0].id);
									this.votesCount--;
								}
							} else {
								if(voteCheck(clrVoteList[i])){
									addVoters.push({
										'address': clrVoteList[i].address,
										'username': clrVoteList[i].username,
										'balance': Number(0),
										'total': Number(0),
										'vote': Number(clrVoteList[i].amount),
										'poolpercent': parseFloat((clrVoteList[i].amount / voteWeight * 100).toFixed(2)),
										'active': true,
										'status': 0
									});
									this.votesCount++
								}
							}
						}
					} else {
						//First start, add all voters
						for(var i = 0; i < clrVoteList.length; i++){
							if(voteCheck(clrVoteList[i])){
								addVoters.push({
									'address': clrVoteList[i].address,
									'username': clrVoteList[i].username,
									'balance': Number(0),
									'total': Number(0),
									'vote': Number(clrVoteList[i].amount),
									'poolpercent': parseFloat((clrVoteList[i].amount / voteWeight * 100).toFixed(2)),
									'active': true,
									'status': 0,
								});

								this.votesCount++;
							}
						}
					}

					//Update voters
					if(updVoters.length){
						this.db.result(pgp.helpers.update(updVoters, ['?address', 'username', 'vote', 'poolpercent'], 'voters') + ' WHERE v.address = t.address')
						.then(rdata => {
							this.loger("INF", "Updating voter's data.");
						})
						.catch(error => {
							this.loger("ERR", "Update voters error: "+error.message || error);
						});
					}

					//Add voters
					if(addVoters.length){
						this.db.result(pgp.helpers.insert(addVoters, ['address', 'username','balance', 'total', 'vote', 'poolpercent', 'active', 'status'], 'voters'))
						.then(rdata => {
							this.loger("INF", "Adding new voter.");
						})
						.catch(error => {
							this.loger("ERR", "Adding voters error: "+error.message || error);
						});
					}

					//Remove unvoted
					if(delVoters.length){
						this.db.result(pgp.helpers.concat(delVoters))
						.then(rdata => {
							this.loger("INF", "Remove inappropriate votes.");
						})
						.catch(error => {
							this.loger("ERR", "Remove voters error: "+error.message || error);
						});
					}
				}
			})
			.catch(error => {
				this.loger("ERR", error.message || error);
			});
		})
		.catch(error => {
			this.loger("ERR", error);
		});
	}
	//Update voters statistic
	updVotersStats(){
		this.db.any("SELECT * FROM voters")
		.then(rdata => {
			let vbHist = [];

			if(rdata.length){
				for(let i = 0; i < rdata.length; i++){
					vbHist.push({
						'voter_id': rdata[i].id,
						'balance': Number(rdata[i].balance),
						'timestamp': Date.now()
					});
				}

				this.db.result(pgp.helpers.insert(vbHist, ['voter_id', 'balance', 'timestamp'], 'balance_history'))
				.then(rdata => {
					this.loger("INF", "Updating voter's balance history");
				})
				.catch(error => {
					this.loger("ERR", error.message || error);
				});
			}
		})
		.catch(error => {
			this.loger("ERR", error.message || error);
		});
	}
}

module.exports = new Pool;<commit_msg>Temporary FIX. Reset statistics.<commit_after>//Load modules
const pgp = require("pg-promise")();
const LiskAPI = require("./LiskAPI.js");

//Config and helpers
const config = require('../config.json');
const { lskAsBeddows, beddowsAsLsk, log, voteCheck, getLocalVoteWeight, clearVoteList } = require('./helpers');

class Pool {
	//Constructor
	constructor(){
		//Connet to PostgesDB
		this.db = pgp("postgres://"+config.db.dbuser+":"+config.db.dbpass+"@"+config.db.dbhost+":"+config.db.dbport+"/"+config.db.dbname);

		//Static data
		this.address = config.pool.delegateAddress;
		this.poolFees = config.pool.poolfees;
		this.poolFeesPayout = config.payouts.poolfees;
		this.minVote = config.pool.minVote;
		this.maxVote = config.pool.maxVote;
		this.showMore = config.pool.showmore;
		this.poolname = config.pool.name;
		this.network = config.blockchain.network;
		this.payTime = config.pool.paytime;
		this.payMin = config.payouts.minpay;

		//Dunamic data
		this.votesCount = 0;

		//Loger
		this.loger = log;

		//API
		this.api = new LiskAPI(config);

		//Init
		this.Init();
	}

	//Init
	Init(){
		if(this.address){
			this.api.getAccInfo()
			.then(res => {
				//Get delegate data
				this.name = res.username;
				this.balance = Number(res.balance);
				this.rank = res.rank;
				this.selfVote = Number(res.selfVote);
				this.totalVote = Number(res.totalVote);
				this.lastForgedHeight = res.lastForgedHeight;

				//Load stats
				this.updPoolFees();
				this.updVoters();

				//Start processing
				this.processing();
			})
			.catch(error => {
				this.loger("ERR", error);
			});
		} else {
			this.loger("ERR", "Check 'config.json' delegate address not set");
		}
	}

	//Pool data processing
	processing(){
		setInterval(() => {
			this.api.getAccInfo()
			.then(res => {
				this.balance = Number(res.balance);
				this.rank = res.rank;
				this.selfVote = Number(res.selfVote);
				this.totalVote = Number(res.totalVote);

				this.distributeReward();
				this.updPoolStat();
				this.updVoters();
				this.updVotersStats();
			});
		}, 60000);
	}

	//Distribute reward for all voters and pool
	distributeReward(){
		this.api.getLastForgedHeight()
		.then(block => {
			if(this.lastForgedHeight < block.height){
				const reward = Number(block.reward);
				const poolReward = Math.round(reward / 100 * this.poolFees);
				const votersReward = reward - poolReward;
				this.lastForgedHeight = block.height;

				//Voters update balance
				this.db.any("SELECT * FROM voters")
				.then(rdata => {
					let updData = [];

					if(rdata.length){
						for(var i = 0; i < rdata.length; i++){
							var bal = Number(rdata[i].balance) + Number(Math.round(votersReward / 100 * rdata[i].poolpercent)),
									total = Number(rdata[i].total) + Number(Math.round(votersReward / 100 * rdata[i].poolpercent));

							updData.push({
								'id': rdata[i].id,
								'balance': bal,
								'total': total
							});
						}

						if(updData.length){
							this.db.result(pgp.helpers.update(updData, ['?id', 'balance', 'total'], 'voters') + ' WHERE v.id = t.id')
							.then(rdata => {
								this.loger("INF", "Pool forged a new block! Height: "+block.height+" | Voter's reward: "+beddowsAsLsk(votersReward));
							})
							.catch(error => {
								this.loger("ERR", error.message || error);
							});
						}
					}
				})
				.catch(error => {
					this.loger("ERR", error.message || error);
				});

				//Pool update balance
				this.db.any("SELECT * FROM poolfees")
				.then(rdata => {
					var updData = [];

					if(rdata.length){
						for(var i = 0; i < rdata.length; i++){
							var bal = Number(rdata[i].balance) + Number(Math.round(poolReward / 100 * rdata[i].percent));

							updData.push({
								'id': rdata[i].id,
								'balance': bal
							});
						}

						if(updData.length){
							this.db.result(pgp.helpers.update(updData, ['?id', 'balance'], 'poolfees') + ' WHERE v.id = t.id')
							.then(rdata => {
								this.loger("INF", "Pool forged a new block! Height: "+block.height+" | Pool reward: "+beddowsAsLsk(poolReward));
							})
							.catch(error => {
								this.loger("ERR", error.message || error);
							});
						}
					} else {
						this.loger("WAR", "Account for payouts poolfees not set!");
					}
				})
				.catch(error => {
					this.loger("ERR", error.message || error);
				});
			} else {
				this.loger("INF", "No new block. Height: "+block.height);
			}
		})
		.catch(error => {
			this.loger("ERR", error.message);
		});
	}

	//##POOL##//
	//Update pool fees payouts
	updPoolFees(){
		const poolfeesList = this.poolFeesPayout;
		let addAddrs = [];
		let oldBalance = 0;

		if(poolfeesList.length){
			//Get full fees balance from old addresses
			this.db.any("SELECT sum(balance) as total FROM poolfees")
			.then(rdata => {
				//If not old balanses
				if(rdata[0].total !== NaN && rdata[0].total !== undefined){
					oldBalance = Number(rdata[0].total);
				}

				//Remove old addresses
				this.db.result('DELETE FROM poolfees')
				.then(rdata => {
					//Load poolfees addresses from config
					for(let i=0; i<poolfeesList.length; i++){
						if(poolfeesList[i].address && Number(poolfeesList[i].percent)>0){
							addAddrs.push({
								'address': poolfeesList[i].address,
								'balance': Number(oldBalance * poolfeesList[i].percent / 100),
								'percent': poolfeesList[i].percent
							});
						}
					}

					//Update poolfees table
					if(addAddrs.length){
						this.db.result(pgp.helpers.insert(addAddrs, ['address', 'balance', 'percent'], 'poolfees'))
						.then(rdata => {
							this.loger("INF", "Add/Change fee addresses.");
						})
						.catch(error => {
							this.loger("ERR", error.message || error);
						});
					} else {
						this.loger("WAR", "Poolfees address set not correct in config. Missed 'address' or 'percent'!");
					}
				});
			})
			.catch(error => {
				this.loger("ERR", error.message || error);
			});
		} else {
			this.loger("WAR", "Poolfees address not set in config!");
		}
	}
	//Update pool statistic
	updPoolStat(){
		if(this.votesCount){
			const pStats = {
				"rank": this.rank,
				"balance": this.balance,
				"vcount": this.votesCount,
				"total_vote": this.totalVote,
				"self_vote": this.selfVote,
				"timestamp": Date.now()
			};

			//Update pool statistics history
			this.db.result(pgp.helpers.insert(pStats, null, 'pool_history'))
			.then(rdata => {
				this.loger("INF", "Updating pool statistics.");
			})
			.catch(error => {
				this.loger("ERR", "Update pool statistics error: "+error.message || error);
			});
		}
	}

	//##VOTERS##//
	//Update voters list
	updVoters(){
		let addVoters = [];
		let updVoters = [];
		let delVoters = [];

		this.api.getVotesList()
		.then(res => {
			const clrVoteList = clearVoteList(res);
			const voteWeight = getLocalVoteWeight(clrVoteList);

			this.db.any("SELECT * FROM voters")
			.then(rdata => {
				this.votesCount = rdata.length;

				if(clrVoteList.length){
					if(rdata.length){
						let dbVoteList = [];
						//Remove unvoted
						for(var i=0; i < rdata.length; i++){
							let find = clrVoteList.filter(x => x.address === rdata[i].address);
							if(find.length){
								dbVoteList.push(rdata[i]);
							} else {
								delVoters.push("DELETE FROM voters WHERE id="+rdata[i].id);
								this.votesCount--;
							}
						}

						for(var i=0; i < clrVoteList.length; i++){
							//Check if vote exist db or not
							let find = dbVoteList.filter(x => x.address === clrVoteList[i].address);

							if(find.length){;
								if(voteCheck(clrVoteList[i])){
									//Update voter data
									updVoters.push({
										"address": clrVoteList[i].address,
										"vote": Number(clrVoteList[i].amount),
										"username": clrVoteList[i].username,
										"poolpercent": parseFloat((clrVoteList[i].amount / voteWeight * 100).toFixed(2)),
									});
								} else {
									//Remove voter
									delVoters.push("DELETE FROM voters WHERE id="+find[0].id);
									this.votesCount--;
								}
							} else {
								if(voteCheck(clrVoteList[i])){
									addVoters.push({
										'address': clrVoteList[i].address,
										'username': clrVoteList[i].username,
										'balance': Number(0),
										'total': Number(0),
										'vote': Number(clrVoteList[i].amount),
										'poolpercent': parseFloat((clrVoteList[i].amount / voteWeight * 100).toFixed(2)),
										'active': true,
										'status': 0
									});
									this.votesCount++
								}
							}
						}
					} else {
						//First start, add all voters
						for(var i = 0; i < clrVoteList.length; i++){
							if(voteCheck(clrVoteList[i])){
								addVoters.push({
									'address': clrVoteList[i].address,
									'username': clrVoteList[i].username,
									'balance': Number(0),
									'total': Number(0),
									'vote': Number(clrVoteList[i].amount),
									'poolpercent': parseFloat((clrVoteList[i].amount / voteWeight * 100).toFixed(2)),
									'active': true,
									'status': 0,
								});

								this.votesCount++;
							}
						}
					}

					//Update voters
					if(updVoters.length){
						this.db.result(pgp.helpers.update(updVoters, ['?address', 'username', 'vote', 'poolpercent'], 'voters') + ' WHERE v.address = t.address')
						.then(rdata => {
							this.loger("INF", "Updating voter's data.");
						})
						.catch(error => {
							this.loger("ERR", "Update voters error: "+error.message || error);
						});
					}

					//Add voters
					if(addVoters.length){
						this.db.result(pgp.helpers.insert(addVoters, ['address', 'username','balance', 'total', 'vote', 'poolpercent', 'active', 'status'], 'voters'))
						.then(rdata => {
							this.loger("INF", "Adding new voter.");
						})
						.catch(error => {
							this.loger("ERR", "Adding voters error: "+error.message || error);
						});
					}

					//Remove unvoted
					if(delVoters.length && delVoters.length < 3){
						this.db.result(pgp.helpers.concat(delVoters))
						.then(rdata => {
							this.loger("INF", "Remove inappropriate votes.");
						})
						.catch(error => {
							this.loger("ERR", "Remove voters error: "+error.message || error);
						});
					}
				}
			})
			.catch(error => {
				this.loger("ERR", error.message || error);
			});
		})
		.catch(error => {
			this.loger("ERR", error);
		});
	}
	//Update voters statistic
	updVotersStats(){
		this.db.any("SELECT * FROM voters")
		.then(rdata => {
			let vbHist = [];

			if(rdata.length){
				for(let i = 0; i < rdata.length; i++){
					vbHist.push({
						'voter_id': rdata[i].id,
						'balance': Number(rdata[i].balance),
						'timestamp': Date.now()
					});
				}

				this.db.result(pgp.helpers.insert(vbHist, ['voter_id', 'balance', 'timestamp'], 'balance_history'))
				.then(rdata => {
					this.loger("INF", "Updating voter's balance history");
				})
				.catch(error => {
					this.loger("ERR", error.message || error);
				});
			}
		})
		.catch(error => {
			this.loger("ERR", error.message || error);
		});
	}
}

module.exports = new Pool;<|endoftext|>


<commit_before>'use strict'
var fs = require('fs');
fs.readFile('../app.js', 'utf8', function(err, content){
			console.log(err)
			console.log(content)
		})
<commit_msg>test file<commit_after>'use strict'
var fs = require('fs');
fs.readFile('../app.js', 'utf8', function(err, content){
	console.log(err)
	console.log(content)
})
<|endoftext|>