<commit_before>/* Copyright 2015 Google Inc. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

'use strict';
require('lib/promise');

var _ = require('underscore');
var debug = require('debug')('wall:module_state_machine');
var random = require('random-js')();

var stateMachine = require('lib/state_machine');
var time = require('server/util/time');
var library = require('server/modules/module_library');
var ServerStateMachine = require('server/modules/server_state_machine');
var geometry = require('lib/geometry');

function isDisplayInPoly(rect, poly) {
  // find the center point of this display:
  var cx = rect.w / 2 + rect.x;
  var cy = rect.h / 2 + rect.y;

  return geometry.isInside(poly, cx, cy);
}

// Takes a map of client ids -> client state machines. Not owned or changed
// by this class, only read.
class ModuleStateMachine extends stateMachine.Machine {
  constructor(allClients, geo) {
    super(debug, new IdleState);

    // The geo that contains this module sm.
    this.geo_ = geo;

    // Map of ID to ClientControlStateMachine for all clients.
    this.allClients_ = allClients;

    // Server module controller by the module state machine.
    this.context_.server = new ServerStateMachine(geo);

    // Clients controlled by the module state machine.
    this.context_.clients = _.pick(allClients, (client) =>
        isDisplayInPoly(client.getClientInfo().rect, geo));

    _.each(this.context_.clients, (clientSM) => clientSM.setGeo(geo));

    this.context_.playlist = null;
    this.context_.moduleDuration = null;
  }
  newClient(client) {
    if (!isDisplayInPoly(client.rect, this.geo_)) {
      return false;
    }

    this.context_.clients[client.socket.id] = this.allClients_[client.socket.id];
    this.context_.clients[client.socket.id].setGeo(this.geo_);
    this.current_.newClient(client);
    return true;
  }
  dropClient(id) {
    if (!(id in this.context_.clients)) {
      return false;
    }

    delete this.context_.clients[id];

    return true;
  }
  loadPlaylist(layout, deadline) {
    debug('switch to layout', layout);
    this.context_.playlist = layout.modules.slice(0);
    random.shuffle(this.context_.playlist);
    this.context_.moduleDuration = layout.moduleDuration;
    this.current_.loadPlaylist(deadline);
  }
  fadeToBlack(deadline) {
    this.context_.playlist = [library.modules['_faded_out']];  // jshint ignore:line
    this.context_.moduleDuration = deadline;
    this.current_.loadPlaylist(deadline);

    // Return a promise that will be resolved when the state machine is
    // idling (technically, in Display state with a black-screen module).
    return this.context_.server.monitorState(function(state) {
      return state.name_ == 'DisplayState';
    }).then(() => this.stop());
  }
  playModule(moduleName) {
    return this.current_.playModule(moduleName);
  }
  getGeo() {
    return this.geo_;
  }
  getDeadlineOfNextTransition() {
    return this.current_.getDeadline();
  }
  stop() {
    this.context_.server.stop();
  }
}

class IdleState extends stateMachine.State {
  constructor() {
    super('IdleState');
  }
  enter_() {}
  loadPlaylist(deadline) {
    this.transition_(new LoadingState(deadline));
  }
  newClient(client) {}
  playModule(moduleName) {
    return false;
  }
  getDeadline() {
    return Infinity;
  }
}

class LoadingState extends stateMachine.State {
  constructor(deadline) {
    super('LoadingState');

    this.indexOfModuleToPlayWhenLoaded_ = 0;

    // The time at which we should swap to the new playlist.
    this.deadline_ = deadline;
  }
  enter_() {
    // Load the playlist.
    var modulePromises = this.context_.playlist.map((m) => m.loadPromise);
    Promise.allSettled(modulePromises).done((results) => {
      // Check to see if any modules were rejected. If so, remove them from the
      // playlist.
      this.context_.playlist = this.context_.playlist.filter((module, index) => {
        if (results[index].status != 'resolved') {
          debug('Removing ' + module + ' from the playlist!');
        }
        return results[index].status == 'resolved';
      });
      this.transition_(new TransitionState(this.deadline_, this.indexOfModuleToPlayWhenLoaded_));
    });
  }
  loadPlaylist(deadline) {
    // Stop any prior async work from continuing.
    // The fact that we still be in the 'map' above is no big deal, we'll just
    // extra disk i/o.
    this.transition_(new LoadingState(deadline));
  }
  newClient(client) {}
  playModule(moduleName) {
    var index = _.findIndex(this.context_.playlist, (d) => d.name == moduleName);
    if (index != -1) {
      debug('Will play module ' + moduleName + ' when loading is complete.');
      this.indexOfModuleToPlayWhenLoaded_ = index;
      return true;
    }
    debug('Could not find requested module ' + moduleName);
    return false;
  }
  getDeadline() {
    return this.deadline_;
  }
}

class TransitionState extends stateMachine.State {
  constructor(deadline, opt_index) {
    super('TransitionState');

    // If no next item passed, choose the first one.
    this.index_ = opt_index || 0;

    this.deadline_ = deadline;

    // The current moduleDef we are attempting to show or showing.
    this.moduleDef_ = null;
  }
  enter_() {
    // Check for wrapping.
    this.index_ = this.index_ % this.context_.playlist.length;

    // We'll attempt to transition the clients to this module.
    this.moduleDef_ = this.context_.playlist[this.index_];

    // Tell the server to transition.
    this.context_.server.nextModule(this.moduleDef_, this.deadline_);
    this.context_.server
        .monitorState((state) => {
          return state.name_ == 'ErrorState' || state.name_ == 'TransitionState';
        }).then(() => {
          if (this.context_.server.getState() == 'ErrorState') {
            debug('Advancing to next module soon due to error state');
            // Wait a bit so that if we only have one module (as in
            // development mode) we don't throw errors in a tight loop.
            this.deadline_ = time.inFuture(2000);
            Promise.delay(2000).then(() => this.transition_(
                new TransitionState(time.inFuture(5000), this.index_ + 1)));
          }
        });

    // Tell each client to do the module.
    _.each(this.context_.clients, function(clientState) {
      clientState.nextModule(this.moduleDef_, this.deadline_);
    }, this);

    // When the deadline arrives, enter display state.
    debug('Waiting until', this.deadline_);
    Promise.delay(time.until(this.deadline_)).done(() => {
      this.transition_(new DisplayState(
          this.moduleDef_, this.deadline_, this.index_));
    });
  }
  loadPlaylist(deadline) {
    // We changed the layout... immediately load the new playlist.
    this.transition_(new LoadingState(deadline));
  }
  newClient(client) {
    // Tell the new guy to load the next module NOW.
    this.context_.clients[client.socket.id].nextModule(
        this.moduleDef_, this.deadline_);
  }
  playModule(moduleName) {
    var index = _.findIndex(this.context_.playlist, (d) => d.name == moduleName);
    if (index != -1) {
      debug('Will play module ' + moduleName + ' just as soon as current transition completes!');
      this.index_ = index;
      return true;
    }
    debug('Could not find requested module ' + moduleName);
    return false;
  }
  getDeadline() {
    return this.deadline_;
  }
}

class DisplayState extends stateMachine.State {
  constructor(moduleDef, deadline, index) {
    super('DisplayState');

    // The module to tell late clients to transition to.
    this.lateClientModuleDef_ = moduleDef;
    this.lateClientDeadline_ = deadline;

    // What to play from the playlist.
    this.index_ = index;
  }
  enter_() {
    if (this.context_.playlist.length > 1) {
      // Hold for a while, then transition to the next module.

      // Pad the module duration by 20% so that individual wall partitions
      // transition at slightly different times.
      var displayDuration = this.context_.moduleDuration +
          Math.random() * this.context_.moduleDuration / 5;
      this.deadline_ = time.inFuture(1000 * displayDuration);

      debug('Displaying ', this.lateClientModuleDef_.name, 'until', this.deadline_);
      Promise.delay(time.until(this.deadline_)).done(() => {
        this.transition_(new TransitionState(
            this.deadline_, this.index_ + 1));
      });
    } else {
      debug('Displaying ', this.lateClientModuleDef_.name);
      this.deadline_ = Infinity;
    }
  }
  loadPlaylist(deadline) {
    // We changed the layout... immediately load the new playlist.
    this.transition_(new LoadingState(deadline));
  }
  newClient(client) {
    // Tell the new guy to load the next module NOW.
    this.context_.clients[client.socket.id].nextModule(
        this.lateClientModuleDef_, this.lateClientDeadline_);
  }
  playModule(moduleName) {
    var index = _.findIndex(this.context_.playlist, (d) => d.name == moduleName);
    if (index != -1) {
      debug('Found requested module ' + moduleName, index);
      this.index_ = index;
      // Transition immediately.
      this.transition_(new TransitionState(time.now(), index));
      return true;
    }
    debug('Could not find requested module ' + moduleName);
    return false;
  }
  getDeadline() {
    return this.deadline_;
  }
}

module.exports = ModuleStateMachine;
<commit_msg>If a playmodule event occurs during transition, still continue to display, but finish it asap.<commit_after>/* Copyright 2015 Google Inc. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

'use strict';
require('lib/promise');

var _ = require('underscore');
var debug = require('debug')('wall:module_state_machine');
var random = require('random-js')();

var stateMachine = require('lib/state_machine');
var time = require('server/util/time');
var library = require('server/modules/module_library');
var ServerStateMachine = require('server/modules/server_state_machine');
var geometry = require('lib/geometry');

function isDisplayInPoly(rect, poly) {
  // find the center point of this display:
  var cx = rect.w / 2 + rect.x;
  var cy = rect.h / 2 + rect.y;

  return geometry.isInside(poly, cx, cy);
}

// Takes a map of client ids -> client state machines. Not owned or changed
// by this class, only read.
class ModuleStateMachine extends stateMachine.Machine {
  constructor(allClients, geo) {
    super(debug, new IdleState);

    // The geo that contains this module sm.
    this.geo_ = geo;

    // Map of ID to ClientControlStateMachine for all clients.
    this.allClients_ = allClients;

    // Server module controller by the module state machine.
    this.context_.server = new ServerStateMachine(geo);

    // Clients controlled by the module state machine.
    this.context_.clients = _.pick(allClients, (client) =>
        isDisplayInPoly(client.getClientInfo().rect, geo));

    _.each(this.context_.clients, (clientSM) => clientSM.setGeo(geo));

    this.context_.playlist = null;
    this.context_.moduleDuration = null;
  }
  newClient(client) {
    if (!isDisplayInPoly(client.rect, this.geo_)) {
      return false;
    }

    this.context_.clients[client.socket.id] = this.allClients_[client.socket.id];
    this.context_.clients[client.socket.id].setGeo(this.geo_);
    this.current_.newClient(client);
    return true;
  }
  dropClient(id) {
    if (!(id in this.context_.clients)) {
      return false;
    }

    delete this.context_.clients[id];

    return true;
  }
  loadPlaylist(layout, deadline) {
    debug('switch to layout', layout);
    this.context_.playlist = layout.modules.slice(0);
    random.shuffle(this.context_.playlist);
    this.context_.moduleDuration = layout.moduleDuration;
    this.current_.loadPlaylist(deadline);
  }
  fadeToBlack(deadline) {
    this.context_.playlist = [library.modules['_faded_out']];  // jshint ignore:line
    this.context_.moduleDuration = deadline;
    this.current_.loadPlaylist(deadline);

    // Return a promise that will be resolved when the state machine is
    // idling (technically, in Display state with a black-screen module).
    return this.context_.server.monitorState(function(state) {
      return state.name_ == 'DisplayState';
    }).then(() => this.stop());
  }
  playModule(moduleName) {
    return this.current_.playModule(moduleName);
  }
  getGeo() {
    return this.geo_;
  }
  getDeadlineOfNextTransition() {
    return this.current_.getDeadline();
  }
  stop() {
    this.context_.server.stop();
  }
}

class IdleState extends stateMachine.State {
  constructor() {
    super('IdleState');
  }
  enter_() {}
  loadPlaylist(deadline) {
    this.transition_(new LoadingState(deadline));
  }
  newClient(client) {}
  playModule(moduleName) {
    return false;
  }
  getDeadline() {
    return Infinity;
  }
}

class LoadingState extends stateMachine.State {
  constructor(deadline) {
    super('LoadingState');

    this.indexOfModuleToPlayWhenLoaded_ = 0;

    // The time at which we should swap to the new playlist.
    this.deadline_ = deadline;
  }
  enter_() {
    // Load the playlist.
    var modulePromises = this.context_.playlist.map((m) => m.loadPromise);
    Promise.allSettled(modulePromises).done((results) => {
      // Check to see if any modules were rejected. If so, remove them from the
      // playlist.
      this.context_.playlist = this.context_.playlist.filter((module, index) => {
        if (results[index].status != 'resolved') {
          debug('Removing ' + module + ' from the playlist!');
        }
        return results[index].status == 'resolved';
      });
      this.transition_(new TransitionState(this.deadline_, this.indexOfModuleToPlayWhenLoaded_));
    });
  }
  loadPlaylist(deadline) {
    // Stop any prior async work from continuing.
    // The fact that we still be in the 'map' above is no big deal, we'll just
    // extra disk i/o.
    this.transition_(new LoadingState(deadline));
  }
  newClient(client) {}
  playModule(moduleName) {
    var index = _.findIndex(this.context_.playlist, (d) => d.name == moduleName);
    if (index != -1) {
      debug('Will play module ' + moduleName + ' when loading is complete.');
      this.indexOfModuleToPlayWhenLoaded_ = index;
      return true;
    }
    debug('Could not find requested module ' + moduleName);
    return false;
  }
  getDeadline() {
    return this.deadline_;
  }
}

class TransitionState extends stateMachine.State {
  constructor(deadline, opt_index) {
    super('TransitionState');

    // If no next item passed, choose the first one.
    this.index_ = opt_index || 0;

    this.deadline_ = deadline;

    // The current moduleDef we are attempting to show or showing.
    this.moduleDef_ = null;
  }
  enter_() {
    // Check for wrapping.
    this.index_ = this.index_ % this.context_.playlist.length;

    // We'll attempt to transition the clients to this module.
    this.moduleDef_ = this.context_.playlist[this.index_];

    // Tell the server to transition.
    this.context_.server.nextModule(this.moduleDef_, this.deadline_);
    this.context_.server
        .monitorState((state) => {
          return state.name_ == 'ErrorState' || state.name_ == 'TransitionState';
        }).then(() => {
          if (this.context_.server.getState() == 'ErrorState') {
            debug('Advancing to next module soon due to error state');
            // Wait a bit so that if we only have one module (as in
            // development mode) we don't throw errors in a tight loop.
            this.deadline_ = time.inFuture(2000);
            Promise.delay(2000).then(() => this.transition_(
                new TransitionState(time.inFuture(5000), this.index_ + 1)));
          }
        });

    // Tell each client to do the module.
    _.each(this.context_.clients, function(clientState) {
      clientState.nextModule(this.moduleDef_, this.deadline_);
    }, this);

    // When the deadline arrives, enter display state.
    debug('Waiting until', this.deadline_);
    Promise.delay(time.until(this.deadline_)).done(() => {
      let originalIndex = _(this.context_.playlist).findIndex(this.moduleDef_);
      let duration = this.index_ != originalIndex ? 1 : undefined;
      this.transition_(new DisplayState(
          this.moduleDef_, this.deadline_, this.index_, duration));
    });
  }
  loadPlaylist(deadline) {
    // We changed the layout... immediately load the new playlist.
    this.transition_(new LoadingState(deadline));
  }
  newClient(client) {
    // Tell the new guy to load the next module NOW.
    this.context_.clients[client.socket.id].nextModule(
        this.moduleDef_, this.deadline_);
  }
  playModule(moduleName) {
    var index = _.findIndex(this.context_.playlist, (d) => d.name == moduleName);
    if (index != -1) {
      debug('Will play module ' + moduleName + ' just as soon as current transition completes!');
      this.index_ = index;
      return true;
    }
    debug('Could not find requested module ' + moduleName);
    return false;
  }
  getDeadline() {
    return this.deadline_;
  }
}

class DisplayState extends stateMachine.State {
  constructor(moduleDef, deadline, index, opt_duration) {
    super('DisplayState');

    // The module to tell late clients to transition to.
    this.lateClientModuleDef_ = moduleDef;
    this.lateClientDeadline_ = deadline;

    // What to play from the playlist.
    this.index_ = index;

    // How long to play the module.
    this.duration_ = opt_duration || 0;
  }
  enter_() {
    if (this.context_.playlist.length > 1) {
      // Hold for a while, then transition to the next module.

      // Pad the module duration by 20% so that individual wall partitions
      // transition at slightly different times.
      this.duration_ = this.duration_ || this.context_.moduleDuration +
          Math.random() * this.context_.moduleDuration / 5 * 1000;
      this.deadline_ = time.inFuture(this.duration_);

      debug('Displaying ', this.lateClientModuleDef_.name, 'until', this.deadline_ , this.duration_);
      Promise.delay(time.until(this.deadline_)).done(() => {
        this.transition_(new TransitionState(
            this.deadline_, this.index_ + 1));
      });
    } else {
      debug('Displaying ', this.lateClientModuleDef_.name);
      this.deadline_ = Infinity;
    }
  }
  loadPlaylist(deadline) {
    // We changed the layout... immediately load the new playlist.
    this.transition_(new LoadingState(deadline));
  }
  newClient(client) {
    // Tell the new guy to load the next module NOW.
    this.context_.clients[client.socket.id].nextModule(
        this.lateClientModuleDef_, this.lateClientDeadline_);
  }
  playModule(moduleName) {
    var index = _.findIndex(this.context_.playlist, (d) => d.name == moduleName);
    if (index != -1) {
      debug('Found requested module ' + moduleName, index);
      this.index_ = index;
      // Transition immediately.
      this.transition_(new TransitionState(time.now(), index));
      return true;
    }
    debug('Could not find requested module ' + moduleName);
    return false;
  }
  getDeadline() {
    return this.deadline_;
  }
}

module.exports = ModuleStateMachine;
<|endoftext|>


<commit_before>"use strict";
var Utils = {
  getCurrentVersion: function() {
    return chrome.runtime.getManifest().version;
  },
  fetchHttpContents: function(url, success, onerror) {
    var req = new XMLHttpRequest();
    req.open("GET", url, true);
    req.onreadystatechange = function () {
      if(req.readyState === 4) {
        var text = req.responseText, status = req.status;
        req = null;
        if (status === 200) {
          success(text);
        } else if (onerror) {
          onerror(text, status);
        }
      }
    };
    req.send();
    return req;
  },
  _escapeRegex: /[&<>]/g,
  _escapeCallback: function(c, n) {
    n = c.charCodeAt(0);
    return (n === 60) ? "<" : (n === 62) ? ">" : "&";
  },
  escapeHtml: function(s) {
    return s.replace(this._escapeRegex, this._escapeCallback);
  },
  // "javascript" should be treated specially
  _chromePrefixes: ["about", "view-source", "chrome-search", "chrome-extension", "data"],
  _urlPrefix: /^[a-z]{3,}:\/\/./,
  hasOrdinaryUrlPrefix: function(url) {
    return this._urlPrefix.test(url);
  },
  isRefusingIncognito: function(url) {
    url = url.toLowerCase();
    if (url.startsWith('chrome://')) {
      return !url.startsWith("chrome://downloads/");
    }
    return url !== Settings.ChromeInnerNewTab && url.startsWith('chrome');
  },
  _hostRegex: /^([^:]+(:[^:]+)?@)?([^:]+|\[[^\]]+\])(:\d+)?$/,
  _nonENTlds: ".\u4e2d\u56fd",
  _tlds: ["", "",
    ".ac.ad.ae.af.ag.ai.al.am.an.ao.aq.ar.as.at.au.aw.az.ba.bb.bd.be.bf.bg.bh.bi.bj.bm.bn.bo.br.bs.bt.bv.bw.by.bz.ca.cc.cd.cf.cg.ch.ci.ck.cl.cm.cn.co.cr.cu.cv.cx.cy.cz.de.dj.dk.dm.do.dz.ec.ee.eg.eh.er.es.et.eu.fi.fj.fk.fm.fo.fr.ga.gd.ge.gf.gg.gh.gi.gl.gm.gn.gp.gq.gr.gs.gt.gu.gw.gy.hk.hm.hn.hr.ht.hu.id.ie.il.im.in.io.iq.ir.is.it.je.jm.jo.jp.ke.kg.kh.ki.km.kn.kp.kr.kw.ky.kz.la.lb.lc.li.lk.lr.ls.lt.lu.lv.ly.ma.mc.md.me.mg.mh.mk.ml.mm.mn.mo.mp.mq.mr.ms.mt.mu.mv.mw.mx.my.mz.na.nc.ne.nf.ng.ni.nl.no.np.nr.nu.nz.om.pa.pe.pf.pg.ph.pk.pl.pm.pn.pr.ps.pt.pw.py.qa.re.ro.ru.rw.sa.sb.sc.sd.se.sg.sh.si.sj.sk.sl.sm.sn.so.sr.ss.st.sv.sy.sz.tc.td.tf.tg.th.tj.tk.tl.tm.tn.to.tp.tr.tt.tv.tw.tz.ua.ug.uk.um.us.uy.uz.va.vc.ve.vg.vi.vn.vu.wf.ws.ye.yt.yu.za.zm.zw",
    ".biz.cat.com.edu.gov.int.mil.mtn.net.org.pro.tel.xxx",
    ".aero.arpa.asia.club.coop.info.jobs.mobi.name.post",
    "",
    ".museum.travel"
  ],
  _ipRegex: /^(\d{1,3}\.){3}\d{1,3}$/,
  spacesRegex: /[\s\u3000]+/g,
  _nonENTldRegex: /[^a-z]/,
  _jsNotEscapeRegex: /["\[\]{}\u00ff-\uffff]|%(?![\dA-Fa-f]{2})/,
  convertToUrl: function(string) {
    if (string.substring(0, 11).toLowerCase() == "javascript:") {
      if (string.indexOf('%', 11) > 0 && !this._jsNotEscapeRegex.test(string)) {
        string = this.decodeEachURLPart(string);
      }
      return string;
    }
    var type = -1, expected = 1, index, index0, oldString, arr;
    // NOTE: here '\u3000' is changed to ' ', which may cause a 404 (for url)
    // NOTE: here a mulit-line string is be changed to single-line,
    //       which may be better
    oldString = string.replace(this.spacesRegex, ' ').trim();
    string = oldString.toLowerCase();
    if ((index = string.indexOf(' ')) > 0) {
      string = string.substring(0, index);
      if ((index = string.indexOf('/')) <= 0 || (index0 = string.indexOf(':')) === 0) {
        type = 2;
      }
      else if (index0 === -1) {}
      else if (string.substring(index0, index0 + 3) !== "://") {
        if (this._chromePrefixes.indexOf(string.substring(0, index0)) !== -1) {
          type = 2;
        } else {
          index0 = -1;
        }
      }
      else if (this._urlPrefix.test(string)) {
        expected = 0;
        if (string.startsWith("file:///")) {
          index0 = string.charCodeAt(8);
          type = (index0 > 32 && index0 !== 47) ? 0 : 2;
        }
      } else if (!this.startsWith("chrome")) {
        type = 2;
      }
      if (type < 0) {
        if (index0 > 0) {
          index0 += 3;
          index = string.indexOf('/', index0);
        } else {
          index0 = 0;
        }
        if (index > index0 && (type = string.charCodeAt(index + 1)) > 32 && type !== 47) {
          string = string.substring(index0, index);
          type = -1;
        } else {
          type = 2;
        }
      }
    }
    else if (this._urlPrefix.test(string)) {
      if (string.startsWith("file:") || string.startsWith("chrome:")) {
        type = 0;
      } else {
        index0 = string.indexOf(':') + 3;
        index = string.indexOf('/', index0);
        string = string.substring(index0, index !== -1 ? index : undefined);
        expected = 0;
      }
    }
    else if ((index = string.indexOf(':')) > 3 && index < 17 &&
        this._chromePrefixes.indexOf(string.substring(0, index)) !== -1) {
      type = 0;
    } else {
      string = (index = string.indexOf('/')) !== -1 ? string.substring(0, index) : string;
    }
    if (type !== -1) {
    } else if (!(arr = this._hostRegex.exec(string))) {
      type = 2;
    } else if ((string = arr[3]).indexOf(':') !== -1 || string.endsWith("localhost")) {
      type = expected;
    } else if ((index = string.lastIndexOf('.')) <= 0) {
      type = 2;
    } else if (this._ipRegex.test(string)) {
      type = expected;
    } else if (!this.isTld(string.substring(index + 1))) {
      type = 2;
    } else if (expected === 0) {
      type = 0;
    } else if (arr[2] || arr[4] || !arr[1]) {
      type = 1;
    // the below means string is like "abc@(uvw.)*xyz.tld"
    } else if (string.startsWith("ftp.")) {
      type = 1;
    } else if (string.startsWith("mail") || string.indexOf(".mail") > 0) {
      type = 2;
    } else if ((index0 = string.indexOf(".")) === index) {
      type = 2;
    } else if (string.indexOf(".", ++index0) !== index) {
      type = 1;
    } else {
      type = this.isTld(string.substring(index0, index)) ? 2 : 1;
    }
    return type === 0 ? oldString : type === 1 ? ("http://" + oldString)
      : this.createSearchUrl(Settings.get("searchEnginesMap")["~"], oldString.split(' ')).url;
  },
  isTld: function(tld) {
    if (this._nonENTldRegex.test(tld)) {
      return this._nonENTlds.indexOf(tld) !== -1;
    } else if (tld.length < this._tlds.length) {
      return this._tlds[tld.length].indexOf(tld) > 0;
    }
    return false;
  },
  _searchWordRegex: /%[sS]/g,
  createSearchUrl: function(pattern, query, $S) {
    if ($S != null ? ($S === true) : pattern.$S) {
      $S = query.join(' ');
    }
    if (pattern.$s) {
      query = query.map(encodeURIComponent).join('+');
    }
    query = pattern.url.replace(this._searchWordRegex, function(s) {
      return (s === "%s") ? query : $S;
    });
    return {
      url: query,
      $S: $S
    };
  },
  decodeURLPart: function(url) {
    try {
      url = decodeURIComponent(url);
    } catch (e) {
    }
    return url;
  },
  _urlEscapeRegex: /((?:%[\dA-Fa-f]{2})+)/g,
  decodeEachURLPart: function(url) {
    var arr = url.split(this._urlEscapeRegex), i = arr.length, e, decode;
    decode = decodeURIComponent;
    for (; ; ) {
      try {
        while (0 < (i -= 2)) {
          arr[i] = decode(arr[i]);
        };
        break;
      } catch (e) {
      }
    }
    return arr.join("");
  }
};
<commit_msg>fix a typo in convertToUrl<commit_after>"use strict";
var Utils = {
  getCurrentVersion: function() {
    return chrome.runtime.getManifest().version;
  },
  fetchHttpContents: function(url, success, onerror) {
    var req = new XMLHttpRequest();
    req.open("GET", url, true);
    req.onreadystatechange = function () {
      if(req.readyState === 4) {
        var text = req.responseText, status = req.status;
        req = null;
        if (status === 200) {
          success(text);
        } else if (onerror) {
          onerror(text, status);
        }
      }
    };
    req.send();
    return req;
  },
  _escapeRegex: /[&<>]/g,
  _escapeCallback: function(c, n) {
    n = c.charCodeAt(0);
    return (n === 60) ? "<" : (n === 62) ? ">" : "&";
  },
  escapeHtml: function(s) {
    return s.replace(this._escapeRegex, this._escapeCallback);
  },
  // "javascript" should be treated specially
  _chromePrefixes: ["about", "view-source", "chrome-search", "chrome-extension", "data"],
  _urlPrefix: /^[a-z]{3,}:\/\/./,
  hasOrdinaryUrlPrefix: function(url) {
    return this._urlPrefix.test(url);
  },
  isRefusingIncognito: function(url) {
    url = url.toLowerCase();
    if (url.startsWith('chrome://')) {
      return !url.startsWith("chrome://downloads/");
    }
    return url !== Settings.ChromeInnerNewTab && url.startsWith('chrome');
  },
  _hostRegex: /^([^:]+(:[^:]+)?@)?([^:]+|\[[^\]]+\])(:\d+)?$/,
  _nonENTlds: ".\u4e2d\u56fd",
  _tlds: ["", "",
    ".ac.ad.ae.af.ag.ai.al.am.an.ao.aq.ar.as.at.au.aw.az.ba.bb.bd.be.bf.bg.bh.bi.bj.bm.bn.bo.br.bs.bt.bv.bw.by.bz.ca.cc.cd.cf.cg.ch.ci.ck.cl.cm.cn.co.cr.cu.cv.cx.cy.cz.de.dj.dk.dm.do.dz.ec.ee.eg.eh.er.es.et.eu.fi.fj.fk.fm.fo.fr.ga.gd.ge.gf.gg.gh.gi.gl.gm.gn.gp.gq.gr.gs.gt.gu.gw.gy.hk.hm.hn.hr.ht.hu.id.ie.il.im.in.io.iq.ir.is.it.je.jm.jo.jp.ke.kg.kh.ki.km.kn.kp.kr.kw.ky.kz.la.lb.lc.li.lk.lr.ls.lt.lu.lv.ly.ma.mc.md.me.mg.mh.mk.ml.mm.mn.mo.mp.mq.mr.ms.mt.mu.mv.mw.mx.my.mz.na.nc.ne.nf.ng.ni.nl.no.np.nr.nu.nz.om.pa.pe.pf.pg.ph.pk.pl.pm.pn.pr.ps.pt.pw.py.qa.re.ro.ru.rw.sa.sb.sc.sd.se.sg.sh.si.sj.sk.sl.sm.sn.so.sr.ss.st.sv.sy.sz.tc.td.tf.tg.th.tj.tk.tl.tm.tn.to.tp.tr.tt.tv.tw.tz.ua.ug.uk.um.us.uy.uz.va.vc.ve.vg.vi.vn.vu.wf.ws.ye.yt.yu.za.zm.zw",
    ".biz.cat.com.edu.gov.int.mil.mtn.net.org.pro.tel.xxx",
    ".aero.arpa.asia.club.coop.info.jobs.mobi.name.post",
    "",
    ".museum.travel"
  ],
  _ipRegex: /^(\d{1,3}\.){3}\d{1,3}$/,
  spacesRegex: /[\s\u3000]+/g,
  _nonENTldRegex: /[^a-z]/,
  _jsNotEscapeRegex: /["\[\]{}\u00ff-\uffff]|%(?![\dA-Fa-f]{2})/,
  convertToUrl: function(string) {
    if (string.substring(0, 11).toLowerCase() == "javascript:") {
      if (string.indexOf('%', 11) > 0 && !this._jsNotEscapeRegex.test(string)) {
        string = this.decodeEachURLPart(string);
      }
      return string;
    }
    var type = -1, expected = 1, index, index0, oldString, arr;
    // NOTE: here '\u3000' is changed to ' ', which may cause a 404 (for url)
    // NOTE: here a mulit-line string is be changed to single-line,
    //       which may be better
    oldString = string.replace(this.spacesRegex, ' ').trim();
    string = oldString.toLowerCase();
    if ((index = string.indexOf(' ')) > 0) {
      string = string.substring(0, index);
      if ((index = string.indexOf('/')) <= 0 || (index0 = string.indexOf(':')) === 0) {
        type = 2;
      }
      else if (index0 === -1) {}
      else if (string.substring(index0, index0 + 3) !== "://") {
        if (this._chromePrefixes.indexOf(string.substring(0, index0)) !== -1) {
          type = 2;
        } else {
          index0 = -1;
        }
      }
      else if (this._urlPrefix.test(string)) {
        expected = 0;
        if (string.startsWith("file:///")) {
          index0 = string.charCodeAt(8);
          type = (index0 > 32 && index0 !== 47) ? 0 : 2;
        }
      } else if (!string.startsWith("chrome")) {
        type = 2;
      }
      if (type < 0) {
        if (index0 > 0) {
          index0 += 3;
          index = string.indexOf('/', index0);
        } else {
          index0 = 0;
        }
        if (index > index0 && (type = string.charCodeAt(index + 1)) > 32 && type !== 47) {
          string = string.substring(index0, index);
          type = -1;
        } else {
          type = 2;
        }
      }
    }
    else if (this._urlPrefix.test(string)) {
      if (string.startsWith("file:") || string.startsWith("chrome:")) {
        type = 0;
      } else {
        index0 = string.indexOf(':') + 3;
        index = string.indexOf('/', index0);
        string = string.substring(index0, index !== -1 ? index : undefined);
        expected = 0;
      }
    }
    else if ((index = string.indexOf(':')) > 3 && index < 17 &&
        this._chromePrefixes.indexOf(string.substring(0, index)) !== -1) {
      type = 0;
    } else {
      string = (index = string.indexOf('/')) !== -1 ? string.substring(0, index) : string;
    }
    if (type !== -1) {
    } else if (!(arr = this._hostRegex.exec(string))) {
      type = 2;
    } else if ((string = arr[3]).indexOf(':') !== -1 || string.endsWith("localhost")) {
      type = expected;
    } else if ((index = string.lastIndexOf('.')) <= 0) {
      type = 2;
    } else if (this._ipRegex.test(string)) {
      type = expected;
    } else if (!this.isTld(string.substring(index + 1))) {
      type = 2;
    } else if (expected === 0) {
      type = 0;
    } else if (arr[2] || arr[4] || !arr[1]) {
      type = 1;
    // the below means string is like "abc@(uvw.)*xyz.tld"
    } else if (string.startsWith("ftp.")) {
      type = 1;
    } else if (string.startsWith("mail") || string.indexOf(".mail") > 0) {
      type = 2;
    } else if ((index0 = string.indexOf(".")) === index) {
      type = 2;
    } else if (string.indexOf(".", ++index0) !== index) {
      type = 1;
    } else {
      type = this.isTld(string.substring(index0, index)) ? 2 : 1;
    }
    return type === 0 ? oldString : type === 1 ? ("http://" + oldString)
      : this.createSearchUrl(Settings.get("searchEnginesMap")["~"], oldString.split(' ')).url;
  },
  isTld: function(tld) {
    if (this._nonENTldRegex.test(tld)) {
      return this._nonENTlds.indexOf(tld) !== -1;
    } else if (tld.length < this._tlds.length) {
      return this._tlds[tld.length].indexOf(tld) > 0;
    }
    return false;
  },
  _searchWordRegex: /%[sS]/g,
  createSearchUrl: function(pattern, query, $S) {
    if ($S != null ? ($S === true) : pattern.$S) {
      $S = query.join(' ');
    }
    if (pattern.$s) {
      query = query.map(encodeURIComponent).join('+');
    }
    query = pattern.url.replace(this._searchWordRegex, function(s) {
      return (s === "%s") ? query : $S;
    });
    return {
      url: query,
      $S: $S
    };
  },
  decodeURLPart: function(url) {
    try {
      url = decodeURIComponent(url);
    } catch (e) {
    }
    return url;
  },
  _urlEscapeRegex: /((?:%[\dA-Fa-f]{2})+)/g,
  decodeEachURLPart: function(url) {
    var arr = url.split(this._urlEscapeRegex), i = arr.length, e, decode;
    decode = decodeURIComponent;
    for (; ; ) {
      try {
        while (0 < (i -= 2)) {
          arr[i] = decode(arr[i]);
        };
        break;
      } catch (e) {
      }
    }
    return arr.join("");
  }
};
<|endoftext|>


<commit_before>var http = require('http'),
    async = require('async'),
    helpers = require('../helpers'),
    Bucket = require('../bucket');

var HTTPBackend = function(host, port, resources) {
    this.host = host;
    this.port = port;
    this.resources = helpers.merge(HTTPBackend.defaults.resources, resources || {});

    this.buckets = Object.create(HTTPBackend.prototype.buckets); // Establish namespace 'buckets'
    this.buckets.this = this; // used as a placeholder for namespaced functions, referenced using this.this in those functions.

    this.objects = Object.create(HTTPBackend.prototype.objects); // Establish namespace 'objects'
    this.objects.this = this; // used as a placeholder for namespaced functions, referenced using this.this in those functions.
};

HTTPBackend.prototype.stats = function(_return) {
    var query = { resource: this.resources.riak_kv_wm_stats };
    this.get(query, _return);
};

HTTPBackend.prototype.ping = function(_return) {
    var query = { resource: this.resources.riak_kv_wm_ping };
    this.get(query, _return);
};

HTTPBackend.prototype.resources = function(_return) {
    var query = { resource: '' };
    this.get(query, _return);
};

HTTPBackend.prototype.buckets = {};
HTTPBackend.prototype.buckets.list = function(_return) {
    var _this = this.this;

    var query = {
        resource: _this.resources.riak_kv_wm_index,
        options: { buckets: true },
        headers: { "Accept": "application/json" }
    };

    _this.get(query, function(err, data, meta) {
        data = JSON.parse(data);
        async.map(data.buckets,
            function(bucket, _intermediate) {
                var temp = _this.buckets.get(bucket);
                temp.fetchProps(function(err, data, meta) {
                    if(err) _intermediate(err, data);
                    else {
                        temp.props = data;
                        _intermediate(err, temp);
                    }
                });
            },
            function(err, results) {
                _return(err, results, meta);
            }
        );
    });
};

HTTPBackend.prototype.buckets.get = function(bucket_name, props) {
    var _this = this.this;

    return new Bucket(bucket_name, props, _this);
};

HTTPBackend.prototype.buckets.props = function(bucket_name, _return) {
    var _this = this.this;

    var query = {
        resource: _this.resources.riak_kv_wm_index+"/"+bucket_name+"/props",
        headers: { "Accept": "application/json" }
    };
    _this.get(query, _return);
};

HTTPBackend.prototype.buckets.save = function(bucket_name, props, _return) {
    var _this = this.this;

    var query = {
        resource: _this.resources.riak_kv_wm_index+"/"+bucket_name+"/props",
        body: JSON.stringify({props: props})
    };
    _this.put(query, _return);
};

HTTPBackend.prototype.buckets.keys = function(bucket_name, _return) {
    var _this = this.this;

    var query = {
        resource: _this.resources.riak_kv_wm_index + "/" +bucket_name+ "/keys/",
        options: { keys: true },
        headers: { "Accept": "application/json" }
    };
    _this.get(query, _return);
};

HTTPBackend.prototype.objects = {};
HTTPBackend.prototype.objects.get = function(/* bucket_name, key, [metadata, [options]], _return */) {
    var _this = this.this;

    var bucket_name = arguments[0];
    var key = arguments[1];
    var metadata = arguments[2] || {};
    var options = arguments[3] || {};
    var _return = typeof(arguments[arguments.length - 1]) == 'function' ? arguments[arguments.length - 1] : function(){};

    var query = {
        resource: _this.resources.riak_kv_wm_index + "/" +bucket_name+ "/keys/" +key ,
        headers: HTTPBackend.metadataToHeaders(metadata),
        options: options
    };

    _this.get(query, _return);
};

