<commit_before>var request = require('request'),
  _ = require('underscore');

/*
* Function defining a Bamboo instance
*
*   @param {String} hostname. E.g. "http://hostname.com:8085"
*/
function Bamboo(host) {
  this.host = host || "http://localhost:8085";
}

/*
* Returns the latest successful build number
*
*   @return {String} build number
*   @param {String} planKey. Bamboo plan key name
*   @return {String} params. Query string. E.g. "?start-index=25"
*   @param {String} callback. Executed when the remote JSON has been parsed.
*/
Bamboo.prototype.getLatestSuccessfulBuilNumber = function(planKey, params, callback) {
  var self = this,
    planUri = self.host + "/rest/api/latest/result/" + planKey + ".json";
  planUri += (params) ? params : "";

  request({ uri: planUri }, function (error, response, body) {

    var errors = checkErrors(error, response);
    if (errors) {
      callback(errors);
      return false;
    }

    var bodyJson = JSON.parse(response.body),
      results = bodyJson.results,
      result = results.result,
      build_no = "",
      isSearching = false;

    // Search for the latest 'Successful' build
    for (var i = 0, len = result.length; i < len; i ++){
      var resultEl = result[i];

      if (resultEl.state === "Successful") {
        build_no = resultEl.number;
        callback(build_no);
        return;
      }
    }

    // Loop through the next series of builds
    var newIndex = results["max-result"] + results["start-index"];
    if (newIndex < results.size) {
      isSearching = true;
      self.getLatestSuccessfulBuilNumber(planKey, "?start-index=" + newIndex, function(result){
        callback(result);
        return;
      });
    } else {
      isSearching = false;
    }

    if (!build_no && !isSearching) {
      callback("The plan doesn't contain any successful build");
    }
    });
};

/*
* Returns the latest build status
*
*   @return {String} build number
*   @param {String} planKey. Bamboo plan key name
*   @param {String} callback. Executed when the remote JSON has been parsed.
*/
Bamboo.prototype.getLatestBuildStatus = function(planKey, callback) {
  var self = this,
    planUri = self.host + "/rest/api/latest/result/" + planKey + ".json";

  request({ uri: planUri }, function (error, response, body) {
    var errors = checkErrors(error, response);

    if (errors) {
      callback(errors);
      return false;
    }

    var bodyJson = JSON.parse(response.body),
      results = bodyJson.results,
      last_result = results.result[0];

    callback(last_result.state, last_result.number);
  });
};

/*
* Returns the status of the build
*
*   @param {String} buildDetails. Bamboo plan key name + build number
*   @param {String} callback. Executed when the remote JSON has been parsed.
*/
Bamboo.prototype.getBuildStatus = function(buildDetails, callback) {
  var self = this,
    planUri = self.host + "/rest/api/latest/result/" + buildDetails + ".json";

  request({ uri: planUri }, function (error, response, body) {
    if (error || response.statusCode !== 200) {
      callback("Unreachable endpoint");
      return false;
    }

    var bodyJson = JSON.parse(response.body),
      result = bodyJson.lifeCycleState;

    callback(result);
  });
};

/*
* Returns the changes associated to a specific build. It also considers a dependent plan recursevely
*
*   @return {Array} List of changes
*   @param {String} buildDetails. Bamboo plan key name +  build number
*   @param {String} callback. Executed when the remote JSON has been parsed.
*/
Bamboo.prototype.getChangesFromBuild = function(buildDetails, callback) {
  var self = this,
    planUri = self.host + "/rest/api/latest/result/" + buildDetails + ".json?expand=changes";

  request({ uri: planUri }, function (error, response, body) {
    if (error || response.statusCode !== 200) {
      callback("Unreachable endpoint");
      return false;
    }

    var bodyJson = JSON.parse(response.body),
      changes = bodyJson.changes.change,
      buildReason = bodyJson.buildReason,
      changeNames = [];

    _.each(changes, function(change){
      changeNames.push(change.fullName);
      _.uniq(changeNames);
    });

    if (buildReason && buildReason.indexOf("Child of") != -1) {
      var dependentPlan = buildReason.substring(buildReason.indexOf(">") + 1).replace("","");

      // Search for JIRA issues coming from the dependent plan
      self.getChangesFromBuild(dependentPlan, function(result){
        _.each(result, function(item){
          changeNames.push(item);
        });
        callback(_.uniq(changeNames));
      });
    } else {
      callback(changeNames);
    }
  });
};

/*
* Returns the jira issues associated to a specific build. It also considers a dependent plan
*
*   @return {Array} List of JIRA tasks
*   @param {String} buildDetails. Bamboo plan key name +  build number
*   @param {String} callback. Executed when the remote JSON has been parsed.
*/
Bamboo.prototype.getJiraIssuesFromBuild = function(buildDetails, callback) {
  var self = this,
    planUri = self.host + "/rest/api/latest/result/" + buildDetails + ".json?expand=jiraIssues";

  request({ uri: planUri }, function (error, response, body) {
    if (error || response.statusCode !== 200) {
      callback("Unreachable endpoint");
      return false;
    }

    var bodyJson = JSON.parse(response.body),
      jiraIssues = bodyJson.jiraIssues.issue,
      buildReason = bodyJson.buildReason,
      jiraNumbers = [];

    _.each(jiraIssues, function(issue){
      jiraNumbers.push(issue.key);
      _.uniq(jiraNumbers);
    });

    if (buildReason.indexOf("Child of") != -1) {
      var dependentPlan = buildReason.substring(buildReason.indexOf(">") + 1).replace("","");

      // Search for JIRA issues coming from the dependent plan
      self.getJiraIssuesFromBuild(dependentPlan, function(result){
        _.each(result, function(item){
          jiraNumbers.push(item);
        });
        callback(_.uniq(jiraNumbers));
      });
    } else {
      callback(jiraNumbers);
    }
  });
};

/*
* Returns the content of an artifact associated to a build
*
*   @return {String} content of an articact
*   @param {String} buildDetails. Bamboo plan key name +  build number
*   @param {String} artifactName. Artifact name
*   @param {String} callback. Executed when the remote JSON has been parsed.
*/
Bamboo.prototype.getArtifactContent = function(buildDetails, artifactName, callback) {
  var self = this,
    artifactUri = self.host + "/browse/" + buildDetails + "/artifact/shared/" + artifactName + "/" + artifactName;

  request({ uri: artifactUri }, function (error, response, body) {
    if (error || response.statusCode !== 200) {
      callback("Unreachable endpoint");
      return false;
    }
    callback(body.toString("utf-8", 0));
    });
};

/*
* Returns the list of plans key names available
*
*   @return {Array} currentPlans - List of plans available (each plan has a 'key' and a 'name' value)
*   @return {String} params - Query string. E.g. "?start-index=25"
*   @param {String} callback. Executed when the remote JSON has been parsed.
*/
Bamboo.prototype.getAllPlans = function(params, callback, currentPlans) {
  var self = this,
    list = currentPlans || [],
    planUri = self.host + "/rest/api/latest/plan.json";

  planUri += (params) ? params : "";

  request({ uri: planUri }, function (error, response, body) {

    if (error || response.statusCode !== 200) {
      callback("Unreachable endpoint");
      return false;
    }

    var bodyJson = JSON.parse(response.body),
      plans = bodyJson.plans;

    if (plans.plan.length === 0) {
      callback("No plans available");
      return false;
    }

    _.each(plans.plan, function(plan){
      list.push({
        key: plan.key,
        name: plan.name
      });
    });

    // Loop through the next series of builds
    var newIndex = plans["max-result"] + plans["start-index"];

    if (newIndex < plans.size) {
      self.getAllPlans("?start-index=" + newIndex, function(result){
        callback(result);
      }, list);
    } else {
      callback(list);
    }
    });
};

function checkErrors(error, response) {
  if (error || response.statusCode !== 200) {
    return "Unreachable endpoint";
  }

  var body = JSON.parse(response.body),
    results = body.results;

  if (results.result.length === 0) {
    return "The plan doesn't contain any result";
  }
}

module.exports = Bamboo;
<commit_msg>comment added to buildStatus method<commit_after>var request = require('request'),
  _ = require('underscore');

/*
* Function defining a Bamboo instance
*
*   @param {String} hostname. E.g. "http://hostname.com:8085"
*/
function Bamboo(host) {
  this.host = host || "http://localhost:8085";
}

/*
* Returns the latest successful build number
*
*   @return {String} build number
*   @param {String} planKey. Bamboo plan key name
*   @param {String} params. Query string. E.g. "?start-index=25"
*   @param {String} callback. Executed when the remote JSON has been parsed.
*/
Bamboo.prototype.getLatestSuccessfulBuilNumber = function(planKey, params, callback) {
  var self = this,
    planUri = self.host + "/rest/api/latest/result/" + planKey + ".json";
  planUri += (params) ? params : "";

  request({ uri: planUri }, function (error, response, body) {

    var errors = checkErrors(error, response);
    if (errors) {
      callback(errors);
      return false;
    }

    var bodyJson = JSON.parse(response.body),
      results = bodyJson.results,
      result = results.result,
      build_no = "",
      isSearching = false;

    // Search for the latest 'Successful' build
    for (var i = 0, len = result.length; i < len; i ++){
      var resultEl = result[i];

      if (resultEl.state === "Successful") {
        build_no = resultEl.number;
        callback(build_no);
        return;
      }
    }

    // Loop through the next series of builds
    var newIndex = results["max-result"] + results["start-index"];
    if (newIndex < results.size) {
      isSearching = true;
      self.getLatestSuccessfulBuilNumber(planKey, "?start-index=" + newIndex, function(result){
        callback(result);
        return;
      });
    } else {
      isSearching = false;
    }

    if (!build_no && !isSearching) {
      callback("The plan doesn't contain any successful build");
    }
    });
};

/*
* Returns the latest build status
*
*   @return {String} build status
*   @return {String} build number
*   @param {String} planKey. Bamboo plan key name
*   @param {String} callback. Executed when the remote JSON has been parsed.
*/
Bamboo.prototype.getLatestBuildStatus = function(planKey, callback) {
  var self = this,
    planUri = self.host + "/rest/api/latest/result/" + planKey + ".json";

  request({ uri: planUri }, function (error, response, body) {
    var errors = checkErrors(error, response);

    if (errors) {
      callback(errors);
      return false;
    }

    var bodyJson = JSON.parse(response.body),
      results = bodyJson.results,
      last_result = results.result[0];

    callback(last_result.state, last_result.number);
  });
};

/*
* Returns the status of the build
*
*   @param {String} buildDetails. Bamboo plan key name + build number
*   @param {String} callback. Executed when the remote JSON has been parsed.
*/
Bamboo.prototype.getBuildStatus = function(buildDetails, callback) {
  var self = this,
    planUri = self.host + "/rest/api/latest/result/" + buildDetails + ".json";

  request({ uri: planUri }, function (error, response, body) {
    if (error || response.statusCode !== 200) {
      callback("Unreachable endpoint");
      return false;
    }

    var bodyJson = JSON.parse(response.body),
      result = bodyJson.lifeCycleState;

    callback(result);
  });
};