HTTPBackend.prototype.objects.save = function(/* bucket_name, key, data, metadata, [options] _return */) {
    var _this = this.this;

    var bucket_name = arguments[0];
    var key = arguments[1] || "";
    var data = arguments[2];
    var metadata = arguments[3] || {};
    var options = typeof(arguments[4]) == 'object' ? arguments[4] : {};
    var _return = typeof(arguments[arguments.length - 1]) == 'function' ? arguments[arguments.length - 1] : function(){};

    var query = {
        resource: _this.resources.riak_kv_wm_index + "/" +bucket_name+ "/keys/" +key,
        headers: HTTPBackend.metadataToHeaders(metadata),
        body: data,
        options: options
    };

    if(key === "") {
        _this.post(query, _return);
    }
    else {
        _this.put(query, _return);
    }
};

HTTPBackend.prototype.objects.exists = function(/* bucket_name, key, [options] _return */) {
    var _this = this.this;

    var bucket_name = arguments[0];
    var key = arguments[1] || "";
    var options = typeof(arguments[2]) == 'object' ? arguments[2] : {};
    var _return = typeof(arguments[arguments.length - 1]) == 'function' ? arguments[arguments.length - 1] : function(){};

    var query = {
        resource: _this.resources.riak_kv_wm_index + "/" +bucket_name+ "/keys/" +key,
        options: options
    };

    _this.head(query, function(err, data, meta) {
        if(err) _return(err, data, meta);
        else {
            if(meta.status_code != 404) {
                _return(err, true);
            }
            else{
                _return(err, false);
            }
        }
    });
};