/*
* Returns the changes associated to a specific build. It also considers a dependent plan recursevely
*
*   @return {Array} List of changes
*   @param {String} buildDetails. Bamboo plan key name +  build number
*   @param {String} callback. Executed when the remote JSON has been parsed.
*/
Bamboo.prototype.getChangesFromBuild = function(buildDetails, callback) {
  var self = this,
    planUri = self.host + "/rest/api/latest/result/" + buildDetails + ".json?expand=changes";

  request({ uri: planUri }, function (error, response, body) {
    if (error || response.statusCode !== 200) {
      callback("Unreachable endpoint");
      return false;
    }

    var bodyJson = JSON.parse(response.body),
      changes = bodyJson.changes.change,
      buildReason = bodyJson.buildReason,
      changeNames = [];

    _.each(changes, function(change){
      changeNames.push(change.fullName);
      _.uniq(changeNames);
    });

    if (buildReason && buildReason.indexOf("Child of") != -1) {
      var dependentPlan = buildReason.substring(buildReason.indexOf(">") + 1).replace("","");

      // Search for JIRA issues coming from the dependent plan
      self.getChangesFromBuild(dependentPlan, function(result){
        _.each(result, function(item){
          changeNames.push(item);
        });
        callback(_.uniq(changeNames));
      });
    } else {
      callback(changeNames);
    }
  });
};

/*
* Returns the jira issues associated to a specific build. It also considers a dependent plan
*
*   @return {Array} List of JIRA tasks
*   @param {String} buildDetails. Bamboo plan key name +  build number
*   @param {String} callback. Executed when the remote JSON has been parsed.
*/
Bamboo.prototype.getJiraIssuesFromBuild = function(buildDetails, callback) {
  var self = this,
    planUri = self.host + "/rest/api/latest/result/" + buildDetails + ".json?expand=jiraIssues";

  request({ uri: planUri }, function (error, response, body) {
    if (error || response.statusCode !== 200) {
      callback("Unreachable endpoint");
      return false;
    }

    var bodyJson = JSON.parse(response.body),
      jiraIssues = bodyJson.jiraIssues.issue,
      buildReason = bodyJson.buildReason,
      jiraNumbers = [];

    _.each(jiraIssues, function(issue){
      jiraNumbers.push(issue.key);
      _.uniq(jiraNumbers);
    });

    if (buildReason.indexOf("Child of") != -1) {
      var dependentPlan = buildReason.substring(buildReason.indexOf(">") + 1).replace("","");

      // Search for JIRA issues coming from the dependent plan
      self.getJiraIssuesFromBuild(dependentPlan, function(result){
        _.each(result, function(item){
          jiraNumbers.push(item);
        });
        callback(_.uniq(jiraNumbers));
      });
    } else {
      callback(jiraNumbers);
    }
  });
};

/*
* Returns the content of an artifact associated to a build
*
*   @return {String} content of an articact
*   @param {String} buildDetails. Bamboo plan key name +  build number
*   @param {String} artifactName. Artifact name
*   @param {String} callback. Executed when the remote JSON has been parsed.
*/
Bamboo.prototype.getArtifactContent = function(buildDetails, artifactName, callback) {
  var self = this,
    artifactUri = self.host + "/browse/" + buildDetails + "/artifact/shared/" + artifactName + "/" + artifactName;

  request({ uri: artifactUri }, function (error, response, body) {
    if (error || response.statusCode !== 200) {
      callback("Unreachable endpoint");
      return false;
    }
    callback(body.toString("utf-8", 0));
    });
};

/*
* Returns the list of plans key names available
*
*   @return {Array} currentPlans - List of plans available (each plan has a 'key' and a 'name' value)
*   @return {String} params - Query string. E.g. "?start-index=25"
*   @param {String} callback. Executed when the remote JSON has been parsed.
*/
Bamboo.prototype.getAllPlans = function(params, callback, currentPlans) {
  var self = this,
    list = currentPlans || [],
    planUri = self.host + "/rest/api/latest/plan.json";

  planUri += (params) ? params : "";

  request({ uri: planUri }, function (error, response, body) {

    if (error || response.statusCode !== 200) {
      callback("Unreachable endpoint");
      return false;
    }

    var bodyJson = JSON.parse(response.body),
      plans = bodyJson.plans;

    if (plans.plan.length === 0) {
      callback("No plans available");
      return false;
    }

    _.each(plans.plan, function(plan){
      list.push({
        key: plan.key,
        name: plan.name
      });
    });

    // Loop through the next series of builds
    var newIndex = plans["max-result"] + plans["start-index"];

    if (newIndex < plans.size) {
      self.getAllPlans("?start-index=" + newIndex, function(result){
        callback(result);
      }, list);
    } else {
      callback(list);
    }
    });
};

function checkErrors(error, response) {
  if (error || response.statusCode !== 200) {
    return "Unreachable endpoint";
  }

  var body = JSON.parse(response.body),
    results = body.results;

  if (results.result.length === 0) {
    return "The plan doesn't contain any result";
  }
}

module.exports = Bamboo;
<|endoftext|>


<commit_before>/**
 * Requires
 *
 * @ignore
 */
var Config = require('../config'),
  FS = require('fs'),
  Path = require('path'),
  Fuzzy = require('fuzzysearch'),
  _ = require('lodash');

/**
 * Variables
 *
 * @ignore
 */
var cardCount = 0,
  cardPacks = {};

/**
 * Private
 *
 * @ignore
 */
function getPackCardFiles(dir) {
  var cards = [],
    files = FS.readdirSync(dir);

  for (var i = 0; i < files.length; i++) {
    var fileName = files[i];

    if (Path.extname(fileName) === '.js') {
      cards.push(Path.basename(fileName, Path.extname(fileName)));
    }
  }

  return cards;
}

module.exports = {
  init: function () {
    var cardsDir = Path.join(process.env.CARDS_DIRECTORY || (process.cwd() + '/cards')),
      packs = _.filter(FS.readdirSync(cardsDir), function (dir) { return _.startsWith(dir, 'hashdo-'); });

    console.log('PACKS: Cards will be loaded from %d packs found in %s.', packs.length, cardsDir);

    for (var i = 0; i < packs.length; i++) {
      var isPackage = false,
        packDir = Path.join(cardsDir, packs[i]);

      // Check if the directory has a package.json file, otherwise ignore it, it's not a pack.
      try {
        FS.statSync(Path.join(packDir, 'package.json'));
        isPackage = true;
      }
      catch (err) {}

      if (isPackage) {
        var packageJson = FS.readFileSync(Path.join(packDir, 'package.json')),
          packageInfo = JSON.parse(packageJson.toString()),
          packInfo = packageInfo.pack,
          packCardsDir = Path.join(cardsDir, packs[i], packInfo.cardsDir || ''),
          packCards = getPackCardFiles(packCardsDir),
          packName = packageInfo.name.replace('hashdo-', '');

        if (!packInfo.hidden) {
          cardPacks[packName] = {
            name: packInfo.friendlyName,
            cards: {}
          };

          for (var j = 0; j < packCards.length; j++) {
            var card = require(Path.join(packCardsDir, packCards[j])),
              cardName = packCards[j];

            cardPacks[packName].cards[cardName] = {
              pack: packName,
              card: cardName,
              name: card.name,
              description: card.description || '',
              icon: card.icon || Config.baseUrl + '/' + packName + '/' + cardName + '/icon.png',
              baseUrl: Config.baseUrl + '/' + packName + '/' + cardName,
              inputs: card.inputs
            };
          }
        }
      }
    }
  },

  count: function (filter) {
    if (cardCount > 0) {
      return cardCount;
    }
    else {
      cardCount = 0;

      if (filter) {
        filter = filter.toLowerCase();

        _.each(_.keys(cardPacks), function (packKey) {
          _.each(_.keys(cardPacks[packKey].cards), function (cardKey) {
            var card = cardPacks[packKey].cards[cardKey];

            filter = filter.toLowerCase();

            if (Fuzzy(filter, card.name.toLowerCase())) {
              cardCount = cardCount + 1;
            }
          });
        });
      }
      else {
        _.each(_.keys(cardPacks), function (packKey) {
          cardCount = cardCount + _.keys(cardPacks[packKey].cards).length;
        });
      }

      return cardCount;
    }
  },

  cards: function (filter) {
    var list = [];

    _.each(_.keys(cardPacks), function (packKey) {
      _.each(_.keys(cardPacks[packKey].cards), function (cardKey) {
        var card = cardPacks[packKey].cards[cardKey],
          item = {
            pack: card.pack,
            card: card.card,
            name: card.name,
            description: card.description,
            icon: card.icon
          };

        if (filter) {
          filter = filter.toLowerCase();

          if (Fuzzy(filter, card.name.toLowerCase())) {
            list.push(item);
          }
        }
        else {
          list.push(item);
        }
      });
    });

    // sort
    list = _.sortBy(list, 'pack card');

    return list;
  },

  card: function (pack, card) {
    if (cardPacks[pack] && cardPacks[pack].cards[card]) {
      return cardPacks[pack].cards[card];
    }
  }
};
<commit_msg>Updated packs to be consumed.<commit_after>/**
 * Requires
 *
 * @ignore
 */
var FS = require('fs'),
  Path = require('path'),
  Fuzzy = require('fuzzysearch'),
  _ = require('lodash');

/**
 * Variables
 *
 * @ignore
 */
var cardCount = 0,
  cardPacks = {};

/**
 * Private
 *
 * @ignore
 */
function getPackCardFiles(dir) {
  var cards = [],
    files = FS.readdirSync(dir);

  for (var i = 0; i < files.length; i++) {
    var fileName = files[i];

    if (Path.extname(fileName) === '.js') {
      cards.push(Path.basename(fileName, Path.extname(fileName)));
    }
  }

  return cards;
}

module.exports = {
  init: function (baseUrl, cardsDirectory) {
    var packs = _.filter(FS.readdirSync(cardsDirectory), function (dir) { return _.startsWith(dir, 'hashdo-'); });

    console.log('PACKS: Cards will be loaded from %d packs found in %s.', packs.length, cardsDirectory);

    for (var i = 0; i < packs.length; i++) {
      var isPackage = false,
        packDir = Path.join(cardsDirectory, packs[i]);

      // Check if the directory has a package.json file, otherwise ignore it, it's not a pack.
      try {
        FS.statSync(Path.join(packDir, 'package.json'));
        isPackage = true;
      }
      catch (err) {}

      if (isPackage) {
        var packageJson = FS.readFileSync(Path.join(packDir, 'package.json')),
          packageInfo = JSON.parse(packageJson.toString()),
          packInfo = packageInfo.pack,
          packCardsDir = Path.join(cardsDirectory, packs[i]),
          packCards = getPackCardFiles(packCardsDir),
          packName = packageInfo.name.replace('hashdo-', '');

        if (!packInfo.hidden) {
          cardPacks[packName] = {
            name: packInfo.friendlyName,
            cards: {}
          };

          for (var j = 0; j < packCards.length; j++) {
            var card = require(Path.join(packCardsDir, packCards[j])),
              cardName = packCards[j];

            cardPacks[packName].cards[cardName] = {
              pack: packName,
              card: cardName,
              name: card.name,
              description: card.description || '',
              icon: card.icon || _.trimRight(baseUrl, '/') + '/' + packName + '/' + cardName + '/icon.png',
              baseUrl: _.trimRight(baseUrl, '/') + '/' + packName + '/' + cardName,
              inputs: card.inputs
            };
          }
        }
      }
    }
  },

  count: function (filter) {
    if (cardCount > 0) {
      return cardCount;
    }
    else {
      cardCount = 0;

      if (filter) {
        filter = filter.toLowerCase();

        _.each(_.keys(cardPacks), function (packKey) {
          _.each(_.keys(cardPacks[packKey].cards), function (cardKey) {
            var card = cardPacks[packKey].cards[cardKey];

            filter = filter.toLowerCase();

            if (Fuzzy(filter, card.name.toLowerCase())) {
              cardCount = cardCount + 1;
            }
          });
        });
      }
      else {
        _.each(_.keys(cardPacks), function (packKey) {
          cardCount = cardCount + _.keys(cardPacks[packKey].cards).length;
        });
      }

      return cardCount;
    }
  },

  cards: function (filter) {
    var list = [];

    _.each(_.keys(cardPacks), function (packKey) {
      _.each(_.keys(cardPacks[packKey].cards), function (cardKey) {
        var card = cardPacks[packKey].cards[cardKey],
          item = {
            pack: card.pack,
            card: card.card,
            name: card.name,
            description: card.description,
            icon: card.icon
          };

        if (filter) {
          filter = filter.toLowerCase();

          if (Fuzzy(filter, card.name.toLowerCase())) {
            list.push(item);
          }
        }
        else {
          list.push(item);
        }
      });
    });

    // sort
    list = _.sortBy(list, 'pack card');

    return list;
  },

  card: function (pack, card) {
    if (cardPacks[pack] && cardPacks[pack].cards[card]) {
      return cardPacks[pack].cards[card];
    }
  }
};
<|endoftext|>