HTTPBackend.prototype.objects.delete = function(/* bucket_name, key, [options] _return */) {
    var _this = this.this;

    var bucket_name = arguments[0];
    var key = arguments[1] || "";
    var options = typeof(arguments[2]) == 'object' ? arguments[2] : {};
    var _return = typeof(arguments[arguments.length - 1]) == 'function' ? arguments[arguments.length - 1] : function(){};

    var query = {
        resource: _this.resources.riak_kv_wm_index + "/" +bucket_name+ "/keys/" +key,
        options: options
    };

    _this.delete(query, _return);
};

HTTPBackend.prototype.request = function(method, query, _return) {
  var req = http.request({ headers: HTTPBackend.appendDefaultHeaders(query.headers),
                           path: query.resource + HTTPBackend.appendOptions(query.options),
                           method: method,
                           host: this.host,
                           port: this.port}, HTTPBackend.responseHandler.bind(this, _return));

  req.on('error', function(error) {
    _return(error, null, null);
  });

  req.end(query.body, query.encoding || 'utf8');
};

HTTPBackend.responseHandler = function(_return, res) { // reversed signature due to bind()'s prepend behavior in request()
  var body = [];
  res.headers['status-code'] = res.statusCode;

  res.on('data', function(chunk) {
    body.push(chunk);
  });

  res.on('end', function() {
    body = Buffer.concat(body, parseInt(res.headers['content-length'], 10) || undefined);
    var err = null;

    if(res.statusCode >= 400 && res.req.method != "DELETE") {
        err = new Error();
        err.code = res.statusCode;
        err.message = body.toString();
    }

    _return(err, body, HTTPBackend.headersToMetadata(res.headers));
  });

  res.on('close', function(err){
    _return(err, body, res.headers);
  });
};