<commit_before>/*
 * raja instance
 * uri of the io namespace - not of a room
 * cb callback(err, socket) when io is connected
 */
module.exports = function(raja, uri, cb) {
	var server = raja.opts.server;
	if (server) {
		raja.server = new RajaServer(uri, server);
	}
	raja.client = new RajaClient(raja, require('socket.io-client').connect(uri));
	raja.client.init(cb);
};

function RajaClient(raja, socket) {
	this.raja = raja;
	this.socket = socket;
}
require('util').inherits(RajaClient, require('events').EventEmitter);

RajaClient.prototype.init = function(cb) {
	var socket = this.socket;
	var raja = this.raja;
	var self = this;
	socket.emit('join', {room: '*'});
	socket.on('message', function(msg) {
		raja.receive(msg);
		self.emit('message', msg);
	});
	socket.on('connect', function() {
		cb(null, self);
	});
	socket.on('connect_error', function(err) {
		cb(err);
	});
	socket.on('error', function(err) {
		raja.error(err);
	});
};

RajaClient.prototype.send = function(msg) {
	this.socket.emit('message', msg);
	this.emit('message', msg);
};

function RajaServer(uri, server) {
	if (!server.listen) server = require('url').parse(uri).port;
	var io = require('socket.io')(server);
	io.on('connection', function(socket) {
		socket.on('message', function(msg) {
			if (!msg.url) return;
			io.to('*').to(msg.url).emit('message', msg);
		});
		socket.on('join', function(msg) {
			socket.join(msg.room, function(err) {
				if (err) console.error(err)
			}); // msg.mtime
		});
	});
}

<commit_msg>When sending, do not emit locally<commit_after>/*
 * raja instance
 * uri of the io namespace - not of a room
 * cb callback(err, socket) when io is connected
 */
module.exports = function(raja, uri, cb) {
	var server = raja.opts.server;
	if (server) {
		raja.server = new RajaServer(uri, server);
	}
	raja.client = new RajaClient(raja, require('socket.io-client').connect(uri));
	raja.client.init(cb);
};

function RajaClient(raja, socket) {
	this.raja = raja;
	this.socket = socket;
}
require('util').inherits(RajaClient, require('events').EventEmitter);

RajaClient.prototype.init = function(cb) {
	var socket = this.socket;
	var raja = this.raja;
	var self = this;
	socket.emit('join', {room: '*'});
	socket.on('message', function(msg) {
		raja.receive(msg);
		self.emit('message', msg);
	});
	socket.on('connect', function() {
		cb(null, self);
	});
	socket.on('connect_error', function(err) {
		cb(err);
	});
	socket.on('error', function(err) {
		raja.error(err);
	});
};

RajaClient.prototype.send = function(msg) {
	this.socket.emit('message', msg);
};

function RajaServer(uri, server) {
	if (!server.listen) server = require('url').parse(uri).port;
	var io = require('socket.io')(server);
	io.on('connection', function(socket) {
		socket.on('message', function(msg) {
			if (!msg.url) return;
			io.to('*').to(msg.url).emit('message', msg);
		});
		socket.on('join', function(msg) {
			socket.join(msg.room, function(err) {
				if (err) console.error(err)
			}); // msg.mtime
		});
	});
}

<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */
var EventEmitter = require('events').EventEmitter;
var _ = require('lodash');
var util = require('util');
var Connection = require('./enum/connection');
var Module = require('./enum/module');

/**
 * Create a new socket of the given `type`.
 *
 * @constructor
 * @param {String|Number} type
 * @api public
 */
var BaseMQ = module.exports = function BaseMQ() {
  EventEmitter.call(this);

  this._connections = [];
  this._sockets = [];
};

/**
 * Inherit from `EventEmitter.prototype`.
 */
util.inherits(BaseMQ, EventEmitter);

/**
 * Module declaration.
 *
 * @param name Module name
 * @param opts... Module params
 */
BaseMQ.prototype.use = function(name) {
  var _this = this;
  var args = Array.apply(null, arguments).slice(1);

  _.forEach(args, function(opt, i) {
    switch (name) {
      case Module.CONNECTION:
        _this._connections[i] = _.defaults({}, _this._connections[i], opt);
        break;
    }
  });
};

/**
 * Initialize.
 */
BaseMQ.prototype.init = function() {
  var _this = this;

  _.forEach(_this._connections, function(connection, i) {
    _this._sockets[i] = require('./module/connection')(_this.constructor.name, connection);
    _this._sockets[i].on('message', function() {
      var args = Array.apply(null, arguments);
      var identity;

      if ([Connection.REP, Connection.REP_SYNC].indexOf(connection.approach) > -1) {
        identity = args.shift();
      }

      if (args[1].toString() === '^') {
        switch (+args[2].toString()) {
          case Connection.STATUS_READY:
            // @todo save client/worker identity
            _this._sockets[i].send([identity, identity, args[1], Connection.STATUS_READY_CONFIRM]);
            break;
          case Connection.STATUS_READY_CONFIRM:
            _this.emit('connect', args[0].toString('utf8'));
            break;
        }
      }
    });
  });
};

<commit_msg>feat(src): Allowed only single connection instance.<commit_after>'use strict';

/**
 * Module dependencies.
 */
var EventEmitter = require('events').EventEmitter;
var _ = require('lodash');
var util = require('util');
var Connection = require('./enum/connection');
var Module = require('./enum/module');

/**
 * Create a new socket of the given `type`.
 *
 * @constructor
 * @param {String|Number} type
 * @api public
 */
var BaseMQ = module.exports = function BaseMQ() {
  EventEmitter.call(this);
};

/**
 * Inherit from `EventEmitter.prototype`.
 */
util.inherits(BaseMQ, EventEmitter);

/**
 * Module declaration.
 *
 * @param name Module name
 * @param opts Module options
 */
BaseMQ.prototype.use = function(name, opts) {
  var _this = this;

  switch (name) {
    case Module.CONNECTION:
      _this._connection = _.defaults({}, _this._connection, opts);
      break;
  }

  return _this;
};

/**
 * Initialize.
 */
BaseMQ.prototype.init = function() {
  var _this = this;

  _this._socket = require('./module/connection')(_this.constructor.name, _this._connection);
  _this._socket.on('message', function() {
    var args = Array.apply(null, arguments);
    var identity;

    if ([Connection.REP, Connection.REP_SYNC].indexOf(_this._connection.approach) > -1) {
      identity = args.shift();
    }

    if (args[1].toString() === '^') {
      switch (+args[2].toString()) {
        case Connection.STATUS_READY:
          // @todo save client/worker identity
          _this._socket.send([identity, identity, args[1], Connection.STATUS_READY_CONFIRM]);
          break;
        case Connection.STATUS_READY_CONFIRM:
          _this.emit('connect', args[0].toString('utf8'));
          break;
      }
    }
  });
};

<|endoftext|>


<commit_before>/* global require, Buffer, Promise, module, console, process, setTimeout */
/* jshint -W097 */
/* jshint esnext: true */
'use strict';
const os = require('os');
const net = require('net');
const util = require('util');
const Writable = require('stream').Writable;
const Readable = require('stream').Readable;
const Msg = require('./messages');
const Conveyor = require('./conveyor');
const PORTS = {
  'iidk': 21030,
  'slave': 21111,
  'video': 20900,
  'map': 21051,
  'pos': 21012,
  'web': 21034
};
const RETRY_TIME = 3000;
const DISCONNECT = {type: 'IQ', action: 'DISCONNECT'};
/**** API ****/
function factorySendReact(output) {
  return (msg) => {
    msg.msg = 'React';
    output.push(msg);
  };
}
function factorySendEvent(output) {
  return (msg) => {
    msg.msg = 'Event';
    output.push(msg);
  };
}
function factorySendCoreReact(output) {
  return (msg) => output.push(toCoreReact(msg));
}
/**** Internal *****/
function toCoreReact(msg) {
  let event = {
    msg: 'Event',
    type: 'CORE',
    action: 'DO_REACT',
    params: {
      source_type: msg.type,
      source_id: msg.id,
      action: msg.action
    }
  };
  let keys = {};
  let key = '';
  let i = 0;
  if (msg.params) {
    keys = Object.keys(msg.params);
    i = keys.length;
    event.params.params = i;
    for (;i--;) {
      key = keys[i];
      event.params['param' + i + '_name'] = key;
      event.params['param' + i + '_val'] = msg.params[key];
    }
  }
  return event;
}
function bind(pipeline, socket) {
  socket.pipe(pipeline.decomposer, {end: false});
  pipeline.composer.pipe(socket, {end: false});
}
function unbind(pipeline, socket) {
  socket.unpipe(pipeline.decomposer);
  pipeline.composer.unpipe(socket);
}
/*
   function catch(msg) {
// BEGIN_STATE, OBJECT_STATE, END_STATE, OBJECT_CONFIG, END_CONFIG
var parts = msg.action.slice(0, msg.action.indexOf('_'));
if (queue.length === 0) {
return;
}
if (parts === 'OBJECT') {
queue[0].append(convert(msg));
}
if (parts === 'END') {
queue[0].finish(msg);
}
}
function _getAccumulator(resolve) {
let list = [];
return {
append: function (msg) {
list.push(msg);
},
finish: (function (msg) {
resolve(list);
conveyor.unqueue();
//console.log('[accumulator] got list of', list.length);
}).bind(this)
};
}

*/
/*
   function get(options) {
   return new Promise(function (resolve, reject) {
   let accumulator = _getAccumulator(resolve);
   if (options.type === undefined) {
   return new Error("[get] Object type is not defined");
   }
   if (options.prop === undefined) {
   return new Error("[get] Property type is not defined");
   }
   console.log(output);
   conveyor.queue(accumulator);
   output.push({
   type: 'CORE',
   action: 'GET_' + options.prop.toUpperCase(),
   params: {
   objtype: options.type,
   objid: options.id || ''
   }
   });
   })
   }
   */