HTTPBackend.headersToMetadata = function(headers) {
  var metadata = HTTPBackend.munchHeaders(headers);

  return metadata;
};

HTTPBackend.metadataToHeaders = function(metadata) {
  var headers = HTTPBackend.munchMetadata(metadata);

  return headers;
};

HTTPBackend.appendDefaultHeaders = function(headers) {
    headers = headers || {};

    headers["Content-Type"] = headers["Content-Type"] || HTTPBackend.defaults.headers["Content-Type"];
    headers["Accept"] = headers["Accept"] || HTTPBackend.defaults.headers["Accept"];

    return headers;
};

HTTPBackend.appendOptions = function(options) {
    var temp = "";

    for(var key in options) {
        temp += key + "=" + options[key] + "&";
    }

    temp = (temp.length !== 0) ? "?"+temp : temp;

    return temp;
};

HTTPBackend.prototype.head = function(query, _return) {
  this.request('HEAD', query, _return);
};

HTTPBackend.prototype.get = function(query, _return) {
  this.request('GET', query, _return);
};

HTTPBackend.prototype.post = function(query, _return) {
  this.request('POST', query, _return);
};

HTTPBackend.prototype.put = function(query, _return) {
  this.request('PUT', query, _return);
};

HTTPBackend.prototype.delete = function(query, _return) {
  this.request('DELETE', query, _return);
};

HTTPBackend.munchHeaders = function(headers) {
  var metadata = {};

  headers = HTTPBackend.filterHeaders(headers);

  for(var key in headers) {
    var low_key = key.toLowerCase();

    if(low_key.indexOf("x-riak-")) {
      low_key = low_key.replace("-","_");
    }
    else{
      low_key = low_key.slice(7).replace("_","-");
    }

    var parts = low_key.split("-");
    parts.push(headers[key]);
    metadata = HTTPBackend.toNamespaced(metadata, parts);
  }
  return metadata;
};

HTTPBackend.filterHeaders = function(headers) {
    for(var i = 0, length = HTTPBackend.defaults.ignore_headers.length; i < length; i++) {
        if(headers[HTTPBackend.defaults.ignore_headers[i]]) {
            delete headers[HTTPBackend.defaults.ignore_headers[i].toLowerCase()];
        }
    }
    return headers;
};

HTTPBackend.munchMetadata = function(metadata, accumulator, container) {
  accumulator = accumulator || "";
  container = container || {};

  for(var prop in metadata) {
    var acc = accumulator;

    acc = (prop === "vclock" || prop === "index" || prop === "meta") ? "x-riak" : acc;

    if(metadata.hasOwnProperty(prop) && metadata[prop].constructor.name == "Object") {
      munchMetadata(metadata[prop], (acc === "") ? prop : acc + "-" + prop, container);
    }
    else {
      var value = metadata[prop].constructor.name == "Array" ? metadata[prop].join(", ") : metadata[prop];
      prop = prop.replace("_","-");

      if(acc === "") {
        container[prop] = value;
      }
      else {
        container[(prop == "int" || prop == 'bin') ? (acc + "_" + prop) : (acc + "-" + prop)] = value;
      }
    }
  }

  return container;
};

HTTPBackend.toNamespaced = function(parent, parts) {
  var namespace = parent;

  for(var i = 0, length = parts.length-1; i < length; i++) {
      if(i+1 == length) {
        parent[parts[i]] = (parts[0] == 'index') ? parts[i+1].split(", ") : parts[i+1];
      }
      else {
        parent[parts[i]] = parent[parts[i]] || {};
        parent = parent[parts[i]];
      }
  }
  return namespace;
};

HTTPBackend.defaults = {
    headers: {
        "Content-Type": "application/json",
        "Accept": "*/*"
    },
    ignore_headers: [
        "date",
        "content-length",
        "server",
        "vary"
    ],
    connection: {
        host: 'localhost',
        port: 8098
    },
    resources: {
        riak_kv_wm_buckets: "/riak",
        riak_kv_wm_index: "/buckets",
        riak_kv_wm_keylist: "/buckets",
        riak_kv_wm_link_walker: "/riak",
        riak_kv_wm_mapred: "/mapred",
        riak_kv_wm_object: "/riak",
        riak_kv_wm_ping: "/ping",
        riak_kv_wm_props: "/buckets",
        riak_kv_wm_stats: "/stats",
        riak_solr_indexer_wm: "/solr",
        riak_solr_searcher_wm: "/solr"
    }
};

module.exports = HTTPBackend;<commit_msg>on Object exists? handle non-404 errors as special case.<commit_after>var http = require('http'),
    async = require('async'),
    helpers = require('../helpers'),
    Bucket = require('../bucket');