/**** Server ****/
function Server () {
  const pipeline = new Pipeline();
  const conveyor = pipeline.conveyor;

  this.listen = function listen(port) {
    return new Promise((resolve, reject) => {
      const server = net.createServer();

      server.listen(PORTS[port]);
      server.on('listening', () => resolve(server));
      server.on('connection', (socket) => {
        bind(pipeline, socket);
        socket.on('error', (err) => {
          reject(err);
        });
        socket.on('close', () => {
          unbind(pipeline, socket);
        });
      });
    });
  };
  this.on = conveyor.subscribe.bind(conveyor);
  this.off = conveyor.unsubscribe.bind(conveyor);
  this.sendReact = factorySendReact(pipeline.output);
  this.sendCoreReact = factorySendCoreReact(pipeline.output);
  this.sendEvent = factorySendEvent(pipeline.output);
}
/**** Client ****/
// TODO: keep connected IIDK id and append it as slave_id<> parameter
function Client () {
  const pipeline = new Pipeline();
  const conveyor = pipeline.conveyor;

  this.connect = function connect(options) {
    return new Promise((resolve, reject) => {
      const socket = net.Socket();
      const ip = options.ip || '127.0.0.1';
      const port_name = options.port || 'iidk';
      const port = PORTS[port_name];
      const host_id = options.host || os.hostname().toUpperCase();
      const iidk_id = options.hasOwnProperty('iidk') ? '.' + options.iidk : '';
      const iqConnected = {
        type: 'IQ',
        action: 'CONNECTED',
      };
      const iqDisconnected = {
        type: 'IQ',
        action: 'DISCONNECTED',
      };
      const connectSocket = () => socket.connect({host: ip, port: port});

      socket.on('connect', () => {
        let connected = {
          type: 'SLAVE',
          id: host_id + iidk_id,
          action: 'CONNECTED',
          params: {
            'SOCKET': socket.localAddress,
            'TRANSPORT_TYPE': 'SOCKET',
            'module': 'node',
            'TRANSPORT_ID': socket.remotePort.toString().slice(1)
          }
        };
        bind(pipeline, socket);
        this.sendEvent(connected);
        resolve(socket, 'connected');
        conveyor.handle(iqConnected);
      });
      socket.on('end', () => reject('terminated'));
      socket.on('close', (hasError) => {
        if (hasError) {
          setTimeout(connectSocket, RETRY_TIME);
        }
        unbind(pipeline, socket);
        conveyor.handle(iqDisconnected);
      });
      socket.on('error', (err) => reject(err));
      socket.on('timeout', () => reject('timeout'));
      conveyor.subscribe(DISCONNECT, () => socket.end());
      connectSocket();
    });
  };
  this.disconnect = function disconnect() {
    conveyor.handle(DISCONNECT);
  };
  this.on = conveyor.subscribe.bind(conveyor);
  this.off = conveyor.unsubscribe.bind(conveyor);
  this.sendReact = factorySendReact(pipeline.output);
  this.sendCoreReact = factorySendCoreReact(pipeline.output);
  this.sendEvent = factorySendEvent(pipeline.output);
}

util.inherits(Input, Writable);
function Input(options) {
  if (!(this instanceof Input)) {
    return new Input(options);
  }
  Writable.call(this, options);
  this._writableState.objectMode = true;
  this.conveyor = new Conveyor();
  this._write = (msg, encoding, next) => {
    process.nextTick(() => this.conveyor.handle(preprocess(msg)));
    next();
  };
}
function convert(msg) {
  msg.type = msg.params.objtype || '';
  msg.action = msg.params.objaction || '';
  msg.id = msg.params.objid || '';
  delete msg.params.objtype;
  delete msg.params.objaction;
  delete msg.params.objid;
  return msg;
}
function preprocess(message) {
  if (message.type === 'ACTIVEX' && message.action === 'EVENT') {
    message.msg = 'Event';
    return convert(message);
    //    } else {
    //      catch(message);
  } else {
    return message;
  }
}

/* Construct pipeline */
function Pipeline() {
  const input = new Input();
  const output = new Readable({objectMode: true});
  const decomposer = new Msg.decomposer();
  const composer = new Msg.composer();

  output._read = () => {};
  output.pipe(composer, {end: false});
  decomposer.pipe(input, {end: false});

  this.output = output;
  this.conveyor = input.conveyor;
  this.decomposer = decomposer;
  this.composer = composer;
}

module.exports.Client = Client;
module.exports.Server = Server;
<commit_msg>Add  client option<commit_after>/* global require, Buffer, Promise, module, console, process, setTimeout */
/* jshint -W097 */
/* jshint esnext: true */
'use strict';
const os = require('os');
const net = require('net');
const util = require('util');
const Writable = require('stream').Writable;
const Readable = require('stream').Readable;
const Msg = require('./messages');
const Conveyor = require('./conveyor');
const PORTS = {
  'iidk': 21030,
  'slave': 21111,
  'video': 20900,
  'map': 21051,
  'pos': 21012,
  'web': 21034
};
const RETRY_TIME = 3000;
const DISCONNECT = {type: 'IQ', action: 'DISCONNECT'};
/**** API ****/
function factorySendReact(output) {
  return (msg) => {
    msg.msg = 'React';
    output.push(msg);
  };
}
function factorySendEvent(output) {
  return (msg) => {
    msg.msg = 'Event';
    output.push(msg);
  };
}
function factorySendCoreReact(output) {
  return (msg) => output.push(toCoreReact(msg));
}
/**** Internal *****/
function toCoreReact(msg) {
  let event = {
    msg: 'Event',
    type: 'CORE',
    action: 'DO_REACT',
    params: {
      source_type: msg.type,
      source_id: msg.id,
      action: msg.action
    }
  };
  let keys = {};
  let key = '';
  let i = 0;
  if (msg.params) {
    keys = Object.keys(msg.params);
    i = keys.length;
    event.params.params = i;
    for (;i--;) {
      key = keys[i];
      event.params['param' + i + '_name'] = key;
      event.params['param' + i + '_val'] = msg.params[key];
    }
  }
  return event;
}
function bind(pipeline, socket) {
  socket.pipe(pipeline.decomposer, {end: false});
  pipeline.composer.pipe(socket, {end: false});
}
function unbind(pipeline, socket) {
  socket.unpipe(pipeline.decomposer);
  pipeline.composer.unpipe(socket);
}
/*
   function catch(msg) {
// BEGIN_STATE, OBJECT_STATE, END_STATE, OBJECT_CONFIG, END_CONFIG
var parts = msg.action.slice(0, msg.action.indexOf('_'));
if (queue.length === 0) {
return;
}
if (parts === 'OBJECT') {
queue[0].append(convert(msg));
}
if (parts === 'END') {
queue[0].finish(msg);
}
}
function _getAccumulator(resolve) {
let list = [];
return {
append: function (msg) {
list.push(msg);
},
finish: (function (msg) {
resolve(list);
conveyor.unqueue();
//console.log('[accumulator] got list of', list.length);
}).bind(this)
};
}

*/
/*
   function get(options) {
   return new Promise(function (resolve, reject) {
   let accumulator = _getAccumulator(resolve);
   if (options.type === undefined) {
   return new Error("[get] Object type is not defined");
   }
   if (options.prop === undefined) {
   return new Error("[get] Property type is not defined");
   }
   console.log(output);
   conveyor.queue(accumulator);
   output.push({
   type: 'CORE',
   action: 'GET_' + options.prop.toUpperCase(),
   params: {
   objtype: options.type,
   objid: options.id || ''
   }
   });
   })
   }
   */
/**** Server ****/
function Server () {
  const pipeline = new Pipeline();
  const conveyor = pipeline.conveyor;

  this.listen = function listen(port) {
    return new Promise((resolve, reject) => {
      const server = net.createServer();

      server.listen(PORTS[port]);
      server.on('listening', () => resolve(server));
      server.on('connection', (socket) => {
        bind(pipeline, socket);
        socket.on('error', (err) => {
          reject(err);
        });
        socket.on('close', () => {
          unbind(pipeline, socket);
        });
      });
    });
  };
  this.on = conveyor.subscribe.bind(conveyor);
  this.off = conveyor.unsubscribe.bind(conveyor);
  this.sendReact = factorySendReact(pipeline.output);
  this.sendCoreReact = factorySendCoreReact(pipeline.output);
  this.sendEvent = factorySendEvent(pipeline.output);
}
/**** Client ****/
// TODO: keep connected IIDK id and append it as slave_id<> parameter
function Client () {
  const pipeline = new Pipeline();
  const conveyor = pipeline.conveyor;

  this.connect = function connect(options) {
    return new Promise((resolve, reject) => {
      const socket = net.Socket();
      const ip = options.ip || '127.0.0.1';
      const port_name = options.port || 'iidk';
      const port = PORTS[port_name];
      const host_id = options.host || os.hostname().toUpperCase();
      const reconnect = options.reconnect || false;
      const iidk_id = options.hasOwnProperty('iidk') ? '.' + options.iidk : '';
      const iqConnected = {
        type: 'IQ',
        action: 'CONNECTED',
      };
      const iqDisconnected = {
        type: 'IQ',
        action: 'DISCONNECTED',
      };
      const connectSocket = () => socket.connect({host: ip, port: port});

      socket.on('connect', () => {
        let connected = {
          type: 'SLAVE',
          id: host_id + iidk_id,
          action: 'CONNECTED',
          params: {
            'SOCKET': socket.localAddress,
            'TRANSPORT_TYPE': 'SOCKET',
            'module': 'node',
            'TRANSPORT_ID': socket.remotePort.toString().slice(1)
          }
        };
        bind(pipeline, socket);
        this.sendEvent(connected);
        resolve(socket, 'connected');
        conveyor.handle(iqConnected);
      });
      socket.on('end', () => reject('terminated'));
      socket.on('close', (hasError) => {
        if (hasError || reconnect) {
          setTimeout(connectSocket, RETRY_TIME);
        }
        unbind(pipeline, socket);
        conveyor.handle(iqDisconnected);
      });
      socket.on('error', (err) => reject(err));
      socket.on('timeout', () => reject('timeout'));
      conveyor.subscribe(DISCONNECT, () => socket.end());
      connectSocket();
    });
  };
  this.disconnect = function disconnect() {
    conveyor.handle(DISCONNECT);
  };
  this.on = conveyor.subscribe.bind(conveyor);
  this.off = conveyor.unsubscribe.bind(conveyor);
  this.sendReact = factorySendReact(pipeline.output);
  this.sendCoreReact = factorySendCoreReact(pipeline.output);
  this.sendEvent = factorySendEvent(pipeline.output);
}

util.inherits(Input, Writable);
function Input(options) {
  if (!(this instanceof Input)) {
    return new Input(options);
  }
  Writable.call(this, options);
  this._writableState.objectMode = true;
  this.conveyor = new Conveyor();
  this._write = (msg, encoding, next) => {
    process.nextTick(() => this.conveyor.handle(preprocess(msg)));
    next();
  };
}
function convert(msg) {
  msg.type = msg.params.objtype || '';
  msg.action = msg.params.objaction || '';
  msg.id = msg.params.objid || '';
  delete msg.params.objtype;
  delete msg.params.objaction;
  delete msg.params.objid;
  return msg;
}
function preprocess(message) {
  if (message.type === 'ACTIVEX' && message.action === 'EVENT') {
    message.msg = 'Event';
    return convert(message);
    //    } else {
    //      catch(message);
  } else {
    return message;
  }
}