var HTTPBackend = function(host, port, resources) {
    this.host = host;
    this.port = port;
    this.resources = helpers.merge(HTTPBackend.defaults.resources, resources || {});

    this.buckets = Object.create(HTTPBackend.prototype.buckets); // Establish namespace 'buckets'
    this.buckets.this = this; // used as a placeholder for namespaced functions, referenced using this.this in those functions.

    this.objects = Object.create(HTTPBackend.prototype.objects); // Establish namespace 'objects'
    this.objects.this = this; // used as a placeholder for namespaced functions, referenced using this.this in those functions.
};

HTTPBackend.prototype.stats = function(_return) {
    var query = { resource: this.resources.riak_kv_wm_stats };
    this.get(query, _return);
};

HTTPBackend.prototype.ping = function(_return) {
    var query = { resource: this.resources.riak_kv_wm_ping };
    this.get(query, _return);
};

HTTPBackend.prototype.resources = function(_return) {
    var query = { resource: '' };
    this.get(query, _return);
};

HTTPBackend.prototype.buckets = {};
HTTPBackend.prototype.buckets.list = function(_return) {
    var _this = this.this;

    var query = {
        resource: _this.resources.riak_kv_wm_index,
        options: { buckets: true },
        headers: { "Accept": "application/json" }
    };

    _this.get(query, function(err, data, meta) {
        data = JSON.parse(data);
        async.map(data.buckets,
            function(bucket, _intermediate) {
                var temp = _this.buckets.get(bucket);
                temp.fetchProps(function(err, data, meta) {
                    if(err) _intermediate(err, data);
                    else {
                        temp.props = data;
                        _intermediate(err, temp);
                    }
                });
            },
            function(err, results) {
                _return(err, results, meta);
            }
        );
    });
};

HTTPBackend.prototype.buckets.get = function(bucket_name, props) {
    var _this = this.this;

    return new Bucket(bucket_name, props, _this);
};

HTTPBackend.prototype.buckets.props = function(bucket_name, _return) {
    var _this = this.this;

    var query = {
        resource: _this.resources.riak_kv_wm_index+"/"+bucket_name+"/props",
        headers: { "Accept": "application/json" }
    };
    _this.get(query, _return);
};

HTTPBackend.prototype.buckets.save = function(bucket_name, props, _return) {
    var _this = this.this;

    var query = {
        resource: _this.resources.riak_kv_wm_index+"/"+bucket_name+"/props",
        body: JSON.stringify({props: props})
    };
    _this.put(query, _return);
};

HTTPBackend.prototype.buckets.keys = function(bucket_name, _return) {
    var _this = this.this;

    var query = {
        resource: _this.resources.riak_kv_wm_index + "/" +bucket_name+ "/keys/",
        options: { keys: true },
        headers: { "Accept": "application/json" }
    };
    _this.get(query, _return);
};

HTTPBackend.prototype.objects = {};
HTTPBackend.prototype.objects.get = function(/* bucket_name, key, [metadata, [options]], _return */) {
    var _this = this.this;

    var bucket_name = arguments[0];
    var key = arguments[1];
    var metadata = arguments[2] || {};
    var options = arguments[3] || {};
    var _return = typeof(arguments[arguments.length - 1]) == 'function' ? arguments[arguments.length - 1] : function(){};

    var query = {
        resource: _this.resources.riak_kv_wm_index + "/" +bucket_name+ "/keys/" +key ,
        headers: HTTPBackend.metadataToHeaders(metadata),
        options: options
    };

    _this.get(query, _return);
};

HTTPBackend.prototype.objects.save = function(/* bucket_name, key, data, metadata, [options] _return */) {
    var _this = this.this;

    var bucket_name = arguments[0];
    var key = arguments[1] || "";
    var data = arguments[2];
    var metadata = arguments[3] || {};
    var options = typeof(arguments[4]) == 'object' ? arguments[4] : {};
    var _return = typeof(arguments[arguments.length - 1]) == 'function' ? arguments[arguments.length - 1] : function(){};

    var query = {
        resource: _this.resources.riak_kv_wm_index + "/" +bucket_name+ "/keys/" +key,
        headers: HTTPBackend.metadataToHeaders(metadata),
        body: data,
        options: options
    };

    if(key === "") {
        _this.post(query, _return);
    }
    else {
        _this.put(query, _return);
    }
};

HTTPBackend.prototype.objects.exists = function(/* bucket_name, key, [options] _return */) {
    var _this = this.this;

    var bucket_name = arguments[0];
    var key = arguments[1] || "";
    var options = typeof(arguments[2]) == 'object' ? arguments[2] : {};
    var _return = typeof(arguments[arguments.length - 1]) == 'function' ? arguments[arguments.length - 1] : function(){};

    var query = {
        resource: _this.resources.riak_kv_wm_index + "/" +bucket_name+ "/keys/" +key,
        options: options
    };

    _this.head(query, function(err, data, meta) {
        if(err && meta.status_code != 404) _return(err, data, meta);
        else {
            if(meta.status_code != 404) {
                _return(err, true);
            }
            else{
                _return(err, false);
            }
        }
    });
};

HTTPBackend.prototype.objects.delete = function(/* bucket_name, key, [options] _return */) {
    var _this = this.this;

    var bucket_name = arguments[0];
    var key = arguments[1] || "";
    var options = typeof(arguments[2]) == 'object' ? arguments[2] : {};
    var _return = typeof(arguments[arguments.length - 1]) == 'function' ? arguments[arguments.length - 1] : function(){};

    var query = {
        resource: _this.resources.riak_kv_wm_index + "/" +bucket_name+ "/keys/" +key,
        options: options
    };

    _this.delete(query, _return);
};

HTTPBackend.prototype.request = function(method, query, _return) {
  var req = http.request({ headers: HTTPBackend.appendDefaultHeaders(query.headers),
                           path: query.resource + HTTPBackend.appendOptions(query.options),
                           method: method,
                           host: this.host,
                           port: this.port}, HTTPBackend.responseHandler.bind(this, _return));

  req.on('error', function(error) {
    _return(error, null, null);
  });

  req.end(query.body, query.encoding || 'utf8');
};

HTTPBackend.responseHandler = function(_return, res) { // reversed signature due to bind()'s prepend behavior in request()
  var body = [];
  res.headers['status-code'] = res.statusCode;

  res.on('data', function(chunk) {
    body.push(chunk);
  });

  res.on('end', function() {
    body = Buffer.concat(body, parseInt(res.headers['content-length'], 10) || undefined);
    var err = null;

    if(res.statusCode >= 400 && res.req.method != "DELETE") {
        err = new Error();
        err.code = res.statusCode;
        err.message = body.toString();
    }

    _return(err, body, HTTPBackend.headersToMetadata(res.headers));
  });

  res.on('close', function(err){
    _return(err, body, res.headers);
  });
};

HTTPBackend.headersToMetadata = function(headers) {
  var metadata = HTTPBackend.munchHeaders(headers);

  return metadata;
};

HTTPBackend.metadataToHeaders = function(metadata) {
  var headers = HTTPBackend.munchMetadata(metadata);

  return headers;
};

HTTPBackend.appendDefaultHeaders = function(headers) {
    headers = headers || {};

    headers["Content-Type"] = headers["Content-Type"] || HTTPBackend.defaults.headers["Content-Type"];
    headers["Accept"] = headers["Accept"] || HTTPBackend.defaults.headers["Accept"];

    return headers;
};

HTTPBackend.appendOptions = function(options) {
    var temp = "";

    for(var key in options) {
        temp += key + "=" + options[key] + "&";
    }

    temp = (temp.length !== 0) ? "?"+temp : temp;

    return temp;
};

HTTPBackend.prototype.head = function(query, _return) {
  this.request('HEAD', query, _return);
};

HTTPBackend.prototype.get = function(query, _return) {
  this.request('GET', query, _return);
};

HTTPBackend.prototype.post = function(query, _return) {
  this.request('POST', query, _return);
};

HTTPBackend.prototype.put = function(query, _return) {
  this.request('PUT', query, _return);
};

HTTPBackend.prototype.delete = function(query, _return) {
  this.request('DELETE', query, _return);
};

HTTPBackend.munchHeaders = function(headers) {
  var metadata = {};

  headers = HTTPBackend.filterHeaders(headers);

  for(var key in headers) {
    var low_key = key.toLowerCase();

    if(low_key.indexOf("x-riak-")) {
      low_key = low_key.replace("-","_");
    }
    else{
      low_key = low_key.slice(7).replace("_","-");
    }

    var parts = low_key.split("-");
    parts.push(headers[key]);
    metadata = HTTPBackend.toNamespaced(metadata, parts);
  }
  return metadata;
};

HTTPBackend.filterHeaders = function(headers) {
    for(var i = 0, length = HTTPBackend.defaults.ignore_headers.length; i < length; i++) {
        if(headers[HTTPBackend.defaults.ignore_headers[i]]) {
            delete headers[HTTPBackend.defaults.ignore_headers[i].toLowerCase()];
        }
    }
    return headers;
};

HTTPBackend.munchMetadata = function(metadata, accumulator, container) {
  accumulator = accumulator || "";
  container = container || {};

  for(var prop in metadata) {
    var acc = accumulator;

    acc = (prop === "vclock" || prop === "index" || prop === "meta") ? "x-riak" : acc;

    if(metadata.hasOwnProperty(prop) && metadata[prop].constructor.name == "Object") {
      munchMetadata(metadata[prop], (acc === "") ? prop : acc + "-" + prop, container);
    }
    else {
      var value = metadata[prop].constructor.name == "Array" ? metadata[prop].join(", ") : metadata[prop];
      prop = prop.replace("_","-");

      if(acc === "") {
        container[prop] = value;
      }
      else {
        container[(prop == "int" || prop == 'bin') ? (acc + "_" + prop) : (acc + "-" + prop)] = value;
      }
    }
  }

  return container;
};

HTTPBackend.toNamespaced = function(parent, parts) {
  var namespace = parent;

  for(var i = 0, length = parts.length-1; i < length; i++) {
      if(i+1 == length) {
        parent[parts[i]] = (parts[0] == 'index') ? parts[i+1].split(", ") : parts[i+1];
      }
      else {
        parent[parts[i]] = parent[parts[i]] || {};
        parent = parent[parts[i]];
      }
  }
  return namespace;
};

HTTPBackend.defaults = {
    headers: {
        "Content-Type": "application/json",
        "Accept": "*/*"
    },
    ignore_headers: [
        "date",
        "content-length",
        "server",
        "vary"
    ],
    connection: {
        host: 'localhost',
        port: 8098
    },
    resources: {
        riak_kv_wm_buckets: "/riak",
        riak_kv_wm_index: "/buckets",
        riak_kv_wm_keylist: "/buckets",
        riak_kv_wm_link_walker: "/riak",
        riak_kv_wm_mapred: "/mapred",
        riak_kv_wm_object: "/riak",
        riak_kv_wm_ping: "/ping",
        riak_kv_wm_props: "/buckets",
        riak_kv_wm_stats: "/stats",
        riak_solr_indexer_wm: "/solr",
        riak_solr_searcher_wm: "/solr"
    }
};

module.exports = HTTPBackend;<|endoftext|>


<commit_before>'use strict'
var hash = require('../../util/hash')
/**
 * @property uid
 * injectable for generation of uids -- handy if you want weakmap-like behaviour
 * @memberOf Base#
 * @param {object} val
*/
exports.define = {
  uid: {
    get () {
      if (!this.hasOwnProperty('_uid')) {
        if (this._parent) {
          let parent = this
          let str = ''
          while (parent && parent.key) {
            str += parent.key
            parent = parent._parent
          }
          // have to do this smarter -- make this when .engine in element before that its irrelevant anyways
          console.log('yo!', str, hash(str), this.path.join('.'))
          this._uid = hash(str) // hash // will create collisions -- so thats not so good -- make entry points on val?
        }
      }
      return this._uid
    }
  },
  getHashedPath (cache) {
    // console.log('get cache!', this.path.join('.'), 'cntx:', this._context && this._context._path.join('.'))
    if (this._context) {
      if (!cache) {
        cache = this.contextMap()
      }
      if (cache.val) {
        return cache.val
      }
      let parent = this
      let str = ''
      while (parent && parent.key) {
        str += parent.key
        let lparent = parent
        let cntx = parent._context
        let level = parent._contextLevel
        parent = parent.parent
        if (lparent._context !== cntx) {
          lparent._context = cntx || null
          lparent._contextLevel = level || null
        }
      }
      cache.val = hash(str)
      // console.log(this.path.join('.'), hash(this.path.join('.')))
      // return hash(this.path.join('.')) // cache.val
      return cache.val
    } else {
      return this.uid
    }
  }
}
<commit_msg>best temp fix for hah uid (make better later!)<commit_after>'use strict'
var hash = require('../../util/hash')
/**
 * @property uid
 * injectable for generation of uids -- handy if you want weakmap-like behaviour
 * @memberOf Base#
 * @param {object} val
*/
var cnt = 0
exports.define = {
  uid: {
    get () {
      if (!this.hasOwnProperty('_uid')) {
        if (this._parent) {
          let parent = this
          let str = ''
          while (parent && parent.key) {
            str += parent.key
            parent = parent._parent
          }
          // have to do this smarter -- make this when .engine in element before that its irrelevant anyways
          console.log('yo!', str, hash(str), this.path.join('.'))
          this._uid = hash(str) // hash // will create collisions -- so thats not so good -- make entry points on val?
        }
      }
      return this._uid || 0// 'h' + (++cnt)
    }
  },
  getHashedPath (cache) {
    // console.log('get cache!', this.path.join('.'), 'cntx:', this._context && this._context._path.join('.'))
    if (this._context) {
      if (!cache) {
        cache = this.contextMap()
      }
      if (cache.val) {
        return cache.val
      }
      let parent = this
      let str = ''
      while (parent && parent.key) {
        str += parent.key
        let lparent = parent
        let cntx = parent._context
        let level = parent._contextLevel
        parent = parent.parent
        if (lparent._context !== cntx) {
          lparent._context = cntx || null
          lparent._contextLevel = level || null
        }
      }
      cache.val = hash(str)
      // console.log(this.path.join('.'), hash(this.path.join('.')))
      // return hash(this.path.join('.')) // cache.val
      return cache.val
    } else {
      return this.uid
    }
  }
}
<|endoftext|>


<commit_before>// ==UserScript==
// @name         Vola Timestamps
// @namespace    http://not.jew.dance/
// @version      1.0
// @description  Dongo said to make this
// @author       RealDolos
// @match        https://volafile.io/r/*
// @grant        none
// @require      https://rawgit.com/RealDolos/volascripts/064d22df5566bda12d222822584b87dcc6a43d45/dry.js
// @run-at       document-start
// ==/UserScript==

dry.once("dom", () => {
    "use strict";
    console.log("running", GM_info.script.name, GM_info.script.version, dry.version);

    const style = document.createElement("style");
    style.textContent = `
.username.timestamp {
  -moz-user-select: none;
  user-select: none;
  display: inline-block;
  /*padding: 0;*/
  whites-pace: pre-wrap;
}
[timestamps="false"] .username.timestamp {
  display: none;
}
`;
    document.body.appendChild(style);

    const config_key = `${dry.config.room_id}-timestamps`;
    let enabled = localStorage.getItem(config_key);
    enabled = enabled !== "disabled";

    dry.replaceEarly("chat", "showMessage", function(orig, nick, message, options, ...args) {
        if (!options.timestamp) {
            options.timestamp = Date.now();
        }
        return orig(...[nick, message, options].concat(args));
    });
    dry.replaceEarly("chat", "addMessage", function(orig, m, ...args) {
        try {
            if (m.nick && m.options && m.options.timestamp) {
                let span = document.createElement("span");
                span.classList.add("timestamp", "username");
                let d = new Date(m.options.timestamp);
                span.textContent = d.toLocaleString("en-US", {
                    hour12: false,
                    hour: "2-digit",
                    minute: "2-digit",
                    second: "2-digit",
                }) + " |";
                span.setAttribute("title", d.toLocaleString("eu"));
                m.timestamp_elem = span;
                m.elem.insertBefore(span, m.elem.firstChild);
            }
        }
        catch (ex) {
            console.error(m, ex);
        }
        return orig(...[m].concat(args));
    });
    new class extends dry.Commands {
        ts(e) {
            enabled = !enabled;
            localStorage.setItem(config_key, enabled ? "enabled" : "disabled");
            document.body.setAttribute("timestamps", "" + enabled);
            return true;
        }
    }();
});
<commit_msg>new dry<commit_after>// ==UserScript==
// @name         Vola Timestamps
// @namespace    http://not.jew.dance/
// @version      1.1
// @description  Dongo said to make this
// @author       RealDolos
// @match        https://volafile.io/r/*
// @grant        none
// @require      https://rawgit.com/RealDolos/volascripts/db222e0a836c6da9d5593c7fc93941c0e7a9d2a1/dry.js
// @run-at       document-start
// ==/UserScript==

dry.once("dom", () => {
    "use strict";
    console.log("running", GM_info.script.name, GM_info.script.version, dry.version);

    const style = document.createElement("style");
    style.textContent = `
.username.timestamp {
  -moz-user-select: none;
  user-select: none;
  display: inline-block;
}
[timestamps="false"] .username.timestamp {
  display: none;
}
`;
    document.body.appendChild(style);

    const config_key = `${dry.config.room_id}-timestamps`;
    let enabled = localStorage.getItem(config_key);
    enabled = enabled !== "disabled";

    new class extends dry.MessageFilter {
        showMessage(orig, nick, message, options) {
            if (!options.timestamp) {
                options.timestamp = Date.now();
            }
        }
        addMessage(orig, m) {
            if (!m.nick || !m.options || !m.options.timestamp) {
                return;
            }
            let span = document.createElement("span");
            span.classList.add("timestamp", "username");
            let d = new Date(m.options.timestamp);
            span.textContent = d.toLocaleString("en-US", {
                hour12: false,
                hour: "2-digit",
                minute: "2-digit",
                second: "2-digit",
            }) + " |";
            span.setAttribute("title", d.toLocaleString("eu"));
            m.timestamp_elem = span;
            m.elem.insertBefore(span, m.elem.firstChild);
        }
    }();
    new class extends dry.Commands {
        ts(e) {
            enabled = !enabled;
            localStorage.setItem(config_key, enabled ? "enabled" : "disabled");
            document.body.setAttribute("timestamps", "" + enabled);
            return true;
        }
    }();
});
<|endoftext|>


<commit_before>class GithubUserData { // eslint-disable-line
  constructor() {
    this.followers = [];
    this.following = [];
    this.repositories = [];
  }

  addFollowers(newFollowers) {
    this.followers = this.followers.concat(newFollowers);
  }

  addFollowing(newFollowing) {
    this.following = this.following.concat(newFollowing);
  }

  addRepositories(newRepositories) {
    this.repositories = this.repositories.concat(newRepositories);
  }

  getRepositories() {
    return this.repositories;
  }
}

export default GithubUserData;
<commit_msg>User data model updated<commit_after>class GithubUserData { // eslint-disable-line
  constructor() {
    this.followers = [];
    this.following = [];
    this.repositories = [];
    this.similarityPercentages = [];
  }

  addFollowers(newFollowers) {
    this.followers = this.followers.concat(newFollowers);
  }

  addFollowing(newFollowing) {
    this.following = this.following.concat(newFollowing);
  }

  addRepositories(newRepositories) {
    this.repositories = this.repositories.concat(newRepositories);
  }

  addSimilarityPercentage(username, percentage) {
    this.similarityPercentages[username] = percentage;
  }

  getRepositories() {
    return this.repositories;
  }
}

export default GithubUserData;
<|endoftext|>


<commit_before>self.onfetch = function(event) {
  console.log('got a request');

  var salutation = 'Hello, ';
  var whom = decodeURIComponent(event.request.url.match(/\/([^/]*)$/)[1]);
  var energyLevel = (whom === 'Cleveland') ? '!!!' : '!';
  var version = '\n\n(Version 1)';

  var body = new Blob([salutation, whom, energyLevel, version]);

  event.respondWith(new Response(body));
};
<commit_msg>Update sample for consistency<commit_after>self.addEventListener("fetch",  function(event) {
  console.log('got a request');

  var salutation = 'Hello, ';
  var whom = decodeURIComponent(event.request.url.match(/\/([^/]*)$/)[1]);
  var energyLevel = (whom === 'Cleveland') ? '!!!' : '!';
  var version = '\n\n(Version 1)';

  var body = new Blob([salutation, whom, energyLevel, version]);

  event.respondWith(new Response(body));
});
<|endoftext|>


<commit_before>/**
 * Module dependencies.
 */
var pkginfo = require('pkginfo')
  , os = require('os')
  , uri = require('url')
  , path = require('path')
  , fs = require('fs')
  , existsSync = fs.existsSync || path.existsSync; // <=0.6

var internals = {};

/**
 * Component-ized boot phase that announces services.
 *
 * To utilize this component within an application, configure the IoC loader
 * to use common service discovery components.
 *
 *     IoC.loader(require('bixby-sd'));
 *
 * @param {Settings} settings
 * @param {Logger} logger
 * @return {Function}
 */
exports = module.exports = function(registry, settings, logger) {

  return function announce(done) {
    var config = settings.get('sd/announce') || {};
    if (!config.domain) { throw new Error('Misconfigured service announcement: missing domain'); }

    var root = path.dirname(pkginfo.find(require.main))
      , file = path.resolve(root, 'app/services.json')
      , domain = config.domain
      , port, address, protocol
      , addresses;

    if (!existsSync(file)) { return done(new Error('No such file "' + file + '"')); }

    if (this.httpServer || this.httpsServer) {
      var server = this.httpsServer || this.httpServer
        , addr = server.address();

      protocol = this.httpsServer ? 'https' : 'http';
      address = addr.address
      port = addr.port
    } else {
      return done(new Error('Unable to determine address of server'));
    }

    if (address == '0.0.0.0') {
      addresses = internals.ips('IPv4');
    } else {
      addresses = [ address ];
    }

    var data = fs.readFileSync(file, 'utf8')
      , services;
    try {
      services = JSON.parse(data);
    } catch (_) {
      return done(new Error('Failed to parse services'));
    }

    // For each service offered by the application, announce it's availability
    // on all addresses.
    var types = Object.keys(services)
      , sidx = 0;

    function siter(err) {
      if (err) { return done(err); }

      var type = types[sidx++];
      if (!type) { return done(); }

      var target = services[type]
        , aidx = 0;

      function aiter(err) {
        if (err) { return siter(err); }

        var address = addresses[aidx++];
        if (!address) { return siter(); }

        var record;
        if (typeof target == 'boolean') {
          if (/^[a-f0-9:]+$/.test(address)) {
            record = '[' + address + ']:' + port;  // IPv6
          } else {
            record = address + ':' + port;  // IPv4
          }
        } else if (typeof target == 'string') {
          record = uri.format({ protocol: protocol, hostname: address, port: port, pathname: target });
        } else {
          aiter(new Error('Invalid record for service "' + type + '"'));
        }

        logger.info('Announcing service %s in %s at %s', type, domain, record);
        registry.announce(domain, type, record, function(err) {
          if (err) { return aiter(err); }
          return aiter();
        });
      }
      aiter();
    }
    siter();
  }
}