/* Construct pipeline */
function Pipeline() {
  const input = new Input();
  const output = new Readable({objectMode: true});
  const decomposer = new Msg.decomposer();
  const composer = new Msg.composer();

  output._read = () => {};
  output.pipe(composer, {end: false});
  decomposer.pipe(input, {end: false});

  this.output = output;
  this.conveyor = input.conveyor;
  this.decomposer = decomposer;
  this.composer = composer;
}

module.exports.Client = Client;
module.exports.Server = Server;
<|endoftext|>


<commit_before>var falafel = require('falafel');
var fs = require('fs');
var path = require('path');

var base = require('./base');
var re = require('./re');

var Formatter = require('./formatter_base');

var A = base.A;

var iterateLines = base.iterateLines;
var sub = base.sub;

/* istanbul ignore next */
var jsonf = A.rbind(
	'stringify',
	JSON,
	function(key, value) {
		if (key === 'start' || key === 'end') {
			return value.line;
		}
		if (['parent', 'range'].indexOf(key) === -1) {
			return value;
		}
	},
	4
);

Formatter.JS = Formatter.create(
	{
		extensions: '*.js',
		id: 'js',
		prototype: {
			init: function() {
				this.processor = {};
			},

			format: function(contents, lint) {
				var hasSheBang = this._hasSheBang(contents);

				if (hasSheBang) {
					contents = '//' + contents;
				}

				this._lint(contents, this.flags.lint !== false && lint);

				this._processSyntax(contents);

				if (hasSheBang) {
					contents = contents.substr(2, contents.length);
				}

				var filePath = this.file;

				var logger = this.log.bind(this);

				return iterateLines(
					contents,
					function(item, index, collection) {
						var fullItem = item;

						item = item.trim();

						re.hasExtraNewLines(item, index, collection, logger);

						var lineNum = index + 1;

						var context = {
							customIgnore: re.js.IGNORE,
							file: filePath,
							hasSheBang: hasSheBang,
							item: item,
							lineNum: lineNum,
							logger: logger,
							nextItem: collection[lineNum] && collection[lineNum].trim()
						};

						fullItem = re.iterateRules('common', fullItem, context);

						item = context.item = fullItem.trim();

						fullItem = re.iterateRules('js', fullItem, context);

						item = context.item = fullItem.trim();

						return fullItem;
					}
				);
			},

			_hasSheBang: function(contents) {
				return contents && contents[0] === '#' && contents[1] === '!';
			},

			_logLintResults: function(results) {
				var instance = this;

				results.forEach(
					function(item, index) {
						instance.log(
							item.line || 0,
							item.message,
							(item.ruleId || item.message),
							{
								ruleId: item.ruleId || 'n/a'
							}
						);
					}
				);
			},

			_lint: function(contents, lint) {
				if (lint !== false) {
					var linter = require('./lint');

					var results = linter(contents, this.file, lint);

					if (results.length) {
						this._logLintResults(results);
					}
				}
			},

			_printAsSource: function(contents) {
				return contents.split('\n').map(
					function(item, index) {
						return (index + 1) + ' ' + item;
					}
				).join('\n');
			},

			_processSyntax: function(contents) {
				var instance = this;

				try {
					contents = falafel(
						contents,
						{
							loc: true,
							tolerant: true
						},
						function(node) {
							var parent = node.parent;
							var type = node.type;

							var processor = instance.processor;

							var processorFn = processor[type];

							if (A.Lang.isFunction(processorFn)) {
								processorFn.call(instance, node, parent);
							}
						}
					).toString();
				}
				catch (e) {
					this.log(e.lineNumber || 'n/a', sub('Could not parse JavaScript: {0}', e.description || e.message));

					if (this.flags.verbose) {
						this.logger.verboseDetails = this._printAsSource(contents);
					}
				}
			}
		}
	}
);

module.exports = Formatter.JS;<commit_msg>Removing unneeded conditionals<commit_after>var falafel = require('falafel');
var fs = require('fs');
var path = require('path');

var base = require('./base');
var re = require('./re');

var Formatter = require('./formatter_base');

var A = base.A;

var iterateLines = base.iterateLines;
var sub = base.sub;

/* istanbul ignore next */
var jsonf = A.rbind(
	'stringify',
	JSON,
	function(key, value) {
		if (key === 'start' || key === 'end') {
			return value.line;
		}
		if (['parent', 'range'].indexOf(key) === -1) {
			return value;
		}
	},
	4
);

Formatter.JS = Formatter.create(
	{
		extensions: '*.js',
		id: 'js',
		prototype: {
			init: function() {
				this.processor = {};
			},

			format: function(contents, lint) {
				var hasSheBang = this._hasSheBang(contents);

				if (hasSheBang) {
					contents = '//' + contents;
				}

				this._lint(contents, this.flags.lint !== false && lint);

				this._processSyntax(contents);

				if (hasSheBang) {
					contents = contents.substr(2, contents.length);
				}

				var filePath = this.file;

				var logger = this.log.bind(this);

				return iterateLines(
					contents,
					function(item, index, collection) {
						var fullItem = item;

						item = item.trim();

						re.hasExtraNewLines(item, index, collection, logger);

						var lineNum = index + 1;

						var context = {
							customIgnore: re.js.IGNORE,
							file: filePath,
							hasSheBang: hasSheBang,
							item: item,
							lineNum: lineNum,
							logger: logger,
							nextItem: collection[lineNum] && collection[lineNum].trim()
						};

						fullItem = re.iterateRules('common', fullItem, context);

						item = context.item = fullItem.trim();

						fullItem = re.iterateRules('js', fullItem, context);

						item = context.item = fullItem.trim();

						return fullItem;
					}
				);
			},

			_hasSheBang: function(contents) {
				return contents && contents[0] === '#' && contents[1] === '!';
			},

			_logLintResults: function(results) {
				var instance = this;

				results.forEach(
					function(item, index) {
						instance.log(
							item.line,
							item.message,
							item.ruleId,
							{
								ruleId: item.ruleId
							}
						);
					}
				);
			},

			_lint: function(contents, lint) {
				if (lint !== false) {
					var linter = require('./lint');

					var results = linter(contents, this.file, lint);

					if (results.length) {
						this._logLintResults(results);
					}
				}
			},

			_printAsSource: function(contents) {
				return contents.split('\n').map(
					function(item, index) {
						return (index + 1) + ' ' + item;
					}
				).join('\n');
			},

			_processSyntax: function(contents) {
				var instance = this;

				try {
					contents = falafel(
						contents,
						{
							loc: true,
							tolerant: true
						},
						function(node) {
							var parent = node.parent;
							var type = node.type;

							var processor = instance.processor;

							var processorFn = processor[type];

							if (A.Lang.isFunction(processorFn)) {
								processorFn.call(instance, node, parent);
							}
						}
					).toString();
				}
				catch (e) {
					this.log(e.lineNumber || 'n/a', sub('Could not parse JavaScript: {0}', e.description || e.message));

					if (this.flags.verbose) {
						this.logger.verboseDetails = this._printAsSource(contents);
					}
				}
			}
		}
	}
);

module.exports = Formatter.JS;<|endoftext|>


<commit_before>'use strict';

var split   = require('split'),
    through = require('through'),
    combine = require('stream-combiner'),
    Promise = require('bluebird');

var START_GROUP  = 'START_GROUP',
    GROUP_MEMBER = 'GROUP_MEMBER',
    NON_GROUP    = 'NON_GROUP';

function parseLine(line) {
  var commentFree = line.replace(/#.*$/, ''),
      index       = commentFree.indexOf(':');

  if(index === -1) return null;

  var field = commentFree.substr(0,index).trim().toLowerCase(),
      value = commentFree.substr(index+1).trim();

  switch (field) {
    case 'user-agent':
      return {
        type : START_GROUP,
        agent: value
      };
    case 'allow':
    case 'disallow':
      return {
        type: GROUP_MEMBER,
        rule: field,
        path: value
      };
    default:
      return {
        type : NON_GROUP,
        field: field,
        value: value
      };
  }
}

function tokenize() {
  return through(function (line) {
    var token = parseLine(line);
    if (token) {
      this.queue(token);
    }
  });
}

module.exports = function parse(content) {
  var result = {
    groups: [],
    extensions: []
  };

  var prevToken    = null,
      currentGroup = null;

  var build = through(function (token) {
    switch (token.type) {
      case START_GROUP:
        if (prevToken !== START_GROUP) {
          currentGroup = {
            agents  : [],
            rules   : []
          };
          result.groups.push(currentGroup);
        }
        currentGroup.agents.push(token.agent);
        break;
      case GROUP_MEMBER:
        if (currentGroup) {
          currentGroup.rules.push({
            rule: token.rule,
            path: token.path
          });
        }
        break;
      case NON_GROUP:
        result.extensions.push({
          extension: token.field,
          value: token.value
        });
        break;
    }

    prevToken = token.type;
  });

  return new Promise(function (resolve, reject) {
    combine(
      content,
      split(),
      tokenize(),
      build
    )
      .on('error', reject)
      .on('end', function () {
        resolve(result);
      });
  });
};

<commit_msg>Add support for noindex<commit_after>'use strict';

var split   = require('split'),
    through = require('through'),
    combine = require('stream-combiner'),
    Promise = require('bluebird');

var START_GROUP  = 'START_GROUP',
    GROUP_MEMBER = 'GROUP_MEMBER',
    NON_GROUP    = 'NON_GROUP';

function parseLine(line) {
  var commentFree = line.replace(/#.*$/, ''),
      index       = commentFree.indexOf(':');

  if(index === -1) return null;

  var field = commentFree.substr(0,index).trim().toLowerCase(),
      value = commentFree.substr(index+1).trim();

  switch (field) {
    case 'user-agent':
      return {
        type : START_GROUP,
        agent: value
      };
    case 'allow':
    case 'disallow':
    case 'noindex':
      return {
        type: GROUP_MEMBER,
        rule: field,
        path: value
      };
    default:
      return {
        type : NON_GROUP,
        field: field,
        value: value
      };
  }
}

function tokenize() {
  return through(function (line) {
    var token = parseLine(line);
    if (token) {
      this.queue(token);
    }
  });
}

module.exports = function parse(content) {
  var result = {
    groups: [],
    extensions: []
  };

  var prevToken    = null,
      currentGroup = null;

  var build = through(function (token) {
    switch (token.type) {
      case START_GROUP:
        if (prevToken !== START_GROUP) {
          currentGroup = {
            agents  : [],
            rules   : []
          };
          result.groups.push(currentGroup);
        }
        currentGroup.agents.push(token.agent);
        break;
      case GROUP_MEMBER:
        if (currentGroup) {
          currentGroup.rules.push({
            rule: token.rule,
            path: token.path
          });
        }
        break;
      case NON_GROUP:
        result.extensions.push({
          extension: token.field,
          value: token.value
        });
        break;
    }

    prevToken = token.type;
  });

  return new Promise(function (resolve, reject) {
    combine(
      content,
      split(),
      tokenize(),
      build
    )
      .on('error', reject)
      .on('end', function () {
        resolve(result);
      });
  });
};

<|endoftext|>


<commit_before>var _ = require('lodash');

var kramed = require('kramed');
var renderer = require('kramed-markdown-renderer');

var sections = require('./sections');
var isExercise = require('./is_exercise');
var section2obj = require('./section2obj');

// Get nodes
function lex(content) {
    return kramed.lexer(content);
}

// Render lexed nodes back to markdown
function render(lexed) {
    // Options to parser
    var options = Object.create(kramed.defaults);
    options.renderer = renderer();

    return kramed.parser(lexed, options);
}

function exerciseBlock(exercise) {
    return [
    '{% exercise %}',
    render(exercise.content),
    '{% initial %}',
    exercise.initial,
    '{% solution %}',
    exercise.solution,
    '{% validation %}',
    exercise.validation,
    '{% context %}',
    exerciseObj.context,
    '{% endexercise %}',
    ].join('\n');
}

function retroSection(section) {
    // Extract exercise data
    var exercise = section2obj(section);

    // Convert to new format
    var blockCode = newNode(exercise);

    return [
        // Use a html node so it's
        // Rawly injected during rendering
        {
            type: 'html',
            text: blockCode,
        }
    ];
}

// retro takes an input markdown file
// and outputs a new markdown file
// converting in the process old exercises to new ones
function retro(content) {
    // Lex incoming markdown file
    var lexed = lex(content);

    // Break it into sections
    var newSections = sections.split(lexed)
    .map(function(section) {
        // Leave non exercise sections untouched
        if(!isExercise) {
            return section;
        }
        // Convert old section to new format
        return retroSection(section);
    });

    // Bring sections back together into a list of lexed nodes
    var newLexed = sections.join(newSections)

    // Render back to markdown
    return render(newLexed);
}

module.exports = retro;
<commit_msg>Fix filter of exercises sections<commit_after>var _ = require('lodash');

var kramed = require('kramed');
var renderer = require('kramed-markdown-renderer');

var sections = require('./sections');
var isExercise = require('./is_exercise');
var section2obj = require('./section2obj');

// Get nodes
function lex(content) {
    return kramed.lexer(content);
}

// Render lexed nodes back to markdown
function render(lexed) {
    // Options to parser
    var options = Object.create(kramed.defaults);
    options.renderer = renderer();

    return kramed.parser(lexed, options);
}

function exerciseBlock(exercise) {
    return [
    '{% exercise %}',
    render(exercise.content),
    '{% initial %}',
    exercise.initial,
    '{% solution %}',
    exercise.solution,
    '{% validation %}',
    exercise.validation,
    '{% context %}',
    exerciseObj.context,
    '{% endexercise %}',
    ].join('\n');
}

function retroSection(section) {
    // Extract exercise data
    var exercise = section2obj(section);

    // Convert to new format
    var blockCode = newNode(exercise);

    return [
        // Use a html node so it's
        // Rawly injected during rendering
        {
            type: 'html',
            text: blockCode,
        }
    ];
}

// retro takes an input markdown file
// and outputs a new markdown file
// converting in the process old exercises to new ones
function retro(content) {
    // Lex incoming markdown file
    var lexed = lex(content);

    // Break it into sections
    var newSections = sections.split(lexed)
    .map(function(section) {
        // Leave non exercise sections untouched
        if(!isExercise(section)) {
            return section;
        }
        // Convert old section to new format
        return retroSection(section);
    });

    // Bring sections back together into a list of lexed nodes
    var newLexed = sections.join(newSections)

    // Render back to markdown
    return render(newLexed);
}

module.exports = retro;
<|endoftext|>


<commit_before>var exec = require('child_process').exec;
var path = require('path');
var _ = require('underscore');
var async = require('async');

var supportedBrowsers = exports.supported = [
	{
		name : 'chrome',
		pathQuery : 'which google-chrome',
		process : 'chrome'
	},
	{
		name : 'firefox',
		pathQuery : 'which firefox',
		process : 'firefox'
	},
	{
		name : 'opera',
		pathQuery : 'which opera',
		process : 'opera'
	},
	{
		name : 'phantom',
		pathQuery : 'which phantomjs',
		process : 'phantomjs'
	}
];

var browsers = supportedBrowsers.map(function (browser) {
	return function(callback) {
		var current = _.extend({}, browser);
		exec(current.pathQuery, function (err, stdout) {
			if (!stdout.length) {
				return callback(null, null);
			}

			current.command = stdout.trim();
			getVersion(current, function(err, version) {
				if(err) return callback(err);

				current.version = version;
				callback(null, current);
			});
		});
	}
});

var getVersion = function (browser, callback) {
	exec(browser.command + ' --version', function (err, stdout) {
		callback(err, (stdout && stdout.trim()));
	});
};

var cache = null;
exports.getBrowsers = function(callback) {
	if(cache !== null) {
		return callback(null, cache);
	}

	async.parallel(browsers, function(error, list) {
		if(error) return callback(error);
		cache = list.filter(function(browser) {
			return browser !== null;
		});
		callback(null, cache);
	});
}
<commit_msg>Fixes #13. Added argument list for unix platform.<commit_after>var exec = require('child_process').exec;
var path = require('path');
var _ = require('underscore');
var async = require('async');

var supportedBrowsers = exports.supported = [
	{
		name : 'chrome',
		pathQuery : 'which google-chrome',
		process : 'chrome'
	},
	{
		name : 'firefox',
		pathQuery : 'which firefox',
		process : 'firefox'
	},
	{
		name : 'opera',
		pathQuery : 'which opera',
		process : 'opera'
	},
	{
		name : 'phantom',
		pathQuery : 'which phantomjs',
		process : 'phantomjs',
		args : [__dirname + '/../../../resources/phantom.js']
	}
];

var browsers = supportedBrowsers.map(function (browser) {
	return function(callback) {
		var current = _.extend({}, browser);
		exec(current.pathQuery, function (err, stdout) {
			if (!stdout.length) {
				return callback(null, null);
			}

			current.command = stdout.trim();
			getVersion(current, function(err, version) {
				if(err) return callback(err);

				current.version = version;
				callback(null, current);
			});
		});
	}
});

var getVersion = function (browser, callback) {
	exec(browser.command + ' --version', function (err, stdout) {
		callback(err, (stdout && stdout.trim()));
	});
};

var cache = null;
exports.getBrowsers = function(callback) {
	if(cache !== null) {
		return callback(null, cache);
	}

	async.parallel(browsers, function(error, list) {
		if(error) return callback(error);
		cache = list.filter(function(browser) {
			return browser !== null;
		});
		callback(null, cache);
	});
}
<|endoftext|>


<commit_before>const {EventEmitter} = require('promise-events');
const GitHubApi = require('github');
const Bottleneck = require('bottleneck');
const express = require('express');
const Context = require('./context');

/**
 * The `robot` parameter available to plugins
 *
 * @property {logger} log - A logger
 */
class Robot {
  constructor({app, cache, logger, router, catchErrors} = {}) {
    this.events = new EventEmitter();
    this.app = app;
    this.cache = cache;
    this.router = router || new express.Router();
    this.log = wrapLogger(logger);
    this.catchErrors = catchErrors;
  }

  async receive(event) {
    return this.events.emit('*', event).then(() => {
      return this.events.emit(event.event, event);
    });
  }

  route(path) {
    if (path) {
      const router = new express.Router();
      this.router.use(path, router);
      return router;
    } else {
      return this.router;
    }
  }

  /**
   * Listen for [GitHub webhooks](https://developer.github.com/webhooks/),
   * which are fired for almost every significant action that users take on
   * GitHub.
   *
   * @param {string} event - the name of the [GitHub webhook
   * event](https://developer.github.com/webhooks/#events). Most events also
   * include an "action". For example, the * [`issues`](
   * https://developer.github.com/v3/activity/events/types/#issuesevent)
   * event has actions of `assigned`, `unassigned`, `labeled`, `unlabeled`,
   * `opened`, `edited`, `milestoned`, `demilestoned`, `closed`, and `reopened`.
   * Often, your bot will only care about one type of action, so you can append
   * it to the event name with a `.`, like `issues.closed`.
   *
   * @param {Robot~webhookCallback} callback - a function to call when the
   * webhook is received.
   *
   * @example
   *
   * robot.on('push', context => {
   *   // Code was just pushed.
   * });
   *
   * robot.on('issues.opened', context => {
   *   // An issue was just opened.
   * });
   */
  on(event, callback) {
    if (callback.length === 2) {
      const caller = (new Error()).stack.split('\n')[2];
      console.warn('DEPRECATED: Event callbacks now only take a single `context` argument.');
      console.warn(caller);
    }

    const [name, action] = event.split('.');

    return this.events.on(name, async event => {
      if (!action || action === event.payload.action) {
        try {
          const github = await this.auth(event.payload.installation.id);
          const context = new Context(event, github);
          return callback(context, context /* DEPRECATED: for backward compat */);
        } catch (err) {
          this.log.error(err);
          if (!this.catchErrors) {
            throw err;
          }
        }
      }
    });
  }

  /**
   * Authenticate and get a GitHub client that can be used to make API calls.
   *
   * You'll probably want to use `context.github` instead.
   *
   * **Note**: `robot.auth` is asynchronous, so it needs to be prefixed with a
   * [`await`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await)
   * to wait for the magic to happen.
   *
   * @example
   *
   *  module.exports = function(robot) {
   *    robot.on('issues.opened', async context => {
   *      const github = await robot.auth();
   *    });
   *  };
   *
   * @param {number} [id] - ID of the installation, which can be extracted from
   * `context.payload.installation.id`. If called without this parameter, the
   * client wil authenticate [as the app](https://developer.github.com/apps/building-integrations/setting-up-and-registering-github-apps/about-authentication-options-for-github-apps/#authenticating-as-a-github-app)
   * instead of as a specific installation, which means it can only be used for
   * [app APIs](https://developer.github.com/v3/apps/).
   *
   * @returns {Promise<github>} - An authenticated GitHub API client
   * @private
   */
  async auth(id) {
    let github;

    if (id) {
      const res = await this.cache.wrap(`app:${id}:token`, () => {
        this.log.trace(`creating token for installation ${id}`);
        return this.app.createToken(id);
      }, {ttl: 60 * 60});

      github = new GitHubApi({debug: process.env.LOG_LEVEL === 'trace'});
      github.authenticate({type: 'token', token: res.data.token});
    } else {
      github = await this.app.asApp();
    }

    return probotEnhancedClient(github);
  }
}

function probotEnhancedClient(github) {
  github = rateLimitedClient(github);

  github.paginate = require('./paginate');

  return github;
}

// Hack client to only allow one request at a time with a 1s delay
// https://github.com/mikedeboer/node-github/issues/526
function rateLimitedClient(github) {
  const limiter = new Bottleneck(1, 1000);
  const oldHandler = github.handler;
  github.handler = (msg, block, callback) => {
    limiter.submit(oldHandler.bind(github), msg, block, callback);
  };
  return github;
}

// Return a function that defaults to "debug" level, and has properties for
// other levels:
//
//     robot.log("debug")
//     robot.log.trace("verbose details");
//
function wrapLogger(logger) {
  const fn = logger ? logger.debug.bind(logger) : function () { };

  // Add level methods on the logger
  ['trace', 'debug', 'info', 'warn', 'error', 'fatal'].forEach(level => {
    fn[level] = logger ? logger[level].bind(logger) : function () { };
  });

  return fn;
}

module.exports = (...args) => new Robot(...args);

/**
* Do the thing
* @callback Robot~webhookCallback
* @param {Context} context - the context of the event that was triggered,
*   including `context.payload`, and helpers for extracting information from
*   the payload, which can be passed to GitHub API calls.
*
*  ```js
*  module.exports = robot => {
*    robot.on('push', context => {
*      // Code was pushed to the repo, what should we do with it?
*      robot.log(context);
*    });
*  };
*  ```
*/

/**
 * A [GitHub webhook event](https://developer.github.com/webhooks/#events) payload
 *
 * @typedef payload
 */

/**
 * the [github Node.js module](https://github.com/mikedeboer/node-github),
 * which wraps the [GitHub API](https://developer.github.com/v3/) and allows
 * you to do almost anything programmatically that you can do through a web
 * browser.
 * @typedef github
 * @see {@link https://github.com/mikedeboer/node-github}
 */

 /**
  * A logger backed by [bunyan](https://github.com/trentm/node-bunyan)
  *
  * The default log level is `debug`, but you can change it by setting the
  * `LOG_LEVEL` environment variable to `trace`, `info`, `warn`, `error`, or
  * `fatal`.
  *
  * @typedef logger
  *
  * @example
  *
  * robot.log("This is a debug message");
  * robot.log.debug("…so is this");
  * robot.log.trace("Now we're talking");
  * robot.log.info("I thought you should know…");
  * robot.log.warn("Woah there");
  * robot.log.error("ETOOMANYLOGS");
  * robot.log.fatal("Goodbye, cruel world!");
  */
<commit_msg>Add jsdoc on robot.route<commit_after>const {EventEmitter} = require('promise-events');
const GitHubApi = require('github');
const Bottleneck = require('bottleneck');
const express = require('express');
const Context = require('./context');

/**
 * The `robot` parameter available to plugins
 *
 * @property {logger} log - A logger
 */
class Robot {
  constructor({app, cache, logger, router, catchErrors} = {}) {
    this.events = new EventEmitter();
    this.app = app;
    this.cache = cache;
    this.router = router || new express.Router();
    this.log = wrapLogger(logger);
    this.catchErrors = catchErrors;
  }

  async receive(event) {
    return this.events.emit('*', event).then(() => {
      return this.events.emit(event.event, event);
    });
  }

  /**
   * Get an {@link http://expressjs.com|express} router that can be used to
   * expose HTTP endpoints
   *
   * @example
   * module.exports = robot => {
   *   // Get an express router to expose new HTTP endpoints
   *   const app = robot.route('/my-plugin');
   *
   *   // Use any middleware
   *   app.use(require('express').static(__dirname + '/public'));
   *
   *   // Add a new route
   *   app.get('/hello-world', (req, res) => {
   *     res.end('Hello World');
   *   });
   * };
   *
   * @param {string} path - the prefix for the routes
   * @returns {@link http://expressjs.com/en/4x/api.html#router|express.Router}
   */
  route(path) {
    if (path) {
      const router = new express.Router();
      this.router.use(path, router);
      return router;
    } else {
      return this.router;
    }
  }

  /**
   * Listen for [GitHub webhooks](https://developer.github.com/webhooks/),
   * which are fired for almost every significant action that users take on
   * GitHub.
   *
   * @param {string} event - the name of the [GitHub webhook
   * event](https://developer.github.com/webhooks/#events). Most events also
   * include an "action". For example, the * [`issues`](
   * https://developer.github.com/v3/activity/events/types/#issuesevent)
   * event has actions of `assigned`, `unassigned`, `labeled`, `unlabeled`,
   * `opened`, `edited`, `milestoned`, `demilestoned`, `closed`, and `reopened`.
   * Often, your bot will only care about one type of action, so you can append
   * it to the event name with a `.`, like `issues.closed`.
   *
   * @param {Robot~webhookCallback} callback - a function to call when the
   * webhook is received.
   *
   * @example
   *
   * robot.on('push', context => {
   *   // Code was just pushed.
   * });
   *
   * robot.on('issues.opened', context => {
   *   // An issue was just opened.
   * });
   */
  on(event, callback) {
    if (callback.length === 2) {
      const caller = (new Error()).stack.split('\n')[2];
      console.warn('DEPRECATED: Event callbacks now only take a single `context` argument.');
      console.warn(caller);
    }

    const [name, action] = event.split('.');

    return this.events.on(name, async event => {
      if (!action || action === event.payload.action) {
        try {
          const github = await this.auth(event.payload.installation.id);
          const context = new Context(event, github);
          return callback(context, context /* DEPRECATED: for backward compat */);
        } catch (err) {
          this.log.error(err);
          if (!this.catchErrors) {
            throw err;
          }
        }
      }
    });
  }

  /**
   * Authenticate and get a GitHub client that can be used to make API calls.
   *
   * You'll probably want to use `context.github` instead.
   *
   * **Note**: `robot.auth` is asynchronous, so it needs to be prefixed with a
   * [`await`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await)
   * to wait for the magic to happen.
   *
   * @example
   *
   *  module.exports = function(robot) {
   *    robot.on('issues.opened', async context => {
   *      const github = await robot.auth();
   *    });
   *  };
   *
   * @param {number} [id] - ID of the installation, which can be extracted from
   * `context.payload.installation.id`. If called without this parameter, the
   * client wil authenticate [as the app](https://developer.github.com/apps/building-integrations/setting-up-and-registering-github-apps/about-authentication-options-for-github-apps/#authenticating-as-a-github-app)
   * instead of as a specific installation, which means it can only be used for
   * [app APIs](https://developer.github.com/v3/apps/).
   *
   * @returns {Promise<github>} - An authenticated GitHub API client
   * @private
   */
  async auth(id) {
    let github;

    if (id) {
      const res = await this.cache.wrap(`app:${id}:token`, () => {
        this.log.trace(`creating token for installation ${id}`);
        return this.app.createToken(id);
      }, {ttl: 60 * 60});

      github = new GitHubApi({debug: process.env.LOG_LEVEL === 'trace'});
      github.authenticate({type: 'token', token: res.data.token});
    } else {
      github = await this.app.asApp();
    }

    return probotEnhancedClient(github);
  }
}

function probotEnhancedClient(github) {
  github = rateLimitedClient(github);

  github.paginate = require('./paginate');

  return github;
}

// Hack client to only allow one request at a time with a 1s delay
// https://github.com/mikedeboer/node-github/issues/526
function rateLimitedClient(github) {
  const limiter = new Bottleneck(1, 1000);
  const oldHandler = github.handler;
  github.handler = (msg, block, callback) => {
    limiter.submit(oldHandler.bind(github), msg, block, callback);
  };
  return github;
}

// Return a function that defaults to "debug" level, and has properties for
// other levels:
//
//     robot.log("debug")
//     robot.log.trace("verbose details");
//
function wrapLogger(logger) {
  const fn = logger ? logger.debug.bind(logger) : function () { };

  // Add level methods on the logger
  ['trace', 'debug', 'info', 'warn', 'error', 'fatal'].forEach(level => {
    fn[level] = logger ? logger[level].bind(logger) : function () { };
  });

  return fn;
}

module.exports = (...args) => new Robot(...args);

/**
* Do the thing
* @callback Robot~webhookCallback
* @param {Context} context - the context of the event that was triggered,
*   including `context.payload`, and helpers for extracting information from
*   the payload, which can be passed to GitHub API calls.
*
*  ```js
*  module.exports = robot => {
*    robot.on('push', context => {
*      // Code was pushed to the repo, what should we do with it?
*      robot.log(context);
*    });
*  };
*  ```
*/

/**
 * A [GitHub webhook event](https://developer.github.com/webhooks/#events) payload
 *
 * @typedef payload
 */

/**
 * the [github Node.js module](https://github.com/mikedeboer/node-github),
 * which wraps the [GitHub API](https://developer.github.com/v3/) and allows
 * you to do almost anything programmatically that you can do through a web
 * browser.
 * @typedef github
 * @see {@link https://github.com/mikedeboer/node-github}
 */

 /**
  * A logger backed by [bunyan](https://github.com/trentm/node-bunyan)
  *
  * The default log level is `debug`, but you can change it by setting the
  * `LOG_LEVEL` environment variable to `trace`, `info`, `warn`, `error`, or
  * `fatal`.
  *
  * @typedef logger
  *
  * @example
  *
  * robot.log("This is a debug message");
  * robot.log.debug("…so is this");
  * robot.log.trace("Now we're talking");
  * robot.log.info("I thought you should know…");
  * robot.log.warn("Woah there");
  * robot.log.error("ETOOMANYLOGS");
  * robot.log.fatal("Goodbye, cruel world!");
  */
<|endoftext|>


<commit_before>if(typeof Roles !== 'undefined'){
    Roles.addGroupRole = function(groupId, role){
        var id,
            match;

        if (!role
            || 'string' !== typeof role
            || role.trim().length === 0) {
            return;
        }

        try {
            id = Meteor.roles.insert({'name': role.trim(), 'groupId': groupId});
            return id;
        } catch (e) {
            if (e.name !== 'MongoError') throw e;
            match = e.err.match(/^E11000 duplicate key error index: ([^ ]+)/);
            if (!match) throw e;
            if (match[1].indexOf('$name') !== -1)
                throw new Meteor.Error(403, "Role already exists.");
            throw e
        }
    };

    Roles.deleteGroupRole = function(groupId, role){
        if (!role) return;

        var foundExistingUser = Groups.findOne({_id:groupId,users: {roles:{$elemMatch: role}}});

        if (foundExistingUser) {
            throw new Meteor.Error(403, 'Role in use in '+foundExistingUser.groupname);
        }

        var thisRole = Meteor.roles.findOne({name: role, groupId: groupId});
        if (thisRole) {
            Meteor.roles.remove({_id: thisRole._id});
        }
    };
}<commit_msg>check rights for changing roles in groups<commit_after>if (typeof Roles !== 'undefined') {
    Roles.userIsInGroupRole = function (userId, groupId, roles) {
        if (typeof roles !== 'undefined') {
            var role = Groups.findOne({
                _id: groupId, 'users.id': userId,
                'users.roles': roles
            });
        }
        if (typeof role !== 'undefined')
            return true;

        return false;
    };

    Roles.addGroupRole = function (groupId, role) {
        if (Roles.userIsInGroupRole(Meteor.userId(), 'admin') || Roles.userIsInRole(Meteor.userId(), ['superAdmin', 'admin'])) {
            var id,
                match;

            if (!role
                || 'string' !== typeof role
                || role.trim().length === 0) {
                return;
            }

            try {
                id = Meteor.roles.insert({'name': role.trim(), 'groupId': groupId});
                return id;
            } catch (e) {
                if (e.name !== 'MongoError') throw e;
                match = e.err.match(/^E11000 duplicate key error index: ([^ ]+)/);
                if (!match) throw e;
                if (match[1].indexOf('$name') !== -1)
                    throw new Meteor.Error(403, "Role already exists.");
                throw e
            }
        } else {
            throw new Meteor.error("addGroupRole", "You are not allowed to add a groupRole")
        }
    };

    Roles.deleteGroupRole = function (groupId, role) {
        if (Roles.userIsInGroupRole(Meteor.userId(), 'admin') || Roles.userIsInRole(Meteor.userId(), ['superAdmin', 'admin'])) {
            if (!role) return;

            var foundExistingUser = Groups.findOne({_id: groupId, users: {roles: {$elemMatch: role}}});

            if (foundExistingUser) {
                throw new Meteor.Error(403, 'Role in use in ' + foundExistingUser.groupname);
            }

            var thisRole = Meteor.roles.findOne({name: role, groupId: groupId});
            if (thisRole) {
                Meteor.roles.remove({_id: thisRole._id});
            }
        } else {
            throw new Meteor.error("deleteGroupRole", "You are not allowed to remove a groupRole")
        }
    };
}<|endoftext|>


<commit_before>var _ = require('lodash')
  , db;

module.exports.init = function(brain) {
  db = brain;
  db.rooms = db.rooms || [];
};

module.exports.add = function(room) {
  if (!has(room)) {
    db.rooms.push(room);
  }
};

module.exports.remove = function(room) {
  return _.remove(db.rooms, room);
};

module.exports.has = has;

function has(room) {
  return _.contains(db.rooms, room);
}
<commit_msg>removing should work now<commit_after>var _ = require('lodash')
  , db;

module.exports.init = function(brain) {
  db = brain;
  db.rooms = db.rooms || [];
};

module.exports.add = function(room) {
  if (!has(room)) {
    db.rooms.push(room);
  }
};

module.exports.remove = function(room) {
  return _.remove(db.rooms, function(r) {
    return r === room;
  });
};

module.exports.has = has;

function has(room) {
  return _.contains(db.rooms, room);
}
<|endoftext|>


<commit_before>/*
    pd(obj) -> propertyDescriptorsOfObject {
        bindAll: function that binds all the methods of an object to the object,
        extend: function that extends the first argument with the rest
        Name: returns a namespace(anyKey) -> uniqueObject function
    }

    pd requires ES5. Uses the shimmable subset of ES5.
*/
(function (Object, slice) {
    "use strict";

    extend(pd, {
        bindAll: bindAll,
        extend: extend,
        Name: Name
    });

    typeof window !== "undefined" ? window.pd = pd : module.exports = pd;

    /*
        pd will return all the own propertydescriptors of the object

        @param Object object - object to get pds from.

        @return Object - A hash of key/propertyDescriptors
    */
    function pd(obj, retObj) {
        retObj = {};
        Object.getOwnPropertyNames(obj).forEach(function(key) {
            var pd = Object.getOwnPropertyDescriptor(obj, key);
            retObj[key] = pd;
        });
        return retObj;
    }

    /*
        Extend will extend the firat parameter with any other parameters
        passed in. Only the own property names will be extended into
        the object

        @param Object target - target to be extended
        @arguments Array [target, ...] - the rest of the objects passed
            in will extended into the target

        @return Object - the target
    */
    function extend(target) {
        slice.call(arguments, 1).forEach(function(source) {
            Object.defineProperties(target, pd(source));
        });
        return target;
    }

    /*
        defines a namespace object. This hides a "privates" object on object
        under the "key" namespace

        @param Object object - object to hide a privates object on
        @param Object key - key to hide it under

        @author Gozala : https://gist.github.com/1269991

        @return Object privates
    */
    function namespace(object, key) {
        var privates = Object.create(object),
            valueOf = object.valueOf;

        Object.defineProperty(object, "valueOf", {
            value: function(value) {
                return value !== key ? valueOf.apply(this, arguments) : privates;
            },
            writable: true
        });

        return privates;
    }

    /*
        Constructs a Name function, when given an object it will return a
        privates object.

        @author Gozala : https://gist.github.com/1269991

        @return Function name
    */
    function Name(key) {
        key = {};
        return name;

        function name(object) {
            var privates = object.valueOf(key);
            return privates !== object ? privates : namespace(object, key)
        }
    }

    /*
        bindAll binds all methods to have their context set to the object

        @param Object obj - the object to bind methods on
        @param Array whitelist - optional whitelist of methods to bind

        @return Object - the bound object
    */
    function bindAll(obj, whitelist) {
        (whitelist || Object.keys(obj).filter(isMethod)).forEach(bindMethods);

        return obj;

        function isMethod(key) {
            return obj[key].call;
        }

        function bindMethods(name) {
            obj[name] = obj[name].bind(obj)
        }
    }
})(Object, [].slice);<commit_msg>Check `.call` is actually `Function.prototype.call`<commit_after>/*
    pd(obj) -> propertyDescriptorsOfObject {
        bindAll: function that binds all the methods of an object to the object,
        extend: function that extends the first argument with the rest
        Name: returns a namespace(anyKey) -> uniqueObject function
    }

    pd requires ES5. Uses the shimmable subset of ES5.
*/
(function (Object, slice) {
    "use strict";

    extend(pd, {
        bindAll: bindAll,
        extend: extend,
        Name: Name
    });

    typeof window !== "undefined" ? window.pd = pd : module.exports = pd;

    /*
        pd will return all the own propertydescriptors of the object

        @param Object object - object to get pds from.

        @return Object - A hash of key/propertyDescriptors
    */
    function pd(obj, retObj) {
        retObj = {};
        Object.getOwnPropertyNames(obj).forEach(function(key) {
            var pd = Object.getOwnPropertyDescriptor(obj, key);
            retObj[key] = pd;
        });
        return retObj;
    }

    /*
        Extend will extend the firat parameter with any other parameters
        passed in. Only the own property names will be extended into
        the object

        @param Object target - target to be extended
        @arguments Array [target, ...] - the rest of the objects passed
            in will extended into the target

        @return Object - the target
    */
    function extend(target) {
        slice.call(arguments, 1).forEach(function(source) {
            Object.defineProperties(target, pd(source));
        });
        return target;
    }

    /*
        defines a namespace object. This hides a "privates" object on object
        under the "key" namespace

        @param Object object - object to hide a privates object on
        @param Object key - key to hide it under

        @author Gozala : https://gist.github.com/1269991

        @return Object privates
    */
    function namespace(object, key) {
        var privates = Object.create(object),
            valueOf = object.valueOf;

        Object.defineProperty(object, "valueOf", {
            value: function(value) {
                return value !== key ? valueOf.apply(this, arguments) : privates;
            },
            writable: true
        });

        return privates;
    }

    /*
        Constructs a Name function, when given an object it will return a
        privates object.

        @author Gozala : https://gist.github.com/1269991

        @return Function name
    */
    function Name(key) {
        key = {};
        return name;

        function name(object) {
            var privates = object.valueOf(key);
            return privates !== object ? privates : namespace(object, key)
        }
    }

    /*
        bindAll binds all methods to have their context set to the object

        @param Object obj - the object to bind methods on
        @param Array whitelist - optional whitelist of methods to bind

        @return Object - the bound object
    */
    function bindAll(obj, whitelist) {
        (whitelist || Object.keys(obj).filter(isMethod)).forEach(bindMethods);

        return obj;

        function isMethod(key) {
            return obj[key].call === isMethod.call;
        }

        function bindMethods(name) {
            obj[name] = obj[name].bind(obj)
        }
    }
})(Object, [].slice);<|endoftext|>


<commit_before>var _ = require('underscore');

var Route = module.exports = function (path, options) {
    this.path             = path;
    this.pathRE           = this._compile(path);

    this.to               = null;
    this.via              = ['get','post','put','delete'];
    this.redirectTo       = null;
    this.autoParseBody    = undefined;
    this.maxContentLength = undefined;

    _.extend(this, options);
};

Route.prototype = {

    match: function (path) {
        var params = null;
        var pathRE = this.pathRE;
        var matches;

        if ((matches = path.match(pathRE)) !== null)
        {
            params = {};
            for (var i = 0; i < pathRE.keys.length; i++)
                params[pathRE.keys[i]] = matches[i + 1];
        }
        return params;
    },

    setPath: function (path) {
        this.path = path;
        this.pathRE = (path !== null) ? this._compile(path) : null;
    },

    getController: function () {
        var tokens;

        if (_.isString(this.to)
                && (tokens = this.to.split('#')).length === 2)
            return tokens[0];
        return null;
    },

    getAction: function () {
        var tokens;

        if (_.isString(this.to)
                && (tokens = this.to.split('#')).length === 2)
            return tokens[1];
        return null;
    },

    _compile: function (path) {
        var keys    = [];
        var pattern = path.replace(/:(\w+)?/g, function (str, key) {
            keys.push(key);
            return "([a-zA-Z0-9-$_.+!*'(),%]+)"; // According to RFC-1738 (http://www.rfc-editor.org/rfc/rfc1738.txt).
        });

        return _.extend(new RegExp('^' + pattern + '$'), {
            keys: keys
        });
    },

    get to() {
        if (this.controller !== null && this.action !== null)
            return this.controller + '#' + this.action;
        return null;
    },

    set to(to) {
        var tokens;

        if (to === null)
        {
            this.controller = null;
            this.action = null;
        }
        else if (_.isString(to) && (tokens = to.split('#')).length === 2)
        {
            this.controller = tokens[0];
            this.action = tokens[1];
        }
    }

};
<commit_msg>remove autoParseBody and maxContentLength properties from Route<commit_after>var _ = require('underscore');

var Route = module.exports = function (path, options) {
    this.path       = path;
    this.pathRE     = this._compile(path);

    this.to         = null;
    this.via        = ['get','post','put','delete'];
    this.redirectTo = null;

    _.extend(this, options);
};

Route.prototype = {

    match: function (path) {
        var params = null;
        var pathRE = this.pathRE;
        var matches;

        if ((matches = path.match(pathRE)) !== null)
        {
            params = {};
            for (var i = 0; i < pathRE.keys.length; i++)
                params[pathRE.keys[i]] = matches[i + 1];
        }
        return params;
    },

    setPath: function (path) {
        this.path = path;
        this.pathRE = (path !== null) ? this._compile(path) : null;
    },

    getController: function () {
        var tokens;

        if (_.isString(this.to)
                && (tokens = this.to.split('#')).length === 2)
            return tokens[0];
        return null;
    },

    getAction: function () {
        var tokens;

        if (_.isString(this.to)
                && (tokens = this.to.split('#')).length === 2)
            return tokens[1];
        return null;
    },

    _compile: function (path) {
        var keys    = [];
        var pattern = path.replace(/:(\w+)?/g, function (str, key) {
            keys.push(key);
            return "([a-zA-Z0-9-$_.+!*'(),%]+)"; // According to RFC-1738 (http://www.rfc-editor.org/rfc/rfc1738.txt).
        });

        return _.extend(new RegExp('^' + pattern + '$'), {
            keys: keys
        });
    },

    get to() {
        if (this.controller !== null && this.action !== null)
            return this.controller + '#' + this.action;
        return null;
    },

    set to(to) {
        var tokens;

        if (to === null)
        {
            this.controller = null;
            this.action = null;
        }
        else if (_.isString(to) && (tokens = to.split('#')).length === 2)
        {
            this.controller = tokens[0];
            this.action = tokens[1];
        }
    }

};
<|endoftext|>