internals.ips = function(fams, devs) {
  if (fams && !Array.isArray(fams)) { fams = [ fams ] }
  if (devs && !Array.isArray(devs)) { devs = [ devs ] }

  var arr = []
    , nics = os.networkInterfaces()
    , nic, dev, addr, i, len;

  for (dev in nics) {
    if (devs && devs.indexOf(dev) == -1) { continue; }

    nic = nics[dev];
    for (i = 0, len = nic.length; i < len; ++i) {
      addr = nic[i];
      if (addr.internal) { continue; }
      if (fams && fams.indexOf(addr.family) == -1) { continue; }
      arr.push(addr.address);
    }
  }
  return arr;
}

/**
 * Component annotations.
 */
exports['@require'] = [ '../registry', 'settings', 'logger' ];
<commit_msg>Service discovery domain is configured directly under sd key.<commit_after>/**
 * Module dependencies.
 */
var pkginfo = require('pkginfo')
  , os = require('os')
  , uri = require('url')
  , path = require('path')
  , fs = require('fs')
  , existsSync = fs.existsSync || path.existsSync; // <=0.6

var internals = {};

/**
 * Component-ized boot phase that announces services.
 *
 * To utilize this component within an application, configure the IoC loader
 * to use common service discovery components.
 *
 *     IoC.loader(require('bixby-sd'));
 *
 * @param {Settings} settings
 * @param {Logger} logger
 * @return {Function}
 */
exports = module.exports = function(registry, settings, logger) {

  return function announce(done) {
    var config = settings.get('sd') || {};
    if (!config.domain) { throw new Error('Misconfigured service announcement: missing domain'); }

    var root = path.dirname(pkginfo.find(require.main))
      , file = path.resolve(root, 'app/services.json')
      , domain = config.domain
      , port, address, protocol
      , addresses;

    if (!existsSync(file)) { return done(new Error('No such file "' + file + '"')); }

    if (this.httpServer || this.httpsServer) {
      var server = this.httpsServer || this.httpServer
        , addr = server.address();

      protocol = this.httpsServer ? 'https' : 'http';
      address = addr.address
      port = addr.port
    } else {
      return done(new Error('Unable to determine address of server'));
    }

    if (address == '0.0.0.0') {
      addresses = internals.ips('IPv4');
    } else {
      addresses = [ address ];
    }

    var data = fs.readFileSync(file, 'utf8')
      , services;
    try {
      services = JSON.parse(data);
    } catch (_) {
      return done(new Error('Failed to parse services'));
    }

    // For each service offered by the application, announce it's availability
    // on all addresses.
    var types = Object.keys(services)
      , sidx = 0;

    function siter(err) {
      if (err) { return done(err); }

      var type = types[sidx++];
      if (!type) { return done(); }

      var target = services[type]
        , aidx = 0;

      function aiter(err) {
        if (err) { return siter(err); }

        var address = addresses[aidx++];
        if (!address) { return siter(); }

        var record;
        if (typeof target == 'boolean') {
          if (/^[a-f0-9:]+$/.test(address)) {
            record = '[' + address + ']:' + port;  // IPv6
          } else {
            record = address + ':' + port;  // IPv4
          }
        } else if (typeof target == 'string') {
          record = uri.format({ protocol: protocol, hostname: address, port: port, pathname: target });
        } else {
          aiter(new Error('Invalid record for service "' + type + '"'));
        }

        logger.info('Announcing service %s in %s at %s', type, domain, record);
        registry.announce(domain, type, record, function(err) {
          if (err) { return aiter(err); }
          return aiter();
        });
      }
      aiter();
    }
    siter();
  }
}

internals.ips = function(fams, devs) {
  if (fams && !Array.isArray(fams)) { fams = [ fams ] }
  if (devs && !Array.isArray(devs)) { devs = [ devs ] }

  var arr = []
    , nics = os.networkInterfaces()
    , nic, dev, addr, i, len;

  for (dev in nics) {
    if (devs && devs.indexOf(dev) == -1) { continue; }

    nic = nics[dev];
    for (i = 0, len = nic.length; i < len; ++i) {
      addr = nic[i];
      if (addr.internal) { continue; }
      if (fams && fams.indexOf(addr.family) == -1) { continue; }
      arr.push(addr.address);
    }
  }
  return arr;
}

/**
 * Component annotations.
 */
exports['@require'] = [ '../registry', 'settings', 'logger' ];
<|endoftext|>


<commit_before>// @flow weak
var config = require('config');
var mysql = require('mysql');
var async = require('async');
var pool = mysql.createPool(config.database_config);

var db_client = function() {

}

db_client.prototype.registerDevice = function(args, callback) {
    pool.getConnection(function(err, connection) {
        connection.query('call register_device(?,?,?,?)', [
            args.Device,
            args.Class,
            args.ClassVer,
            args.Network
        ], function(error, results, fields) {
            if (err) callback(error);
            if (results == null)
                callback('Device already registered!')
            else
                callback(null, results);
            connection.release();
        });
    });
}

db_client.prototype.showDevices = function(callback) {
    pool.getConnection(function(err, connection) {
        if (err) console.log(err);
        connection.query('call show_devices()', function(error, results, fields) {
            if (err) throw err(error);
            callback(null, results[0]);
            connection.release();
        });
    });
}

db_client.prototype.logData = function(args, callback) {
    pool.getConnection(function(err, connection) {
        //console.log("ARGUMEEEEEEENNNTTTSSS!")
        console.log([args.Device, args.power, args.energy]);
        if (err) console.log(err);
        connection.query('call log_data(?,?,?)', [args.Device, args.power, args.energy], function(error, results, fields) {
            if (results != null)
                callback(null, results);
            else {
                callback('Data not writen!');
            }
            connection.release();
        });
    });
}

db_client.prototype.getHourlyData = function(args,callback) {
    var result = [];
    var hours = [{
        begin: '00:00:01',end:'01:00:00'
    },{
        begin: '01:00:01',end:'02:00:00'
    },{
        begin: '02:00:01',end:'03:00:00'
    },{
        begin: '03:00:01',end:'04:00:00'
    },{
        begin: '04:00:01',end:'05:00:00'
    },{
        begin: '05:00:01',end:'06:00:00'
    },{
        begin: '06:00:01',end:'07:00:00'
    },{
        begin: '07:00:01',end:'08:00:00'
    },{
        begin: '08:00:01',end:'09:00:00'
    },{
        begin: '09:00:01',end:'10:00:00'
    },{
        begin: '10:00:01',end:'11:00:00'
    },{
        begin: '11:00:01',end:'12:00:00'
    },{
        begin: '12:00:01',end:'13:00:00'
    },{
        begin: '13:00:01',end:'14:00:00'
    },{
        begin: '14:00:01',end:'15:00:00'
    },{
        begin: '15:00:01',end:'16:00:00'
    },{
        begin: '16:00:01',end:'17:00:00'
    },{
        begin: '17:00:01',end:'18:00:00'
    },{
        begin: '18:00:01',end:'19:00:00'
    },{
        begin: '19:00:01',end:'20:00:00'
    },{
        begin: '20:00:01',end:'21:00:00'
    },{
        begin: '21:00:01',end:'22:00:00'
    },{
        begin: '22:00:01',end:'23:00:00'
    },{
        begin: '23:00:01',end:'23:59:59'
    },];
    async.eachSeries(hours, function(hour, callback) {
        //console.log(date + ' ' + hour.begin+'   '+date + ' ' + hour.end);
        pool.getConnection(function(err, connection) {
            connection.query('call get_data(?,?,?)', [
                args.Device,
                args.Date + ' ' + hour.begin,
                args.Date + ' ' + hour.end
            ], function(error, results, fields) {
                if (err) callback(error);

                var string = JSON.stringify(results[0]);
                var jsoned = JSON.parse(string);
                result.push({"power":jsoned[0].power,"energy":jsoned[0].energy,"time":args.Date + ' ' + hour.begin});
                connection.release();
                callback(null)
            });
        });
    }, function(err, res) {
        if (err) callback(err);
        callback(null,result);
    });

}

module.exports = db_client;
<commit_msg><commit_after>// @flow weak
var config = require('config');
var mysql = require('mysql');
var async = require('async');
var pool = mysql.createPool(config.database_config);

var db_client = function() {

}

db_client.prototype.registerDevice = function(args, callback) {
    pool.getConnection(function(err, connection) {
        connection.query('call register_device(?,?,?,?)', [
            args.Device,
            args.Class,
            args.ClassVer,
            args.Network
        ], function(error, results, fields) {
            if (err) callback(error);
            if (results == null)
                callback('Device already registered!')
            else
                callback(null, results);
            connection.release();
        });
    });
}

db_client.prototype.showDevices = function(callback) {
    pool.getConnection(function(err, connection) {
        if (err) console.log(err);
        connection.query('call show_devices()', function(error, results, fields) {
            if (err) throw err(error);
            callback(null, {
                Device: results[0].DEV_NAME,
                class: results[0].CLASS_NAME,
                network: results[0].NETWORK_NAME,
                classVer: results[0].VER
            });
            connection.release();
        });
    });
}

db_client.prototype.logData = function(args, callback) {
    pool.getConnection(function(err, connection) {
        //console.log("ARGUMEEEEEEENNNTTTSSS!")
        console.log([args.Device, args.power, args.energy]);
        if (err) console.log(err);
        connection.query('call log_data(?,?,?)', [args.Device, args.power, args.energy], function(error, results, fields) {
            if (results != null)
                callback(null, results);
            else {
                callback('Data not writen!');
            }
            connection.release();
        });
    });
}

db_client.prototype.getHourlyData = function(args, callback) {
    var result = [];
    var hours = [{
        begin: '00:00:01',
        end: '01:00:00'
    }, {
        begin: '01:00:01',
        end: '02:00:00'
    }, {
        begin: '02:00:01',
        end: '03:00:00'
    }, {
        begin: '03:00:01',
        end: '04:00:00'
    }, {
        begin: '04:00:01',
        end: '05:00:00'
    }, {
        begin: '05:00:01',
        end: '06:00:00'
    }, {
        begin: '06:00:01',
        end: '07:00:00'
    }, {
        begin: '07:00:01',
        end: '08:00:00'
    }, {
        begin: '08:00:01',
        end: '09:00:00'
    }, {
        begin: '09:00:01',
        end: '10:00:00'
    }, {
        begin: '10:00:01',
        end: '11:00:00'
    }, {
        begin: '11:00:01',
        end: '12:00:00'
    }, {
        begin: '12:00:01',
        end: '13:00:00'
    }, {
        begin: '13:00:01',
        end: '14:00:00'
    }, {
        begin: '14:00:01',
        end: '15:00:00'
    }, {
        begin: '15:00:01',
        end: '16:00:00'
    }, {
        begin: '16:00:01',
        end: '17:00:00'
    }, {
        begin: '17:00:01',
        end: '18:00:00'
    }, {
        begin: '18:00:01',
        end: '19:00:00'
    }, {
        begin: '19:00:01',
        end: '20:00:00'
    }, {
        begin: '20:00:01',
        end: '21:00:00'
    }, {
        begin: '21:00:01',
        end: '22:00:00'
    }, {
        begin: '22:00:01',
        end: '23:00:00'
    }, {
        begin: '23:00:01',
        end: '23:59:59'
    }, ];
    async.eachSeries(hours, function(hour, callback) {
        //console.log(date + ' ' + hour.begin+'   '+date + ' ' + hour.end);
        pool.getConnection(function(err, connection) {
            connection.query('call get_data(?,?,?)', [
                args.Device,
                args.Date + ' ' + hour.begin,
                args.Date + ' ' + hour.end
            ], function(error, results, fields) {
                if (err) callback(error);

                var string = JSON.stringify(results[0]);
                var jsoned = JSON.parse(string);
                result.push({
                    "power": jsoned[0].power,
                    "energy": jsoned[0].energy,
                    "time": args.Date + ' ' + hour.begin
                });
                connection.release();
                callback(null)
            });
        });
    }, function(err, res) {
        if (err) callback(err);
        callback(null, result);
    });

}

module.exports = db_client;
<|endoftext|>


<commit_before>'use strict';

var path = require('path');
var events = require('events');
var fs = require('fs');
var Q = require('q');
var semver = require('semver');
var nodecgVersion = require('../../package.json').version;
var watcher = require('./watcher.js');
var parseBundle = require('nodecg-bundle-parser');
var installNpmDeps = require('./dep_installers/npm');
var installBowerDeps = require('./dep_installers/bower');
var log = require('../logger')('nodecg/lib/bundles');

exports = module.exports = new events.EventEmitter();

var _bundles = [];

log.trace('Loading bundles');

// Create the "bundles" dir if it does not exist
if (!fs.existsSync('bundles/')) {
    fs.mkdirSync('bundles');
}

// Do an initial load of each bundle in the "bundles" folder.
// During runtime, any changes to a bundle's "dashboard" folder will trigger a re-load of that bundle.
var depInstallerPromises = [];
fs.readdirSync('bundles/').forEach(function(bundleFolderName) {
    var bundlePath = path.resolve('bundles/' + bundleFolderName);
    if (!fs.statSync(bundlePath).isDirectory()) return;

    // Parse each bundle and push the result onto the _bundles array
    var bundle;
    var bundleCfgPath = path.resolve('cfg/', bundleFolderName + '.json');
    if (fs.existsSync(bundleCfgPath)) {
        bundle = parseBundle(bundlePath, bundleCfgPath);
    } else {
        bundle = parseBundle(bundlePath);
    }

    // Check if the bundle is compatible with this version of NodeCG
    if (!semver.satisfies(nodecgVersion, bundle.compatibleRange)) {
        log.error('%s requires NodeCG version %s, current version is %s',
            bundle.name, bundle.compatibleRange, nodecgVersion);
        return;
    }

    // TODO: make this error better explain why a bundle might be undefined
    if (typeof bundle === 'undefined') {
        log.error('Could not load bundle in directory', bundleFolderName);
        return;
    }

    _bundles.push(bundle);

    // TODO make this all happen in series, fuck `syncNpm`.
    var npmPromise = installNpmDeps(bundle);
    var bowerPromise = installBowerDeps(bundle);
    depInstallerPromises.push(npmPromise, bowerPromise);
});

// Once all the dependency installation have been resolved, start up the bundle watcher and emit "allLoaded"
Q.all(depInstallerPromises)
    .then(function() {
        watcher.on('bundleChanged', function (name) {
            var bundle = exports.find(name);
            if (!bundle) return;
            var reparsedBundle = parseBundle(bundle.dir);
            _replaceBundle(name, reparsedBundle);
            exports.emit('bundleChanged', bundle);
        });

        watcher.on('bundleRemoved', function(name) {
            log.info('%s\'s package.json can no longer be found on disk, ' +
                'assuming the bundle has been deleted or moved', name);
            exports.remove(name);
        });

        exports.emit('allLoaded', exports.all());
    })
    .fail(function(err) {
        log.error(err.stack);
    });

exports.all = function() {
    // return a clone of the array, not a reference to it
    return _bundles.slice(0);
};

exports.find = function(name) {
    var len = _bundles.length;
    for (var i = 0; i < len; i++) {
        if (_bundles[i].name === name) return _bundles[i];
    }
};

exports.add = function(bundle) {
    // If the parser rejects a bundle for some reason (such as a NodeCG version mismatch), it will be null
    if(!bundle) return;
    if (this.find(bundle.name)) this.remove(bundle.name); // remove any existing bundles with this name
    _bundles.push(bundle);
};

exports.remove = function(bundleName) {
    var len = _bundles.length;
    for (var i = 0; i < len; i++) {
        // TODO: this check shouldn't have to happen, idk why things in this array can sometimes be undefined
        if (!_bundles[i]) continue;
        if (_bundles[i].name === bundleName) _bundles.splice(i, 1);
    }
};

// Replaces bundle with the specified "name" with "newBundle"
// If no bundle with this name is found, pushes "newBundle" onto the end of the _bundles array.
function _replaceBundle(name, newBundle) {
    var len = _bundles.length;
    var existingIndex;
    for (var i = 0; i < len; i++) {
        if (_bundles[i].name === name) {
            existingIndex = i;
            break;
        }
    }

    if (existingIndex >= 0) {
        _bundles.splice(existingIndex, 1, newBundle);
    } else {
        _bundles.push(newBundle);
    }
}
<commit_msg>[bundles] Fix `bundleConfig` being lost whenever a bundle was reparsed<commit_after>'use strict';

var path = require('path');
var events = require('events');
var fs = require('fs');
var Q = require('q');
var semver = require('semver');
var nodecgVersion = require('../../package.json').version;
var watcher = require('./watcher.js');
var parseBundle = require('nodecg-bundle-parser');
var installNpmDeps = require('./dep_installers/npm');
var installBowerDeps = require('./dep_installers/bower');
var log = require('../logger')('nodecg/lib/bundles');

exports = module.exports = new events.EventEmitter();

var _bundles = [];

log.trace('Loading bundles');

// Create the "bundles" dir if it does not exist
if (!fs.existsSync('bundles/')) {
    fs.mkdirSync('bundles');
}

// Do an initial load of each bundle in the "bundles" folder.
// During runtime, any changes to a bundle's "dashboard" folder will trigger a re-load of that bundle.
var depInstallerPromises = [];
fs.readdirSync('bundles/').forEach(function(bundleFolderName) {
    var bundlePath = path.resolve('bundles/' + bundleFolderName);
    if (!fs.statSync(bundlePath).isDirectory()) return;

    // Parse each bundle and push the result onto the _bundles array
    var bundle;
    var bundleCfgPath = path.resolve('cfg/', bundleFolderName + '.json');
    if (fs.existsSync(bundleCfgPath)) {
        bundle = parseBundle(bundlePath, bundleCfgPath);
    } else {
        bundle = parseBundle(bundlePath);
    }

    // Check if the bundle is compatible with this version of NodeCG
    if (!semver.satisfies(nodecgVersion, bundle.compatibleRange)) {
        log.error('%s requires NodeCG version %s, current version is %s',
            bundle.name, bundle.compatibleRange, nodecgVersion);
        return;
    }

    // TODO: make this error better explain why a bundle might be undefined
    if (typeof bundle === 'undefined') {
        log.error('Could not load bundle in directory', bundleFolderName);
        return;
    }

    _bundles.push(bundle);

    // TODO make this all happen in series, fuck `syncNpm`.
    var npmPromise = installNpmDeps(bundle);
    var bowerPromise = installBowerDeps(bundle);
    depInstallerPromises.push(npmPromise, bowerPromise);
});

// Once all the dependency installation have been resolved, start up the bundle watcher and emit "allLoaded"
Q.all(depInstallerPromises)
    .then(function() {
        watcher.on('bundleChanged', function (name) {
            var bundle = exports.find(name);
            if (!bundle) return;

            var reparsedBundle;
            var bundleCfgPath = path.resolve('cfg/', bundle.name + '.json');
            if (fs.existsSync(bundleCfgPath)) {
                reparsedBundle = parseBundle(bundle.dir, bundleCfgPath);
            } else {
                reparsedBundle = parseBundle(bundle.dir);
            }

            _replaceBundle(name, reparsedBundle);
            exports.emit('bundleChanged', bundle);
        });

        watcher.on('bundleRemoved', function(name) {
            log.info('%s\'s package.json can no longer be found on disk, ' +
                'assuming the bundle has been deleted or moved', name);
            exports.remove(name);
        });

        exports.emit('allLoaded', exports.all());
    })
    .fail(function(err) {
        log.error(err.stack);
    });

exports.all = function() {
    // return a clone of the array, not a reference to it
    return _bundles.slice(0);
};

exports.find = function(name) {
    var len = _bundles.length;
    for (var i = 0; i < len; i++) {
        if (_bundles[i].name === name) return _bundles[i];
    }
};

exports.add = function(bundle) {
    // If the parser rejects a bundle for some reason (such as a NodeCG version mismatch), it will be null
    if(!bundle) return;
    if (this.find(bundle.name)) this.remove(bundle.name); // remove any existing bundles with this name
    _bundles.push(bundle);
};

exports.remove = function(bundleName) {
    var len = _bundles.length;
    for (var i = 0; i < len; i++) {
        // TODO: this check shouldn't have to happen, idk why things in this array can sometimes be undefined
        if (!_bundles[i]) continue;
        if (_bundles[i].name === bundleName) _bundles.splice(i, 1);
    }
};

// Replaces bundle with the specified "name" with "newBundle"
// If no bundle with this name is found, pushes "newBundle" onto the end of the _bundles array.
function _replaceBundle(name, newBundle) {
    var len = _bundles.length;
    var existingIndex;
    for (var i = 0; i < len; i++) {
        if (_bundles[i].name === name) {
            existingIndex = i;
            break;
        }
    }

    if (existingIndex >= 0) {
        _bundles.splice(existingIndex, 1, newBundle);
    } else {
        _bundles.push(newBundle);
    }
}
<|endoftext|>


<commit_before>function ddg_spice_yoga_asanas(apiResult) {

    var numFound = apiResult.response.numFound,
        docs = apiResult.response.docs,
        i,
        seen = {},
        d,
        seen_key,
        deDuped = [];

    if (!apiResult || !numFound) {
        return Spice.failed('yoga_asanas');
    }

    //de-dupe by default
    for(i = 0;i < numFound; i++){
        d = docs[i];
        d.meta = eval("(" + d.meta + ")");
        seen_key = d.title + d.meta.srcName;
        if(seen_key in seen){
            continue;
        }
        else{
            deDuped.push(d);
            seen[seen_key] = true;
        }
    }

    // unde-dupe if it's a sequence
    if( (docs[docs.length - 1].meta.order - docs[0].meta.order) == (numFound - 1) ){
        deDuped = docs;
    }

    Spice.add({
        id: 'yoga_asanas',
        name: 'Yoga Asanas',

        data: deDuped,
        normalize: function(a){
            var meta = a.meta;
            delete a.meta;

            return {
                image: meta.img,
                title: a.title,
                altSubtitle: a.paragraph,
                srcName: meta.srcName,
                srcUrl: meta.srcUrl,
                srcIcon: meta.favicon
            };
        },

        templates: {
            group: 'media',
            item_detail: false,
            detail: false,
            options: {
                moreAt: false,
                footer: Spice.yoga_asanas.footer
            }
        },

    });
}
<commit_msg>Let dup do the de-duping<commit_after>function ddg_spice_yoga_asanas(apiResult) {
    var numFound,
        docs,
        i,
        seen = {},
        d,
        seen_key,
        asanas = {};

    if (!apiResult || !apiResult.response.numFound) {
        return Spice.failed('yoga_asanas');
    }

    numFound = apiResult.response.numFound;
    docs = apiResult.response.docs;

    console.log("docs: ", docs);
    console.log("meta 0: ". docs);
    asanas = {
        id: 'yoga_asanas',
        name: 'Yoga Asanas',

        data: docs,
        templates: {
            group: 'media',
            item_detail: false,
            detail: false,
            options: {
                moreAt: true,
                footer: Spice.yoga_asanas.footer
            }
        }
    };

    console.log("asanas.data: ", asanas.data);
    console.log("order diff: ",docs[docs.length - 1].meta.order - docs[0].meta.order);
    console.log("numFound: ", numFound);
    // if not a sequence de-dupe
    if(!((docs[docs.length - 1].meta.order - docs[0].meta.order) == (numFound - 1))){
        asanas.relevancy = {dup: ['title', 'srcName']};
    }

    asanas.normalize =  function(a){
            var meta = a.meta;
            delete a.meta;

            return {
                image: meta.img,
                title: a.title,
                altSubtitle: a.paragraph,
                url: meta.srcUrl,
                srcName: meta.srcName,
                srcUrl: meta.srcUrl,
                srcIcon: meta.favicon
            };
        };

    Spice.add(asanas);
}
<|endoftext|>