<commit_before>/**
 *
 * input:
 *
 * {% multicodeblock %}
 * ---js esnext
 * const greeting = `hello ${name}`;
 * ---js es5
 * var greeting = 'hello ' + name;
 * ---php php
 * $greeting = 'hello ' . $name;
 * {% endmulticodeblock %}
 *
 * pseudo-output:
 *
 * {% raw %}
 *

 * {% endraw %}
 *
 * ```js
 * const greeting = `hello ${name}`;
 * ```
 *
 * ```js
 * var greeting = 'hello ' + name;
 * ```
 *
 * ```php
 * $greeting = 'hello ' . $name;
 * {% raw %}
 * </div>
 * {% endraw %}
 *
 *
 * You can also use a default language:
 *
 * {% multicodeblock js %}
 * --- esnext
 * const greeting = `hello ${name}`;
 * --- es5
 * var greeting = 'hello ' + name;
 * {% endmulticodeblock %}
 *
 */

const parse = ([defaultLanguage], content) => {
  const [_, textParts] = content.split('---');

  const objectParts = textParts.map((textPart) => {
    const [configText, ...content] = textPart.split('\n');
    const [language, slot] = configText.split(' ');

    return {
      config: {
        language,
        slot
      },
      content: content.join('\n')
    };
  });

  const htmlParts = objectParts.map((objectPart) => {
    const pre = markdown(
      `\`\`\`${objectPart.config.language}\n${objectPart.content}`
    );

    const [preTag, ...content] = pre.split('\n');
    const [preTagName, ...preTagParts] = preTag.split(' ');
    const slottedPre = `${preTagName} slot=${objectPart.config.slot || defaultLanguage || 'js'} ${preTagParts.join(' ')}\n${content.join('\n')}`
  })

  return `
<div class="hexo-multi-codeblock">
  ${htmlParts.join('\n')}
</div>
`
}

hexo.extend.tag.register('multicodeblock', parse)
<commit_msg>fixed no end tag<commit_after>/**
 *
 * input:
 *
 * {% multicodeblock %}
 * ---js esnext
 * const greeting = `hello ${name}`;
 * ---js es5
 * var greeting = 'hello ' + name;
 * ---php php
 * $greeting = 'hello ' . $name;
 * {% endmulticodeblock %}
 *
 * pseudo-output:
 *
 * {% raw %}
 * <div class="hexo-multi-codeblock">
 * {% endraw %}
 *   <!-- this will be <pre slot="esnext" ...>...</pre> -->
 * ```js
 * const greeting = `hello ${name}`;
 * ```
 *   <!-- <pre slot="es5" ...>...</pre> -->
 * ```js
 * var greeting = 'hello ' + name;
 * ```
 *   <!-- <pre slot="php" ...>...</pre> -->
 * ```php
 * $greeting = 'hello ' . $name;
 * {% raw %}
 *

 * {% endraw %}
 *
 *
 * You can also use a default language:
 *
 * {% multicodeblock js %}
 * --- esnext
 * const greeting = `hello ${name}`;
 * --- es5
 * var greeting = 'hello ' + name;
 * {% endmulticodeblock %}
 *
 */

const parse = ([defaultLanguage], content) => {
  const [_, textParts] = content.split('---');

  const objectParts = textParts.map((textPart) => {
    const [configText, ...content] = textPart.split('\n');
    const [language, slot] = configText.split(' ');

    return {
      config: {
        language,
        slot
      },
      content: content.join('\n')
    };
  });

  const htmlParts = objectParts.map((objectPart) => {
    const pre = markdown(
      `\`\`\`${objectPart.config.language}\n${objectPart.content}`
    );

    const [preTag, ...content] = pre.split('\n');
    const [preTagName, ...preTagParts] = preTag.split(' ');
    const slottedPre = `${preTagName} slot=${objectPart.config.slot || defaultLanguage || 'js'} ${preTagParts.join(' ')}\n${content.join('\n')}`
  })

  return `

  ${htmlParts.join('\n')}

`
}

hexo.extend.tag.register('multicodeblock', parse, {ends: true})
<|endoftext|>


<commit_before>"use strict";

var spread       = require("es5-ext/function/#/spread")
  , deferred     = require("deferred")
  , path         = require("path")
  , commonPath   = require("path2/common")
  , runInContext = require("vm").runInContext
  , out          = require("./lib/console")
  , configure    = require("./lib/configure")
  , load         = require("./lib/load")
  , run          = require("./lib/run")

  , resolve = path.resolve, map = Array.prototype.map
  , suite, isError;

isError = function (e, context) {
	if (e instanceof Error) return true;
	if (context !== global) {
		return runInContext("(function () { return this instanceof Error; })",
			context).call(e);
	}
	return false;
};

suite = {
	init: function (paths, options) {
		var conf, d, root;
		d = deferred();
		paths = map.call(paths, function (path) {
 return resolve(path);
});
		this.resolve = d.resolve;
		this.console = out(options);
		this.tail = deferred(null);
		if (paths.length > 1) {
			root = commonPath.apply(null, paths);
			this.rindex = root ? root.length + 1 : 0;
		} else if (paths.length) {
			this.rindex = paths[0].length + 1;
		}

		conf = configure(paths);
		conf("data", this.ondata.bind(this));
		conf("end", this.onend.bind(this));
		return d.promise;
	},
	ondata: function () {
		this.tail = this.tail(spread.call(this.process).bind(this, arguments));
	},
	process: function (p, fpath, tpath, context) {
		var pname = p.slice(this.rindex), fname, logger, o, d;
		d = deferred();
		this.console.break();
		if (fpath instanceof Error) {
			// Wrong path
			this.console.error(pname, null, fpath);
			return d.resolve();
		}

		fname = fpath.slice(this.rindex);
		if (tpath instanceof Error) {
			if (tpath.type === "testfile") {
				// Input is a test file, ignore
				return d.resolve();
			}
			// Could not assume test file path (not within package)
			// or there were problems with obtaining context
			this.console.error(pname, fname, tpath);
			return d.resolve();
		}

		// Configured ok, load files
		o = load(fpath, tpath, context);

		// Any files missing, any evaluation errors ?
		if (o.testee === undefined) {
			// File not accessible
			this.console.error(pname, fname, "Couldn't load module '" + fpath + "'");
			return d.resolve();
		}

		if (isError(o.test, context)) {
			this.console.error(pname, fname, o.test);
			return d.resolve();
		}
		if (isError(o.testee, context)) {
			this.console.error(pname, fname, o.testee);
			return d.resolve();
		}
		if (!o.test) {
			this.console.error(pname, fname, "Tests could not be loaded, tried '" +
				tpath + "'");
			return d.resolve();
		}

		// Loaded ok, run tests
		logger = run(o.testee, o.test);
		logger.on("data", function (o) {
			var name = [fname].concat(o.msg);
			if (o.type === "pass") {
				name.push(o.data);
			} else if ((o.type === "fail") && o.data.operator) {
				name.push(o.data.message);
			}
			name = name.filter(Boolean).join(": ");
			this.console[o.type](fname, name, o.data);
		}.bind(this));
		logger.on("end", function () {
			d.resolve();
		});

		return d.promise;
	},
	onend: function () {
		this.tail(this.end.bind(this)).done();
		delete this.tail;
	},
	end: function () {
		this.console.end();
		this.resolve(this);
	}
};

module.exports = function (paths, options) {
	return Object.create(suite).init(paths, options);
};
<commit_msg>style: prettier<commit_after>"use strict";

var spread       = require("es5-ext/function/#/spread")
  , deferred     = require("deferred")
  , path         = require("path")
  , commonPath   = require("path2/common")
  , runInContext = require("vm").runInContext
  , out          = require("./lib/console")
  , configure    = require("./lib/configure")
  , load         = require("./lib/load")
  , run          = require("./lib/run");

var resolve = path.resolve, map = Array.prototype.map, suite, isError;

isError = function (e, context) {
	if (e instanceof Error) return true;
	if (context !== global) {
		return runInContext("(function () { return this instanceof Error; })", context).call(e);
	}
	return false;
};

suite = {
	init: function (paths, options) {
		var conf, d, root;
		d = deferred();
		paths = map.call(paths, function (path) {
			return resolve(path);
		});
		this.resolve = d.resolve;
		this.console = out(options);
		this.tail = deferred(null);
		if (paths.length > 1) {
			root = commonPath.apply(null, paths);
			this.rindex = root ? root.length + 1 : 0;
		} else if (paths.length) {
			this.rindex = paths[0].length + 1;
		}

		conf = configure(paths);
		conf("data", this.ondata.bind(this));
		conf("end", this.onend.bind(this));
		return d.promise;
	},
	ondata: function () {
		this.tail = this.tail(spread.call(this.process).bind(this, arguments));
	},
	process: function (p, fpath, tpath, context) {
		var pname = p.slice(this.rindex), fname, logger, o, d;
		d = deferred();
		this.console.break();
		if (fpath instanceof Error) {
			// Wrong path
			this.console.error(pname, null, fpath);
			return d.resolve();
		}

		fname = fpath.slice(this.rindex);
		if (tpath instanceof Error) {
			if (tpath.type === "testfile") {
				// Input is a test file, ignore
				return d.resolve();
			}
			// Could not assume test file path (not within package)
			// or there were problems with obtaining context
			this.console.error(pname, fname, tpath);
			return d.resolve();
		}

		// Configured ok, load files
		o = load(fpath, tpath, context);

		// Any files missing, any evaluation errors ?
		if (o.testee === undefined) {
			// File not accessible
			this.console.error(pname, fname, "Couldn't load module '" + fpath + "'");
			return d.resolve();
		}

		if (isError(o.test, context)) {
			this.console.error(pname, fname, o.test);
			return d.resolve();
		}
		if (isError(o.testee, context)) {
			this.console.error(pname, fname, o.testee);
			return d.resolve();
		}
		if (!o.test) {
			this.console.error(pname, fname, "Tests could not be loaded, tried '" + tpath + "'");
			return d.resolve();
		}

		// Loaded ok, run tests
		logger = run(o.testee, o.test);
		logger.on(
			"data",
			function (o) {
				var name = [fname].concat(o.msg);
				if (o.type === "pass") {
					name.push(o.data);
				} else if (o.type === "fail" && o.data.operator) {
					name.push(o.data.message);
				}
				name = name.filter(Boolean).join(": ");
				this.console[o.type](fname, name, o.data);
			}.bind(this)
		);
		logger.on("end", function () {
			d.resolve();
		});

		return d.promise;
	},
	onend: function () {
		this.tail(this.end.bind(this)).done();
		delete this.tail;
	},
	end: function () {
		this.console.end();
		this.resolve(this);
	}
};

module.exports = function (paths, options) {
	return Object.create(suite).init(paths, options);
};
<|endoftext|>


<commit_before>/**
 * Created by daxlab on 21/12/15.
 */

'use strict';
var exec = require('child_process').exec;
if (process.platform === 'darwin') {
    //module.exports = require('./lib/osx');
} else if (process.platform === 'win32') {
    //module.exports = require('./lib/win');
    var util = {};
    util.getMAC = function(cb) {
      exec('getmac', function (err, stdout, stderr) {
          if (!err) {
              var temp = stdout.split(' ');
              temp = temp[51];
              var MAC = temp.substring(temp.length - 17, temp.length);
              MAC = MAC.split('-').join(':');
              return cb(null, MAC);
          }
          else {
              console.log('Some error occurred in getting MAC.');
              return cb(err, null);
          }
      });
    };
    module.exports = util;
} else {
    //module.exports = require('./lib/linux');
    var util = {};
    util.getMAC = function(cb) {
            exec('ifconfig | grep HWaddr', function (err, stdout, stderr) {
                if (!err) {
                    var temp = stdout.split(' ');
                    var MAC = temp[10].toUpperCase();
                    return cb(null, MAC);
                }
                else {
                    console.log('Some error occurred in getting MAC.');
                    return cb(err, null);
                }
            });
    };
    module.exports = util;
}
<commit_msg>clean up<commit_after>/**
 * Created by daxlab on 21/12/15.
 */

'use strict';
var exec = require('child_process').exec;
if (process.platform === 'darwin') {

} else if (process.platform === 'win32') {
    var util = {};
    util.getMAC = function(cb) {
      exec('getmac', function (err, stdout, stderr) {
          if (!err) {
              var temp = stdout.split(' ');
              temp = temp[51];
              var MAC = temp.substring(temp.length - 17, temp.length);
              MAC = MAC.split('-').join(':');
              return cb(null, MAC);
          }
          else {
              console.log('Some error occurred in getting MAC.');
              return cb(err, null);
          }
      });
    };
    module.exports = util;
} else {
    var util = {};
    util.getMAC = function(cb) {
            exec('ifconfig | grep HWaddr', function (err, stdout, stderr) {
                if (!err) {
                    var temp = stdout.split(' ');
                    var MAC = temp[10].toUpperCase();
                    return cb(null, MAC);
                }
                else {
                    console.log('Some error occurred in getting MAC.');
                    return cb(err, null);
                }
            });
    };
    module.exports = util;
}
<|endoftext|>


<commit_before>var normalize = require('normalize-object');

/**
 * Docs...
 * @param  {Object} superagent
 * @param  {String} type
 * @return {void}
 */
function serializer(superagent, type) {
  //TODO: Check arguments size
  //TODO: Validate arguments

  var Request = superagent.Request;
  var end = Request.prototype.end;

  Request.prototype.end = function(cb) {
    console.log('mock end');
    return end.call(this, function(err, res) {
      if (typeof cb !== 'function') return;

      var serializedRes;

      try {
        serializedRes = JSON.parse(res.text);
        serializedRes = normalize(serializedRes, type);
      } catch (e) {
        serializedRes = res.text;
      }

      cb(err, serializedRes);
    });

    // return end.apply(this, arguments);
  };
}

module.exports = serializer;<commit_msg>Add params validations<commit_after>var normalize = require('normalize-object');
var validTypes = ['upper', 'lower', 'snake', 'pascal', 'camel', 'kebab', 'constant', 'title', 'capital', 'sentence'];

/**
 * Wrapps Superagent and returns a serialized response
 * @param  {Object} superagent
 * @param  {String} type
 * @return {void}
 */
function serializer(superagent, type) {
  if (arguments.length < 2) {
    throw new Error("superagent-serializer: expects 2 params");
  }
  if (validTypes.indexOf(type) === -1) {
    throw new Error("superagent-serializer: the passed type don't exist");
  }

  var Request = superagent.Request;
  var end = Request.prototype.end;

  Request.prototype.end = function(cb) {
    return end.call(this, function(err, res) {
      if (typeof cb !== 'function') return;

      var serializedRes;

      try {
        serializedRes = JSON.parse(res.text);
        serializedRes = normalize(serializedRes, type);
      } catch (e) {
        serializedRes = res.text;
      }

      cb(err, serializedRes);
    });
  };
}

module.exports = serializer;<|endoftext|>


<commit_before>#!/usr/bin/env node

var AWS = require('aws-sdk');
var rc = require('rc');
var config = rc('ec2-instance-lister');
var searchString;

if (config.s) {
	searchString = config.s;
} else {
	searchString = config.searchString;
}

var ec2params = {
	Filters: [{
		Name: 'instance-state-code',
		Values: [
			'16'
		]
	}]
};

var credentials = config.aws

if (config.account) {
	if (config[config.account]) {
		credentials = config[config.account]
	} else {
		return console.error('you specified an account %s, but the config did not include actual credential data, try adding config.[account name] = { ... credentials here ...}', config.account)
	}
}

var ipField = config.ipType === 'private' ? 'PrivateIpAddress' : 'PublicIpAddress'

var ec2 = new AWS.EC2(credentials);
ec2.describeInstances(ec2params, onResponse);

function onResponse(err, data) {
	if (err) {
		console.error(err);
		return;
	}

	var res = data.Reservations;
	if (res === undefined) {
		console.error('No instances found!');
		return;
	}

	var result = [];

	for (var i = 0; i < res.length; i++) {
		var group = res[i].Instances;
		if (group !== undefined) {
			for (var j = 0; j < group.length; j++) {
				var instance = group[j];
				var tags = instance.Tags;
				for (var k = 0; k < tags.length; k++) {
					if ((tags[k].Key === 'Name') && (tags[k].Value.indexOf(searchString) > -1)) {
						var ip = instance[ipField]
						if (ip) {
							console.log(ip);
						}
					}
				}
			}
		}
	}
}
<commit_msg>support search by any tag using -t "k=v", tag names are case insensitive<commit_after>#!/usr/bin/env node

var AWS = require('aws-sdk');
var rc = require('rc');
var config = rc('ec2-instance-lister');
var tagName = 'name';
var tagValue;

if (config.s) {
	tagValue = config.s;
} else if (config.tag || config.t) {
	config.tag = config.tag || config.t
	var split = config.tag.split('=')

	if (split.length !== 2) {
		throw new Error('invalid tag expression, must be key=value. Input was ' + config.tag)
	}

	tagName = split[0].toLowerCase()
	tagValue = split[1]
} else {
	tagValue = config.searchString;
}

var ec2params = {
	Filters: [{
		Name: 'instance-state-code',
		Values: [
			'16'
		]
	}]
};

var credentials = config.aws

if (config.account) {
	if (config[config.account]) {
		credentials = config[config.account]
	} else {
		return console.error('you specified an account %s, but the config did not include actual credential data, try adding config.[account name] = { ... credentials here ...}', config.account)
	}
}

var ipField = config.ipType === 'private' ? 'PrivateIpAddress' : 'PublicIpAddress'

var ec2 = new AWS.EC2(credentials);
ec2.describeInstances(ec2params, onResponse);

function onResponse(err, data) {
	if (err) {
		console.error(err);
		return;
	}

	var res = data.Reservations;
	if (res === undefined) {
		console.error('No instances found!');
		return;
	}

	var result = [];

	console.error('NOTE: only ips are written to stdout, the rest is written to stderr.')

	for (var i = 0; i < res.length; i++) {
		var group = res[i].Instances;
		if (group !== undefined) {
			for (var j = 0; j < group.length; j++) {
				var instance = group[j];
				var tags = instance.Tags;
				for (var k = 0; k < tags.length; k++) {
					if ((tags[k].Key.toLowerCase() === tagName) && (tags[k].Value.indexOf(tagValue) > -1)) {
						var ip = instance[ipField]
						if (ip) {
							console.error('instance id [%s]', instance.InstanceId)
							console.log(ip);
						}
					}
				}
			}
		}
	}
}
<|endoftext|>


<commit_before>var app = require('express')();
var bodyParser = require('body-parser');

app.set('port', (process.env.PORT || 5000));

// for parsing application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }));

var request = function(req, res) {
	console.log(req.body.text);
  res.send('{ "text": ' + JSON.stringify(req.body) + ' }');
};

app.get('/', request);
app.post('/', request);

app.listen(app.get('port'), function() {
  console.log("Node app is running on port:" + app.get('port'))
});
<commit_msg>improving<commit_after>var app = require('express')();
var bodyParser = require('body-parser');

app.set('port', (process.env.PORT || 5000));

// for parsing application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }));

var request = function(req, res) {
	console.log(req.body.text);
  res.send('{ "text": ' + req.body.text + ' }');
};

app.get('/', request);
app.post('/', request);

app.listen(app.get('port'), function() {
  console.log("Node app is running on port:" + app.get('port'))
});
<|endoftext|>


<commit_before>import Messenger from "./src/lib/messenger";

const telegram = new Messenger();

telegram.listen();
<commit_msg>testing<commit_after>import Messenger from "./dist/lib/messenger";

const telegram = new Messenger();

telegram.listen();
<|endoftext|>


<commit_before>var stringsAndFlowComments = /(`(?:.|\s)*?`|'(?:.|\s)*?'|`(?:.|\s)*?`|"(?:.|\s)*?"|\/\*.*?(?::{1,2}|flow-include).*?(?:.|\s)*?\*\/)/;

function removeComments(code){
	return code.split(stringsAndFlowComments)
	.map( function(chunk){
		if(chunk.trim().search(/\/\*.*?(?::{1,2}|flow-include).*?(?:.|\s)*?\*\//) === 0){
			var include = /\/\*.*?(?::{2}|flow-include)(.*?(?:.|\s)*)\*\//;
			var inline  = /\/\*(.*?:.*?(?:.|\s)*)\*\//;
			var pattern = include.test(chunk) ? include : inline;

			var flowInside = pattern.exec(chunk);
			if(flowInside && flowInside.length >= 2 && flowInside[1].length > 0){
				return flowInside[1];
			}
		}
		return chunk;
	}).join('');
}

module.exports = removeComments;<commit_msg>Make the regexp a bit more efficient and correct<commit_after>var stringsAndFlowComments = /(`(?:[^`\\]|\\.)*?`|'(?:[^'\\]|\\.)*?'|"(?:[^"\\]|\\.)*?"|\/\*.*?(?::{1,2}|flow-include).*?[\s\S]*?\*\/)/;

function removeComments(code){
	return code.split(stringsAndFlowComments)
	.map( function(chunk){
		if(chunk.trim().search(/\/\*.*?(?::{1,2}|flow-include).*?[\s\S]*?\*\//) === 0){
			var include = /\/\*.*?(?::{2}|flow-include)(.*?[\s\S]*)\*\//;
			var inline  = /\/\*(.*?:.*?[\s\S]*)\*\//;
			var pattern = include.test(chunk) ? include : inline;

			var flowInside = pattern.exec(chunk);
			if(flowInside && flowInside.length >= 2 && flowInside[1].length > 0){
				return flowInside[1];
			}
		}
		return chunk;
	}).join('');
}

module.exports = removeComments;<|endoftext|>


<commit_before>module.exports = function (_Firebase) {
  Firebase = _Firebase
  return Node
}

var debug = require('debug')('fireflower')
var events = require('events')
var inherits = require('inherits')
var SimplePeer = require('simple-peer')
var Firebase = null

var CONNECTION_TIMEOUT = 2000

inherits(Node, events.EventEmitter)

function Node (url, opts) {
  if (!(this instanceof Node)) {
    return new Node(url, opts)
  }

  this.url = url
  this.opts = opts || {}
  this.root = this.opts.root
  this.state = 'disconnected'
  this.config = {}
  this.upstream = null
  this.downstream = {}

  // firebase refs
  this._ref = new Firebase(this.url)
  this._configRef = this._ref.child('configuration')
  this._requestsRef = this._ref.child('requests')

  // set a random id if one was not provided
  this.id = this.opts.id || this._requestsRef.push().key()

  // bind callbacks
  this._onconfig = this._onconfig.bind(this)
  this._doconnect = this._doconnect.bind(this)
  this._onrequest = this._onrequest.bind(this)
  this._onresponse = this._onresponse.bind(this)
  this._onmaskupdate = this._onmaskupdate.bind(this)

  events.EventEmitter.call(this)
}

Node.prototype.connect = function () {
  if (this.state !== 'disconnected') {
    throw new Error('invalid state for connect')
  }

  this._preventReconnect = false

  // change state -> requesting
  debug(this.id + ' requesting connection')
  this.state = 'requesting'
  this.emit('statechange')

  // watch config
  if (!this._watchingConfig) {
    this._configRef.on('value', this._onconfig)
    this._watchingConfig = true
  }

  // ensure required config info
  if (!this.config.K) {
    this.once('configure', this._doconnect)
    return this
  }

  this._doconnect()

  return this
}

Node.prototype.disconnect = function () {
  this.state = 'disconnected'
  this._preventReconnect = true
  this._watchingConfig = false

  // remove some listeners
  this.removeListener('configure', this._doconnect)
  this._configRef.off('value', this._onconfig)
  this._requestsRef.off('child_added', this._onrequest)

  // remove outstanding request / response listener
  if (this._requestRef) {
    this._requestRef.remove()
    this._responsesRef.off('child_added', this._onresponse)
  }

  // destroy upstream connection
  if (this.upstream) {
    this.upstream.destroy()
    this.upstream = null
  }

  // destroy downstream connections
  for (var i in this.downstream) {
    this.downstream[i].destroy()
  }
  this.downstream = {}

  return this
}

// private api below

Node.prototype._onconfig = function (snapshot) {
  var data = snapshot.val()

  if (!data) {
    this.emit('error', new Error('missing configuration'))
    return
  }

  if (!data.K || isNaN(data.K)) {
    this.emit('error', new Error('configuration did not supply valid value for K'))
    return
  }

  this.config = data
  debug(this.id + ' updated configuration')
  this.emit('configure')
}

Node.prototype._doconnect = function () {
  var self = this

  if (this.root) {

    // emit connect but in nextTick
    setTimeout(function () {
      // change state -> connected
      debug(self.id + ' connected as root')
      self.state = 'connected'
      self.emit('statechange')

      // emit connect
      self.emit('connect')

      // start responding to requests
      self._requestsRef.on('child_added', self._onrequest)
    })

    return
  }

  // we are not root so publish a connection request
  this._dorequest()
}

Node.prototype._dorequest = function () {
  var self = this

  this._requestRef = this._requestsRef.push({
    id: this.id,
    removal_flag: {
      removed: false
    }
  })

  // make sure no one removes our request until we're connected
  this._requestRef.child('removal_flag').once('child_removed', function () {
    if (self.state === 'requesting') {
      self._responsesRef.off('child_added', self._onresponse)
      self._dorequest()
    }
  })

  // listen for a response
  this._responsesRef = this._requestRef.child('responses')
  this._responsesRef.once('child_added', this._onresponse)
}

Node.prototype._onrequest = function (snapshot) {
  if (this.state !== 'connected') {
    return // can't respond to requests unless we are connected
  }

  if (Object.keys(this.downstream).length >= this.config.K) {
    return // can't respond to requests if we've hit K peers
  }

  var self = this
  var requestRef = snapshot.ref()
  var requestId = snapshot.key()
  var request = snapshot.val()
  var peerId = request.id

  // responders may accidentally recreate requests
  // these won't have an id though and can be removed
  if (!peerId) {
    requestRef.remove()
    return
  }

  // prevent circles
  if (peerId === this._mask) {
    return
  }

  // since we review requests after every connect / disconnect
  // it is possible to see a peer we know about
  var knownPeer = this.downstream[peerId]
  if (knownPeer) {
    if (knownPeer.requestId !== requestId) {
      // if request ids don't match, the peer must have disconnected without us noticing
      knownPeer.destroy()
    } else {
      return
    }
  }

  debug(this.id + ' saw request by ' + peerId)

  var responseRef = requestRef.child('responses/' + this.id)

  // initiate peer connection
  // we have to do this before actually writing our response because
  // firebase can trigger events in the same tick which could circumvent
  // the K check at the top of this method
  this._connectToPeer(true, peerId, requestId, responseRef)

  // publish response
  responseRef.update({
    id: this.id
  })

  // watch for request withdrawal
  responseRef.once('child_removed', function () {
    var peer = self.downstream[peerId]
    if (peer && !peer.didConnect) {
      peer.requestWithdrawn = true
      peer.destroy()
    }
  })
}

Node.prototype._onresponse = function (snapshot) {
  if (this.state !== 'requesting') {
    return
  }

  var responseRef = snapshot.ref()
  var response = snapshot.val()
  var peerId = response.id

  if (!peerId) {
    return
  }

  // change state -> connecting (this prevents accepting multiple responses)
  debug(this.id + ' got response from ' + peerId)
  this.state = 'connecting'
  this.emit('statechange')

  // stop watching for request removal
  this._requestRef.child('removal_flag').off()

  // attempt a connection
  this._connectToPeer(false, peerId, null, responseRef)
}

Node.prototype._connectToPeer = function (initiator, peerId, requestId, responseRef) {
  var self = this
  var localSignals = responseRef.child(initiator ? 'responderSignals' : 'requesterSignals')
  var remoteSignals = responseRef.child(initiator ? 'requesterSignals' : 'responderSignals')

  var peer = new SimplePeer({
    initiator: initiator
  })

  peer.id = peerId

  if (initiator) {
    this.downstream[peer.id] = peer
    peer.notifications = peer._pc.createDataChannel('notifications')
    peer.requestId = requestId
  } else {
    var oldondatachannel = peer._pc.ondatachannel
    peer._pc.ondatachannel = function (evt) {
      if (evt.channel.label === 'notifications') {
        peer.notifications = evt.channel
        peer.notifications.onmessage = self._onmaskupdate
      } else {
        oldondatachannel(evt)
      }
    }
  }

  peer.on('connect', this._onpeerConnect.bind(this, peer, remoteSignals))
  peer.on('close', this._onpeerDisconnect.bind(this, peer, remoteSignals))

  peer.on('error', function (err) {
    debug(this.id + ' saw peer connection error', err)
  })

  peer.on('signal', function (signal) {
    if (initiator && self.state !== 'connected') return
    signal = JSON.parse(JSON.stringify(signal))
    localSignals.push(signal)
  })

  remoteSignals.on('child_added', function (snapshot) {
    if (initiator && self.state !== 'connected') return
    var signal = snapshot.val()
    peer.signal(signal)
  })

  // timeout connections
  setTimeout(function () {
    if (!peer.didConnect) {
      peer.destroy()
    }
  }, CONNECTION_TIMEOUT)
}

Node.prototype._onpeerConnect = function (peer, remoteSignals) {
  peer.didConnect = true
  peer.removeAllListeners('connect')
  peer.removeAllListeners('signal')
  remoteSignals.off()

  peer._channel.maxPacketLifeTime = this.opts.maxPacketLifeTime || null
  peer._channel.maxRetransmits = this.opts.maxRetransmits || null
  peer._channel.ordered = this.opts.ordered === false ? false : true

  if (this.downstream[peer.id]) {
    this._ondownstreamConnect(peer)
  } else {
    this._onupstreamConnect(peer)
  }
}

Node.prototype._onpeerDisconnect = function (peer, remoteSignals) {
  peer.removeAllListeners()
  remoteSignals.off()

  if (this.downstream[peer.id]) {
    this._ondownstreamDisconnect(peer)
  } else {
    this._onupstreamDisconnect(peer)
  }
}

Node.prototype._onupstreamConnect = function (peer) {
  // remove our request
  this._requestRef.remove()

  // already got connected by someone else
  if (this.state === 'connected') {
    debug(this.id + ' rejected upstream connection by ' + peer.id)
    peer.destroy()
    return
  }

  this.upstream = peer

  // change state -> connected
  debug(this.id + ' established upstream connection to ' + peer.id)
  this.state = 'connected'
  this.emit('statechange')
  this.emit('connect', peer)

  // begin responding to requests
  this._reviewRequests()
}

Node.prototype._onupstreamDisconnect = function (peer) {
  // stop responding to new requests
  this._requestsRef.off('child_added', this._onrequest)

  // remove request
  this._requestRef.remove()

  this.upstream = null

  // change state -> disconnected
  if (this.state !== 'disconnected') {
    debug(this.id + ' lost upstream connection to ' + peer.id)
  }

  this.state = 'disconnected'
  this.emit('statechange')

  // emit disconnect if we were connected
  if (peer.didConnect) {
    this.emit('disconnect', peer)
  }

  // attempt to reconnect if we were not disconnected intentionally
  if (!this._preventReconnect) {

    // mask off our descendants
    this._onmaskupdate({ data: this.id })

    // give our mask update a tiny head start
    var self = this
    setTimeout(function () {
      if (!self._preventReconnect) {
        self.connect()
      }
    }, 100)
  }
}

Node.prototype._ondownstreamConnect = function (peer) {
  // emit peerconnect
  debug(this.id + ' established downstream connection to ' + peer.id)
  this.emit('peerconnect', peer)

  // stop responding to requests if peers > K
  if (Object.keys(this.downstream).length >= this.config.K) {
    this._requestsRef.off('child_added', this._onrequest)
  }
}

Node.prototype._ondownstreamDisconnect = function (peer) {
  // remove from lookup
  delete this.downstream[peer.id]

  // emit events and potentially remove stale requests
  if (peer.didConnect) {
    if (this.state !== 'disconnected') {
      debug(this.id + ' lost downstream connection to ' + peer.id)
    }

    this.emit('peerdisconnect', peer)
  } else {
    if (peer.requestWithdrawn) {
      debug(this.id + ' saw request withdrawn by ' + peer.id)
    } else {
      debug(this.id + ' removing stale request by ' + peer.id)
      this._requestsRef.child(peer.requestId).remove()
    }
  }

  this._reviewRequests()
}

Node.prototype._onmaskupdate = function (evt) {
  this._mask = evt.data

  debug(this.id + ' set mask to ' + this._mask)

  // oops we made a circle, fix that
  if (this.downstream[this._mask]) {
    debug(this.id + ' destroying accidental circle back to ' + this._mask)
    this.downstream[this._mask].destroy()
  }

  for (var i in this.downstream) {
    try {
      this.downstream[i].notifications.send(this._mask)
    } catch (err) {
      // this would only happen if the peer was in
      // the process of closing so we don't care
    }
  }
}

Node.prototype._reviewRequests = function () {
  if (this.state === 'connected' && Object.keys(this.downstream).length < this.config.K) {
    this._requestsRef.off('child_added', this._onrequest)
    this._requestsRef.on('child_added', this._onrequest)
  }
}
<commit_msg>add opt-in reporting<commit_after>module.exports = function (_Firebase) {
  Firebase = _Firebase
  return Node
}

var debug = require('debug')('fireflower')
var events = require('events')
var inherits = require('inherits')
var SimplePeer = require('simple-peer')
var Firebase = null

var CONNECTION_TIMEOUT = 2000

inherits(Node, events.EventEmitter)

function Node (url, opts) {
  if (!(this instanceof Node)) {
    return new Node(url, opts)
  }

  this.url = url
  this.opts = opts || {}
  this.root = this.opts.root
  this.reportInterval = this.opts.reportInterval
  this.state = 'disconnected'
  this.config = {}
  this.upstream = null
  this.downstream = {}

  // firebase refs
  this._ref = new Firebase(this.url)
  this._configRef = this._ref.child('configuration')
  this._requestsRef = this._ref.child('requests')
  this._reports = this._ref.child('reports')

  // set a random id if one was not provided
  this.id = this.opts.id || this._requestsRef.push().key()

  // bind callbacks
  this._onconfig = this._onconfig.bind(this)
  this._doconnect = this._doconnect.bind(this)
  this._onrequest = this._onrequest.bind(this)
  this._onresponse = this._onresponse.bind(this)
  this._onmaskupdate = this._onmaskupdate.bind(this)
  this._onreportNeeded = this._onreportNeeded.bind(this)

  events.EventEmitter.call(this)
}

Node.prototype.connect = function () {
  if (this.state !== 'disconnected') {
    throw new Error('invalid state for connect')
  }

  this._preventReconnect = false

  // reporting?
  if (this.reportInterval && !this._reportInterval) {
    this._reportInterval = setInterval(this._onreportNeeded, this.reportInterval)
    this._onreportNeeded()
  }

  // change state -> requesting
  debug(this.id + ' requesting connection')
  this.state = 'requesting'
  this.emit('statechange')

  // watch config
  if (!this._watchingConfig) {
    this._configRef.on('value', this._onconfig)
    this._watchingConfig = true
  }

  // ensure required config info
  if (!this.config.K) {
    this.once('configure', this._doconnect)
    return this
  }

  this._doconnect()

  return this
}

Node.prototype.disconnect = function () {
  this.state = 'disconnected'
  this._preventReconnect = true
  this._watchingConfig = false

  // remove some listeners
  this.removeListener('configure', this._doconnect)
  this._configRef.off('value', this._onconfig)
  this._requestsRef.off('child_added', this._onrequest)

  // stop reporting
  clearInterval(this._reportInterval)
  delete this._reportInterval

  // remove outstanding request / response listener
  if (this._requestRef) {
    this._requestRef.remove()
    this._responsesRef.off('child_added', this._onresponse)
  }

  // destroy upstream connection
  if (this.upstream) {
    this.upstream.destroy()
    this.upstream = null
  }

  // destroy downstream connections
  for (var i in this.downstream) {
    this.downstream[i].destroy()
  }
  this.downstream = {}

  return this
}

// private api below

Node.prototype._onconfig = function (snapshot) {
  var data = snapshot.val()

  if (!data) {
    this.emit('error', new Error('missing configuration'))
    return
  }

  if (!data.K || isNaN(data.K)) {
    this.emit('error', new Error('configuration did not supply valid value for K'))
    return
  }

  this.config = data
  debug(this.id + ' updated configuration')
  this.emit('configure')
}

Node.prototype._doconnect = function () {
  var self = this

  if (this.root) {

    // emit connect but in nextTick
    setTimeout(function () {
      // change state -> connected
      debug(self.id + ' connected as root')
      self.state = 'connected'
      self.emit('statechange')

      // emit connect
      self.emit('connect')

      // start responding to requests
      self._requestsRef.on('child_added', self._onrequest)
    })

    return
  }

  // we are not root so publish a connection request
  this._dorequest()
}

Node.prototype._dorequest = function () {
  var self = this

  this._requestRef = this._requestsRef.push({
    id: this.id,
    removal_flag: {
      removed: false
    }
  })

  // make sure no one removes our request until we're connected
  this._requestRef.child('removal_flag').once('child_removed', function () {
    if (self.state === 'requesting') {
      self._responsesRef.off('child_added', self._onresponse)
      self._dorequest()
    }
  })

  // listen for a response
  this._responsesRef = this._requestRef.child('responses')
  this._responsesRef.once('child_added', this._onresponse)
}

Node.prototype._onrequest = function (snapshot) {
  if (this.state !== 'connected') {
    return // can't respond to requests unless we are connected
  }

  if (Object.keys(this.downstream).length >= this.config.K) {
    return // can't respond to requests if we've hit K peers
  }

  var self = this
  var requestRef = snapshot.ref()
  var requestId = snapshot.key()
  var request = snapshot.val()
  var peerId = request.id

  // responders may accidentally recreate requests
  // these won't have an id though and can be removed
  if (!peerId) {
    requestRef.remove()
    return
  }

  // prevent circles
  if (peerId === this._mask) {
    return
  }

  // since we review requests after every connect / disconnect
  // it is possible to see a peer we know about
  var knownPeer = this.downstream[peerId]
  if (knownPeer) {
    if (knownPeer.requestId !== requestId) {
      // if request ids don't match, the peer must have disconnected without us noticing
      knownPeer.destroy()
    } else {
      return
    }
  }

  debug(this.id + ' saw request by ' + peerId)

  var responseRef = requestRef.child('responses/' + this.id)

  // initiate peer connection
  // we have to do this before actually writing our response because
  // firebase can trigger events in the same tick which could circumvent
  // the K check at the top of this method
  this._connectToPeer(true, peerId, requestId, responseRef)

  // publish response
  responseRef.update({
    id: this.id
  })

  // watch for request withdrawal
  responseRef.once('child_removed', function () {
    var peer = self.downstream[peerId]
    if (peer && !peer.didConnect) {
      peer.requestWithdrawn = true
      peer.destroy()
    }
  })
}

Node.prototype._onresponse = function (snapshot) {
  if (this.state !== 'requesting') {
    return
  }

  var responseRef = snapshot.ref()
  var response = snapshot.val()
  var peerId = response.id

  if (!peerId) {
    return
  }

  // change state -> connecting (this prevents accepting multiple responses)
  debug(this.id + ' got response from ' + peerId)
  this.state = 'connecting'
  this.emit('statechange')

  // stop watching for request removal
  this._requestRef.child('removal_flag').off()

  // attempt a connection
  this._connectToPeer(false, peerId, null, responseRef)
}

Node.prototype._connectToPeer = function (initiator, peerId, requestId, responseRef) {
  var self = this
  var localSignals = responseRef.child(initiator ? 'responderSignals' : 'requesterSignals')
  var remoteSignals = responseRef.child(initiator ? 'requesterSignals' : 'responderSignals')

  var peer = new SimplePeer({
    initiator: initiator
  })

  peer.id = peerId

  if (initiator) {
    this.downstream[peer.id] = peer
    peer.notifications = peer._pc.createDataChannel('notifications')
    peer.requestId = requestId
  } else {
    var oldondatachannel = peer._pc.ondatachannel
    peer._pc.ondatachannel = function (evt) {
      if (evt.channel.label === 'notifications') {
        peer.notifications = evt.channel
        peer.notifications.onmessage = self._onmaskupdate
      } else {
        oldondatachannel(evt)
      }
    }
  }

  peer.on('connect', this._onpeerConnect.bind(this, peer, remoteSignals))
  peer.on('close', this._onpeerDisconnect.bind(this, peer, remoteSignals))

  peer.on('error', function (err) {
    debug(this.id + ' saw peer connection error', err)
  })

  peer.on('signal', function (signal) {
    if (initiator && self.state !== 'connected') return
    signal = JSON.parse(JSON.stringify(signal))
    localSignals.push(signal)
  })

  remoteSignals.on('child_added', function (snapshot) {
    if (initiator && self.state !== 'connected') return
    var signal = snapshot.val()
    peer.signal(signal)
  })

  // timeout connections
  setTimeout(function () {
    if (!peer.didConnect) {
      peer.destroy()
    }
  }, CONNECTION_TIMEOUT)
}

Node.prototype._onpeerConnect = function (peer, remoteSignals) {
  peer.didConnect = true
  peer.removeAllListeners('connect')
  peer.removeAllListeners('signal')
  remoteSignals.off()

  peer._channel.maxPacketLifeTime = this.opts.maxPacketLifeTime || null
  peer._channel.maxRetransmits = this.opts.maxRetransmits || null
  peer._channel.ordered = this.opts.ordered === false ? false : true

  if (this.downstream[peer.id]) {
    this._ondownstreamConnect(peer)
  } else {
    this._onupstreamConnect(peer)
  }
}

Node.prototype._onpeerDisconnect = function (peer, remoteSignals) {
  peer.removeAllListeners()
  remoteSignals.off()

  if (this.downstream[peer.id]) {
    this._ondownstreamDisconnect(peer)
  } else {
    this._onupstreamDisconnect(peer)
  }
}

Node.prototype._onupstreamConnect = function (peer) {
  // remove our request
  this._requestRef.remove()

  // already got connected by someone else
  if (this.state === 'connected') {
    debug(this.id + ' rejected upstream connection by ' + peer.id)
    peer.destroy()
    return
  }

  this.upstream = peer

  // change state -> connected
  debug(this.id + ' established upstream connection to ' + peer.id)
  this.state = 'connected'
  this.emit('statechange')
  this.emit('connect', peer)

  // begin responding to requests
  this._reviewRequests()
}

Node.prototype._onupstreamDisconnect = function (peer) {
  // stop responding to new requests
  this._requestsRef.off('child_added', this._onrequest)

  // remove request
  this._requestRef.remove()

  this.upstream = null

  // change state -> disconnected
  if (this.state !== 'disconnected') {
    debug(this.id + ' lost upstream connection to ' + peer.id)
  }

  this.state = 'disconnected'
  this.emit('statechange')

  // emit disconnect if we were connected
  if (peer.didConnect) {
    this.emit('disconnect', peer)
  }

  // attempt to reconnect if we were not disconnected intentionally
  if (!this._preventReconnect) {

    // mask off our descendants
    this._onmaskupdate({ data: this.id })

    // give our mask update a tiny head start
    var self = this
    setTimeout(function () {
      if (!self._preventReconnect) {
        self.connect()
      }
    }, 100)
  }
}

Node.prototype._ondownstreamConnect = function (peer) {
  // emit peerconnect
  debug(this.id + ' established downstream connection to ' + peer.id)
  this.emit('peerconnect', peer)

  // stop responding to requests if peers > K
  if (Object.keys(this.downstream).length >= this.config.K) {
    this._requestsRef.off('child_added', this._onrequest)
  }
}

Node.prototype._ondownstreamDisconnect = function (peer) {
  // remove from lookup
  delete this.downstream[peer.id]

  // emit events and potentially remove stale requests
  if (peer.didConnect) {
    if (this.state !== 'disconnected') {
      debug(this.id + ' lost downstream connection to ' + peer.id)
    }

    this.emit('peerdisconnect', peer)
  } else {
    if (peer.requestWithdrawn) {
      debug(this.id + ' saw request withdrawn by ' + peer.id)
    } else {
      debug(this.id + ' removing stale request by ' + peer.id)
      this._requestsRef.child(peer.requestId).remove()
    }
  }

  this._reviewRequests()
}

Node.prototype._onmaskupdate = function (evt) {
  this._mask = evt.data

  debug(this.id + ' set mask to ' + this._mask)

  // oops we made a circle, fix that
  if (this.downstream[this._mask]) {
    debug(this.id + ' destroying accidental circle back to ' + this._mask)
    this.downstream[this._mask].destroy()
  }

  for (var i in this.downstream) {
    try {
      this.downstream[i].notifications.send(this._mask)
    } catch (err) {
      // this would only happen if the peer was in
      // the process of closing so we don't care
    }
  }
}

Node.prototype._onreportNeeded = function () {
  debug(this.id + ' reporting')

  var report = {
    state: this.state,
    upstream: this.upstream ? this.upstream.id : null,
    timestamp: Date.now()
  }

  this._reports
    .child(this.id)
    .update(report)
}

Node.prototype._reviewRequests = function () {
  if (this.state === 'connected' && Object.keys(this.downstream).length < this.config.K) {
    this._requestsRef.off('child_added', this._onrequest)
    this._requestsRef.on('child_added', this._onrequest)
  }
}
<|endoftext|>


<commit_before>"use strict";

var https = require( "https" );
var bower = require( "bower" );
var mime = require( "mime" );

// Express and middlewares
var express = require( "express" );
var compression = require( "compression" );

// -------------------------------------------------------------------------------------------------

var app = express();

// Set the default mime type to an object, so we know that it didn't found anything that could
// conflict with a valid mimetype.
mime.default_type = {};

app.use( compression({
    threshold: 1024
}));

app.route( "/:package/:version/*" ).get(function( req, res ) {
    var command = bower.commands.lookup( req.params.package );

    command.on( "end", function( pkg ) {
        var slug, url;

        if ( !pkg ) {
            return res.send( 404, "Not Found" );
        }

        slug = getSlug( pkg.url );
        url = getGithubUrl( slug );
        url += req.params.version + "/";
        url += req.params[ 0 ];

        https.get( url, function( ghResp ) {
            var type = findMimetype( url, ghResp );

            res.statusCode = ghResp.statusCode;
            res.set( "Content-Type", type );
            res.set( "X-Expanded-Url", url );

            ghResp.pipe( res );
        });
    });
});

app.listen( process.env.PORT || 3000, function() {
    console.log( "Listening on port " + this.address().port );
});

// -------------------------------------------------------------------------------------------------

function getSlug( url ) {
    url = url.replace( "git://github.com/", "" );
    url = url.replace( /\.git$/, "" );

    return url;
}

function getGithubUrl( slug ) {
    return "https://raw.githubusercontent.com/" + slug + "/";
}

function findMimetype( url, ghResp ) {
    var type = mime.lookup( url );

    // If the defaule mime type was used, this means we should rely on GitHub and return their
    // content-type (which is usually plain text or octet-stream).
    // Otherwise, we simply use the mime module returned value.
    return type === mime.default_type ? ghResp.headers[ "content-type" ] : type;
}<commit_msg>refactor(server): better resolve and respond<commit_after>"use strict";

// Constants
var STATUS_CODES = require( "http" ).STATUS_CODES;
var EXPANDED_URL_HEADER = "X-Expanded-Url";

// Modules
var https = require( "https" );
var bower = require( "bower" );
var mime = require( "mime" );

// Express and middlewares
var express = require( "express" );
var compression = require( "compression" );

// -------------------------------------------------------------------------------------------------

var app = express();

// Set the default mime type to an object, so we know that it didn't found anything that could
// conflict with a valid mimetype.
mime.default_type = {};

app.use( compression({
    threshold: 1024
}));

app.route( "/:package/:version/*" ).get(function( req, res ) {
    var command = bower.commands.lookup( req.params.package );

    command.on( "end", function( pkg ) {
        var url;
        var slug = pkg ? getSlug( pkg.url ) : null;

        if ( !pkg || !slug ) {
            return send( 404 );
        }

        url = getGithubUrl( slug );
        url += req.params.version + "/";
        url += req.params[ 0 ];

        https.get( url, function( ghResp ) {
            var type = findMimetype( url, ghResp );
            var status = ghResp.statusCode;

            if ( status >= 400 ) {
                return send( status, url );
            }

            res.statusCode = status;
            res.set( "Content-Type", type );
            res.set( EXPANDED_URL_HEADER, url );

            ghResp.pipe( res );
        });
    });

    function send( status, url ) {
        res.set( "Content-Type", "text/plain" );
        if ( url ) {
            res.set( EXPANDED_URL_HEADER, url );
        }

        return res.send( status, STATUS_CODES[ status ] );
    }
});

app.listen( process.env.PORT || 3000, function() {
    console.log( "Listening on port " + this.address().port );
});

// -------------------------------------------------------------------------------------------------

function getSlug( url ) {
    // Regexp taken from
    // https://github.com/bower/bower/blob/337c0f2d0adc4a04a8c282f8fa2eef85b48616a4/lib/core/resolvers/GitHubResolver.js#L114
    var match = url.match( /(?:@|:\/\/)github.com[:\/]([^\/\s]+?)\/([^\/\s]+?)(?:\.git)?\/?$/i );
    if ( !match ) {
        return;
    }

    return match[ 1 ] + "/" + match[ 2 ];
}

function getGithubUrl( slug ) {
    return "https://raw.githubusercontent.com/" + slug + "/";
}

function findMimetype( url, ghResp ) {
    var type = mime.lookup( url );

    // If the defaule mime type was used, this means we should rely on GitHub and return their
    // content-type (which is usually plain text or octet-stream).
    // Otherwise, we simply use the mime module returned value.
    return type === mime.default_type ? ghResp.headers[ "content-type" ] : type;
}<|endoftext|>


<commit_before>function isEnabled(mod, options) {
	if(!options.enabled && !options.disabled) return true;
	else if(options.disabled && !~options.disabled.indexOf(mod)) return true;
	else if(options.enabled && ~options.enabled.indexOf(mod)) return true;
	else return false;
}

let loadedAdditions = [];
function addAddition(addition, Eris, options = {}) {
	if(!isEnabled(addition, options)) return;

	let mod = require(`./lib/${addition.replace(".", "/")}`);
	if(!~loadedAdditions.indexOf(addition)) (mod(Eris), loadedAdditions.push(addition));
	if(mod.deps) mod.deps.forEach(dep => addAddition(`${dep}.js`, Eris));
}

const fs = require("fs");
const libdir = require("path").resolve(__dirname, "lib");
module.exports = (Eris, options = {}) => {
	let structs = fs.readdirSync(libdir);
	structs.forEach(struct => {
		let additions = fs.readdirSync(`${libdir}/${struct}/`);
		additions.forEach(addition => addAddition(`${struct}.${addition}`, Eris, options));
	});

	return Eris;
};
<commit_msg>Create index.js<commit_after>function isEnabled(mod, options) {
	if(!options.enabled && !options.disabled) return true;
	else if(options.disabled && !~options.disabled.indexOf(mod)) return true;
	else if(options.enabled && ~options.enabled.indexOf(mod)) return true;
	else return false;
}

let loadedAdditions = [];
function addAddition(addition, Eris, options = {}) {
	if(!isEnabled(addition, options)) return;

	let mod = require(`./lib/${addition.replace(".", "/")}`);
	if(!~loadedAdditions.indexOf(addition)) (mod(Eris), loadedAdditions.push(addition));
	if(mod.deps) mod.deps.forEach(dep => addAddition(dep, Eris));
}

const fs = require("fs");
const libdir = require("path").resolve(__dirname, "lib");
module.exports = (Eris, options = {}) => {
	let structs = fs.readdirSync(libdir);
	structs.forEach(struct => {
		let additions = fs.readdirSync(`${libdir}/${struct}/`);
		additions = additions.map(script => script.substring(0, script.length - 3));
		additions.forEach(addition => addAddition(`${struct}.${addition}`, Eris, options));
	});

	return Eris;
};
<|endoftext|>


<commit_before>'use strict'

const express = require('express')
const bodyParser = require('body-parser')
const request = require('request')
const async = require('async')
const app = express()
const token = process.env.PAGE_ACCESS_TOKEN

app.set('port', (process.env.PORT || 5000))

// Spin up the server
app.listen(app.get('port'), function() {
	console.log('running on port', app.get('port'))
})

// Process application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({
	extended: false
}))

// Process application/json
app.use(bodyParser.json())

// Index route
app.get('/', function(req, res) {
	res.send('App Online!')
})

// for Facebook verification
app.get('/webhook/', function(req, res) {
	if (req.query['hub.mode'] && req.query['hub.verify_token'] === process.env.VERIFY_TOKEN) {
		res.status(200).send(req.query['hub.challenge'])
	} else {
		res.send('Error, wrong token')
	}
})

app.post('/webhook/', function(req, res) {
	let messaging_events = req.body.entry[0].messaging

	for (let i = 0; i < messaging_events.length; i++) {
		let event = req.body.entry[0].messaging[i]
		let sender = event.sender.id
 		if (event.message && event.message.text) {
			let text = event.message.text
			messageHandler(sender, text)
		}
	}
	res.sendStatus(200)
})

function messageHandler(sender, text){
	//if the message does not call out the chat bot, it is not a command
	if(text.indexOf('@Chess-bot') == -1 && text.indexOf('@chess') == -1){
		return null
	}
	//array of split terms from the command
	let textSplit = text.toLowerCase().split(" ")

	switch(textSplit[1]){
		case "hey":
			sendTextMessage(sender, "Hey!")
			break
		case "challenge":
			break
		case "move":
			break
		case "resign":
			break
		case "draw":
			break
		case "accept":
			break
		case "help":
			sendHelp(sender)
			break
		default:
			async.series([sendTextMessage(sender, "That's not a command"),
				sendHelp(sender)
			]);
			break
	}
}

function sendTextMessage(sender, text) {
	let messageData = {
		text: text
	}
	request({
		url: 'https://graph.facebook.com/v2.6/me/messages',
		qs: {
			access_token: token
		},
		method: 'POST',
		json: {
			recipient: {
				id: sender
			},
			message: messageData
		}
	}, function(error, response, body) {
		if (error) {
			console.log('Error sending messages: ', error)
		} else if (response.body.error) {
			console.log('Error: ', response.body.error)
		}
	})
}

function sendHelp(sender){
	sendTextMessage(sender, "HELP: I'M TRYING DAMNIT!")
}
<commit_msg>bscommit<commit_after>'use strict'

const express = require('express')
const bodyParser = require('body-parser')
const request = require('request')
const async = require('async')
const app = express()
const token = process.env.PAGE_ACCESS_TOKEN

app.set('port', (process.env.PORT || 5000))

// Spin up the server
app.listen(app.get('port'), function() {
	console.log('running on port', app.get('port'))
})

// Process application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({
	extended: false
}))

// Process application/json
app.use(bodyParser.json())

// Index route
app.get('/', function(req, res) {
	res.send('App Online!')
})

// for Facebook verification
app.get('/webhook/', function(req, res) {
	if (req.query['hub.mode'] && req.query['hub.verify_token'] === process.env.VERIFY_TOKEN) {
		res.status(200).send(req.query['hub.challenge'])
	} else {
		res.send('Error, wrong token')
	}
})

app.post('/webhook/', function(req, res) {
	let messaging_events = req.body.entry[0].messaging

	for (let i = 0; i < messaging_events.length; i++) {
		let event = req.body.entry[0].messaging[i]
		let sender = event.sender.id
 		if (event.message && event.message.text) {
			let text = event.message.text
			messageHandler(sender, text)
		}
	}
	res.sendStatus(200)
})

function messageHandler(sender, text){
	//if the message does not call out the chat bot, it is not a command
	if(text.indexOf('@Chess-bot') == -1 && text.indexOf('@chess') == -1){
		return null
	}
	//array of split terms from the command
	let textSplit = text.toLowerCase().split(" ")

	switch(textSplit[1]){
		case "hey":
			sendTextMessage(sender, "Hey!")
			break
		case "challenge":
			break
		case "move":
			break
		case "resign":
			break
		case "draw":
			break
		case "accept":
			break
		case "help":
			sendHelp(sender)
			break
		default:
			async.series([function(){sendTextMessage(sender, "That's not a command")},
				function(){sendHelp(sender)}
			]);
			break
	}
}

function sendTextMessage(sender, text) {
	let messageData = {
		text: text
	}
	request({
		url: 'https://graph.facebook.com/v2.6/me/messages',
		qs: {
			access_token: token
		},
		method: 'POST',
		json: {
			recipient: {
				id: sender
			},
			message: messageData
		}
	}, function(error, response, body) {
		if (error) {
			console.log('Error sending messages: ', error)
		} else if (response.body.error) {
			console.log('Error: ', response.body.error)
		}
	})
}

function sendHelp(sender){
	sendTextMessage(sender, "HELP: I'M TRYING DAMNIT!")
}
<|endoftext|>


<commit_before>var App = require("./lib/app").App,
    Client = require("./lib/client").Client,
    Parser = require("./lib/parser").Parser;

exports.App = App;
exports.Client = Client;
exports.Parser = Parser;
<commit_msg>Remove app from index.js<commit_after>exports.Client = require("./lib/client").Client;
exports.Parser = require("./lib/parser").Parser;
<|endoftext|>


<commit_before>/**
 * RabbitMQ job subscribe & publish functions for Runnable
 * @module ./index
 */
'use strict';

require('loadenv')();

var EventEmitter = require('events').EventEmitter;
var amqplib = require('amqplib/callback_api');
var async = require('async');
var debug = require('debug')('hermes:index');
var hasKeypaths = require('101/has-keypaths');
var util = require('util');

// Temporarily hard coded
var queues = [
  'container-create'
];
var hermes;

/**
 * Hermes - Runnable job queue API
 * @class
 * @throws
 * @param {Object} opts
 * @return this
 */
function Hermes (opts) {
  var requiredOpts = ['hostname', 'port', 'username', 'password'];
  if (!hasKeypaths(opts, requiredOpts)) {
    throw new Error('Hermes missing required arguments. Supplied opts '+
                    Object.prototype.keys(opts).join(', ')+
                    '. Opts must include: '+
                    requiredOpts.join(', '));
  }
  var _this = this;
  this._channel = null;
  this.publishQueue = [];
  this.subscribeQueue = [];
  var connectionUrl = [
    'amqp://', opts.username, ':', opts.password,
    '@', opts.hostname];
  if (opts.port) {
    // optional port
    connectionUrl.push(':');
    connectionUrl.push(opts.port);
  }
  connectionUrl = connectionUrl.join('');
  debug('connectionUrl', connectionUrl);
  amqplib.connect(connectionUrl, function (err, conn) {
    if (err) { throw err; }
    debug('rabbitmq connected');
    conn.createChannel(function (err, ch) {
      if (err) { throw err; }
      debug('rabbitmq channel created');
      /**
       * Durable queue: https://www.rabbitmq.com/tutorials/tutorial-two-python.html
       * (Message Durability)
       */
      async.forEach(queues, function forEachQueue (queueName, cb) {
        ch.assertQueue(queueName, {durable: true}, cb);
      }, function done (err) {
        if (err) { throw err; }
        _this._channel = ch;
        _this.emit('ready');
      });
    });
  });
  this.on('ready', function () {
    debug('hermes ready');
    var args;
    while(args = _this.publishQueue.pop()) {
      publish.apply(_this, args);
    }
    while(args = _this.subscribeQueue.pop()) {
      subscribe.apply(_this, args);
    }
  });
  this.on('publish', function (queueName, data) {
    debug('hermes publish', queueName, data);
    if (_this._channel) {
      publish(queueName, data);
    }
    else {
      _this.publishQueue.push(Array.prototype.slice.call(arguments));
    }
  });
  this.on('subscribe', function (queueName, cb) {
    debug('hermes subscribe', queueName);
    if (_this._channel) {
      subscribe(queueName, cb);
    }
    else {
      _this.subscribeQueue.push(Array.prototype.slice.call(arguments));
    }
  });
  /**
   * @param {Object} data
   * @return null
   */
  function publish (queueName, data) {
    debug('channel.sendToQueue', queueName, data);
    _this._channel.sendToQueue(queueName, data);
  }
  /**
   * @param {Object} data
   * @return null
   */
  function subscribe (queueName, cb) {
    debug('channel.consume', queueName);
    _this._channel.consume(queueName, subscribeCallback(cb));
  }
  /**
   * @param {Function} cb
   * @return Function
   */
  function subscribeCallback (cb) {
    debug('subscribeCallback');
    return function (msg) {
      if (!msg) {
        debug('subscribeCallback invalid message', msg);
        return;
      }
      cb(JSON.parse(msg.content.toString()), function done () {
        debug('subscribeCallback done');
        _this._channel.ack(msg);
      });
    };
  }
  return this;
}

util.inherits(Hermes, EventEmitter);

/**
 * @throws
 * @param {String} queueName
 * @param {Object|String|Buffer} data
 * @return this
 */
Hermes.prototype.publish = function (queueName, data) {
  /*jshint maxcomplexity:6 */
  if (!~queues.indexOf(queueName)) {
    throw new Error('attempting to publish to invalid queue: '+queueName);
  }
  if (typeof data === 'string' || data instanceof String || data instanceof Buffer) {
    try {
      JSON.parse(data.toString());
    } catch (err) {
      throw new Error('data must be valid JSON');
    }
  }
  else {
    data = new Buffer(JSON.stringify(data));
  }
  this.emit('publish', queueName, data);
  return this;
};

/**
 * @throws
 * @param {String} queueName
 * @param {Function} cb
 * @return this
 */
Hermes.prototype.subscribe = function (queueName, cb) {
  if (!~queues.indexOf(queueName)) {
    throw new Error('attempting to subscribe to invalid queue: '+queueName);
  }
  if (cb.length !== 2) {
    throw new Error('queue listener callback must take a "done" callback function as a second'+
                    ' argument and invoke the function to send the ACK message to RabbitMQ'+
                    ' and remove the job from the queue.');
  }
  this.emit('subscribe', queueName, cb);
  return this;
};

/**
 * Factory method takes configuration once during applicaiton lifecycle and
 * returns instance of hermes
 */
module.exports.hermesSingletonFactory = function (opts) {
  hermes = (hermes) ? hermes : new Hermes(opts);
  return hermes;
};
<commit_msg>quick disable env flag for tests<commit_after>/**
 * RabbitMQ job subscribe & publish functions for Runnable
 * @module ./index
 */
'use strict';

require('loadenv')();

var EventEmitter = require('events').EventEmitter;
var amqplib = require('amqplib/callback_api');
var async = require('async');
var debug = require('debug')('hermes:index');
var hasKeypaths = require('101/has-keypaths');
var util = require('util');

// Temporarily hard coded
var queues = [
  'container-create'
];
var hermes;

/**
 * Hermes - Runnable job queue API
 * @class
 * @throws
 * @param {Object} opts
 * @return this
 */
function Hermes (opts) {
  var requiredOpts = ['hostname', 'port', 'username', 'password'];
  if (!hasKeypaths(opts, requiredOpts)) {
    throw new Error('Hermes missing required arguments. Supplied opts '+
                    Object.prototype.keys(opts).join(', ')+
                    '. Opts must include: '+
                    requiredOpts.join(', '));
  }
  var _this = this;
  this._channel = null;
  this.publishQueue = [];
  this.subscribeQueue = [];
  var connectionUrl = [
    'amqp://', opts.username, ':', opts.password,
    '@', opts.hostname];
  if (opts.port) {
    // optional port
    connectionUrl.push(':');
    connectionUrl.push(opts.port);
  }
  connectionUrl = connectionUrl.join('');
  debug('connectionUrl', connectionUrl);
  amqplib.connect(connectionUrl, function (err, conn) {
    if (err) { throw err; }
    debug('rabbitmq connected');
    conn.createChannel(function (err, ch) {
      if (err) { throw err; }
      debug('rabbitmq channel created');
      /**
       * Durable queue: https://www.rabbitmq.com/tutorials/tutorial-two-python.html
       * (Message Durability)
       */
      async.forEach(queues, function forEachQueue (queueName, cb) {
        ch.assertQueue(queueName, {durable: true}, cb);
      }, function done (err) {
        if (err) { throw err; }
        _this._channel = ch;
        _this.emit('ready');
      });
    });
  });
  this.on('ready', function () {
    debug('hermes ready');
    var args;
    while(args = _this.publishQueue.pop()) {
      publish.apply(_this, args);
    }
    while(args = _this.subscribeQueue.pop()) {
      subscribe.apply(_this, args);
    }
  });
  this.on('publish', function (queueName, data) {
    debug('hermes publish', queueName, data);
    if (_this._channel) {
      publish(queueName, data);
    }
    else {
      _this.publishQueue.push(Array.prototype.slice.call(arguments));
    }
  });
  this.on('subscribe', function (queueName, cb) {
    debug('hermes subscribe', queueName);
    if (_this._channel) {
      subscribe(queueName, cb);
    }
    else {
      _this.subscribeQueue.push(Array.prototype.slice.call(arguments));
    }
  });
  /**
   * @param {Object} data
   * @return null
   */
  function publish (queueName, data) {
    debug('channel.sendToQueue', queueName, data);
    _this._channel.sendToQueue(queueName, data);
  }
  /**
   * @param {Object} data
   * @return null
   */
  function subscribe (queueName, cb) {
    debug('channel.consume', queueName);
    _this._channel.consume(queueName, subscribeCallback(cb));
  }
  /**
   * @param {Function} cb
   * @return Function
   */
  function subscribeCallback (cb) {
    debug('subscribeCallback');
    return function (msg) {
      if (!msg) {
        debug('subscribeCallback invalid message', msg);
        return;
      }
      cb(JSON.parse(msg.content.toString()), function done () {
        debug('subscribeCallback done');
        _this._channel.ack(msg);
      });
    };
  }
  return this;
}

util.inherits(Hermes, EventEmitter);

/**
 * @throws
 * @param {String} queueName
 * @param {Object|String|Buffer} data
 * @return this
 */
Hermes.prototype.publish = function (queueName, data) {
  /*jshint maxcomplexity:7 */
  if (process.env.DISABLE_HERMES_PUBLISH) {
    debug('DISABLE_HERMES_PUBLISH', queueName, data);
    return this;
  }
  if (!~queues.indexOf(queueName)) {
    throw new Error('attempting to publish to invalid queue: '+queueName);
  }
  if (typeof data === 'string' || data instanceof String || data instanceof Buffer) {
    try {
      JSON.parse(data.toString());
    } catch (err) {
      throw new Error('data must be valid JSON');
    }
  }
  else {
    data = new Buffer(JSON.stringify(data));
  }
  this.emit('publish', queueName, data);
  return this;
};

/**
 * @throws
 * @param {String} queueName
 * @param {Function} cb
 * @return this
 */
Hermes.prototype.subscribe = function (queueName, cb) {
  if (!~queues.indexOf(queueName)) {
    throw new Error('attempting to subscribe to invalid queue: '+queueName);
  }
  if (cb.length !== 2) {
    throw new Error('queue listener callback must take a "done" callback function as a second'+
                    ' argument and invoke the function to send the ACK message to RabbitMQ'+
                    ' and remove the job from the queue.');
  }
  this.emit('subscribe', queueName, cb);
  return this;
};

/**
 * Factory method takes configuration once during applicaiton lifecycle and
 * returns instance of hermes
 */
module.exports.hermesSingletonFactory = function (opts) {
  hermes = (hermes) ? hermes : new Hermes(opts);
  return hermes;
};
<|endoftext|>


<commit_before>var express = require('express');
var app     = express();

var sendgrid = require('sendgrid')(
  process.env.SENDGRID_USERNAME,
  process.env.SENDGRID_PASSWORD
);

app.use(require('body-parser')());

app.get('/', function (req, res) {
  res.send([
    '<form method="post" style="width:500px;" action="/">',
    '<fieldset style="display:block;padding:5px;">',
    'To:
',
    '<input type="text" name="email" placeholder="text@example.com">',
    '</fieldset>',
    '<fieldset style="display:block;padding:5px;">',
    'Subject:
',
    '<input type="text" name="subject" placeholder="Test Email">',
    '</fieldset>',
    '<fieldset style="display:block;padding:5px;">',
    'Message:
',
    '<textarea style="width:100%;height:80px;padding:2px;" name="message" placeholder="Whoa!"></textarea>',
    '</fieldset>',
    '
<input type="submit" value="Send" />
',
    '</form>'
  ].join(''));
});

app.post('/', function (req, res) {
  sendgrid.send({
    to: req.body.email,
    from: 'test@example.com',
    subject: req.body.subject,
    text: req.body.message
  }, function (err, result) {
      if (err) {
        return res.send('Invalid format.');
      }

      res.send('Sent!');
    });
});

app.listen(process.env.PORT || 3000);
<commit_msg>Center the form.<commit_after>var express = require('express');
var app     = express();

var sendgrid = require('sendgrid')(
  process.env.SENDGRID_USERNAME,
  process.env.SENDGRID_PASSWORD
);

app.use(require('body-parser')());

app.get('/', function (req, res) {
  res.send([
    '<form method="post" style="width:500px;margin:60px auto 0;" action="/">',
    '<fieldset style="display:block;padding:5px;">',
    'To:
',
    '<input type="text" name="email" placeholder="text@example.com">',
    '</fieldset>',
    '<fieldset style="display:block;padding:5px;">',
    'Subject:
',
    '<input type="text" name="subject" placeholder="Test Email">',
    '</fieldset>',
    '<fieldset style="display:block;padding:5px;">',
    'Message:
',
    '<textarea style="width:100%;height:80px;padding:2px;" name="message" placeholder="Whoa!"></textarea>',
    '</fieldset>',
    '
<input type="submit" value="Send" />
',
    '</form>'
  ].join(''));
});

app.post('/', function (req, res) {
  sendgrid.send({
    to: req.body.email,
    from: 'test@example.com',
    subject: req.body.subject,
    text: req.body.message
  }, function (err) {
      if (err) {
        return res.send('Invalid format.');
      }

      res.send('Sent!');
    });
});

app.listen(process.env.PORT || 3000);
<|endoftext|>


<commit_before>#!/usr/bin/env node

const path = require('path');
const Mqtt = require('mqtt');
const log = require('yalm');
const HAP = require('hap-nodejs');
const pkgHap = require('./node_modules/hap-nodejs/package.json');
const pkg = require('./package.json');
const config = require('./config.js');

log.setLevel(config.verbosity);

log(pkg.name + ' ' + pkg.version + ' starting');

const mqttStatus = {};        // Holds the payloads of the last-received message, keys are the topics.
const mqttCallbacks = {};     // Holds arrays of subscription callbacks, keys are the topics.
let mqttConnected;

let bridgeListening;

log.info('mqtt trying to connect', config.url);
const mqtt = Mqtt.connect(config.url, {will: {topic: config.name + '/connected', payload: '0', retain: true}});

mqtt.on('connect', () => {
    mqttConnected = true;
    log.info('mqtt connected ' + config.url);
    /* istanbul ignore if */
    if (!bridgeListening) {
        mqtt.publish(config.name + '/connected', '1', {retain: true});
    }
});

/* istanbul ignore next */
mqtt.on('reconnect', () => {
    log.info('mqtt reconnect');
});

/* istanbul ignore next */
mqtt.on('offline', () => {
    log.info('mqtt offline');
});

/* istanbul ignore next */
mqtt.on('close', () => {
    if (mqttConnected) {
        mqttConnected = false;
        log.info('mqtt closed ' + config.url);
    }
});

/* istanbul ignore next */
mqtt.on('error', err => {
    log.error('mqtt error ' + err);
});

mqtt.on('message', (topic, payload) => {
    payload = payload.toString();
    let state;
    try {
        // Todo - check for json objects in a less nasty way ;)
        if (payload.indexOf('{') === -1) {
            throw new Error('not an object');
        } // We have no use for arrays here.
        // We got an Object - let's hope it follows mqtt-smarthome architecture and has an attribute "val"
        // see https://github.com/mqtt-smarthome/mqtt-smarthome/blob/master/Architecture.md
        state = JSON.parse(payload).val;
    } catch (err) {
        // Nasty type guessing.
        // Do we really need to cast the strings "true" and "false" to bool?
        if (payload === 'true') {
            state = true;
        } else if (payload === 'false') {
            state = false;
        } else if (isNaN(payload)) {
            state = payload;
        } else {
            state = parseFloat(payload);
        }
    }
    log.debug('< mqtt', topic, state);
    mqttStatus[topic] = state;
    /* istanbul ignore else */
    if (mqttCallbacks[topic]) {
        mqttCallbacks[topic].forEach(cb => {
            cb(state);
        });
    }
});

// MQTT subscribe function that provides a callback on incoming messages.
// Not meant to be used with wildcards!
function mqttSub(topic, callback) {
    topic = String(topic);
    /* istanbul ignore else */
    if (typeof callback === 'function') {
        if (mqttCallbacks[topic]) {
            mqttCallbacks[topic].push(callback);
        } else {
            mqttCallbacks[topic] = [callback];
            log.debug('mqtt subscribe', topic);
            mqtt.subscribe(topic);
        }
    } else {
        log.debug('mqtt subscribe', topic);
        mqtt.subscribe(topic);
    }
}

// MQTT publish function, checks for valid topic and converts payload to string in a meaningful manner.
function mqttPub(topic, payload, options) {
    if (!topic || (typeof topic !== 'string')) {
        log.error('mqttPub invalid topic', topic);
    } else {
        if (typeof payload === 'object') {
            payload = JSON.stringify(payload);
        } else if (typeof payload !== 'string') {
            payload = String(payload);
        }
        mqtt.publish(topic, payload, options, err => {
            /* istanbul ignore next */
            if (err) {
                log.error('mqtt publish error ' + err);
            }
        });
    }
}

log.info('using hap-nodejs version', pkgHap.version);

const uuid = HAP.uuid;
const Bridge = HAP.Bridge;
const Accessory = HAP.Accessory;
const Service = HAP.Service;
const Characteristic = HAP.Characteristic;

/* istanbul ignore next */
if (config.storagedir) {
    log.info('using directory ' + config.storagedir + ' for persistent storage');
}
// If storagedir is not set it uses HAP-Nodejs default
// (usually /usr/local/lib/node_modules/homekit2mqtt/node_modules/node-persist/persist)
HAP.init(config.storagedir || undefined);

// Create Bridge which will host all Accessories
const bridge = new Bridge(config.bridgename, uuid.generate(config.bridgename));

// Listen for Bridge identification event
/* istanbul ignore next */
bridge.on('identify', (paired, callback) => {
    log('< hap bridge identify', paired ? '(paired)' : '(unpaired)');
    callback();
});

// Handler for Accessory identification events
/* istanbul ignore next */
function identify(settings, paired, callback) {
    log.debug('< hap identify', settings.name, paired ? '(paired)' : '(unpaired)');
    if (settings.topic.identify) {
        log.debug('> mqtt', settings.topic.identify, settings.payload.identify);
        mqttPub(settings.topic.identify, settings.payload.identify);
    }
    callback();
}

function newAccessory(settings) {
    const acc = new Accessory(settings.name, uuid.generate(settings.id));
    if (settings.manufacturer || settings.model || settings.serial) {
        acc.getService(Service.AccessoryInformation)
            .setCharacteristic(Characteristic.Manufacturer, settings.manufacturer || '-')
            .setCharacteristic(Characteristic.Model, settings.model || '-')
            .setCharacteristic(Characteristic.SerialNumber, settings.serial || '-');
    }
    if (!settings.payload) {
        settings.payload = {};
    }
    /* istanbul ignore next */
    acc.on('identify', (paired, callback) => {
        identify(settings, paired, callback);
    });
    return acc;
}

const createAccessory = {};

function loadAccessory(acc) {
    const file = 'accessories/' + acc + '.js';
    log.debug('loading', file);
    createAccessory[acc] = require(path.join(__dirname, file))({mqttPub, mqttSub, mqttStatus, log, newAccessory, Service, Characteristic});
}

// Load and create all accessories
log.info('loading HomeKit to MQTT mapping file ' + config.mapfile);
const mapping = require(config.mapfile);
let accCount = 0;
Object.keys(mapping).forEach(id => {
    const a = mapping[id];
    a.id = id;
    if (!createAccessory[a.service]) {
        loadAccessory(a.service);
    }
    log.debug('addBridgedAccessory ' + a.service + ' ' + a.name);
    bridge.addBridgedAccessory(createAccessory[a.service](a));
    accCount++;
});
log.info('hap created', accCount, 'Accessories');

log('hap publishing bridge "' + config.bridgename + '" username=' + config.username, 'port=' + config.port, 'pincode=' + config.c);
bridge.publish({
    username: config.username,
    port: config.port,
    pincode: config.c,
    category: Accessory.Categories.OTHER
});

bridge._server.on('listening', () => {
    bridgeListening = true;
    mqtt.publish(config.name + '/connected', '2', {retain: true});
    log('hap Bridge listening on port', config.port);
});

bridge._server.on('pair', username => {
    log('hap paired', username);
});

/* istanbul ignore next */
bridge._server.on('unpair', username => {
    log('hap unpaired', username);
});

/* istanbul ignore next */
bridge._server.on('verify', () => {
    log('hap verify');
});
<commit_msg>empty default config<commit_after>#!/usr/bin/env node

const path = require('path');
const Mqtt = require('mqtt');
const log = require('yalm');
const HAP = require('hap-nodejs');
const pkgHap = require('./node_modules/hap-nodejs/package.json');
const pkg = require('./package.json');
const config = require('./config.js');

log.setLevel(config.verbosity);

log(pkg.name + ' ' + pkg.version + ' starting');

const mqttStatus = {};        // Holds the payloads of the last-received message, keys are the topics.
const mqttCallbacks = {};     // Holds arrays of subscription callbacks, keys are the topics.
let mqttConnected;

let bridgeListening;

log.info('mqtt trying to connect', config.url);
const mqtt = Mqtt.connect(config.url, {will: {topic: config.name + '/connected', payload: '0', retain: true}});

mqtt.on('connect', () => {
    mqttConnected = true;
    log.info('mqtt connected ' + config.url);
    /* istanbul ignore if */
    if (!bridgeListening) {
        mqtt.publish(config.name + '/connected', '1', {retain: true});
    }
});

/* istanbul ignore next */
mqtt.on('reconnect', () => {
    log.info('mqtt reconnect');
});

/* istanbul ignore next */
mqtt.on('offline', () => {
    log.info('mqtt offline');
});

/* istanbul ignore next */
mqtt.on('close', () => {
    if (mqttConnected) {
        mqttConnected = false;
        log.info('mqtt closed ' + config.url);
    }
});

/* istanbul ignore next */
mqtt.on('error', err => {
    log.error('mqtt error ' + err);
});

mqtt.on('message', (topic, payload) => {
    payload = payload.toString();
    let state;
    try {
        // Todo - check for json objects in a less nasty way ;)
        if (payload.indexOf('{') === -1) {
            throw new Error('not an object');
        } // We have no use for arrays here.
        // We got an Object - let's hope it follows mqtt-smarthome architecture and has an attribute "val"
        // see https://github.com/mqtt-smarthome/mqtt-smarthome/blob/master/Architecture.md
        state = JSON.parse(payload).val;
    } catch (err) {
        // Nasty type guessing.
        // Do we really need to cast the strings "true" and "false" to bool?
        if (payload === 'true') {
            state = true;
        } else if (payload === 'false') {
            state = false;
        } else if (isNaN(payload)) {
            state = payload;
        } else {
            state = parseFloat(payload);
        }
    }
    log.debug('< mqtt', topic, state);
    mqttStatus[topic] = state;
    /* istanbul ignore else */
    if (mqttCallbacks[topic]) {
        mqttCallbacks[topic].forEach(cb => {
            cb(state);
        });
    }
});

// MQTT subscribe function that provides a callback on incoming messages.
// Not meant to be used with wildcards!
function mqttSub(topic, callback) {
    topic = String(topic);
    /* istanbul ignore else */
    if (typeof callback === 'function') {
        /* istanbul ignore if */
        if (mqttCallbacks[topic]) {
            mqttCallbacks[topic].push(callback);
        } else {
            mqttCallbacks[topic] = [callback];
            log.debug('mqtt subscribe', topic);
            mqtt.subscribe(topic);
        }
    } else {
        log.debug('mqtt subscribe', topic);
        mqtt.subscribe(topic);
    }
}

// MQTT publish function, checks for valid topic and converts payload to string in a meaningful manner.
function mqttPub(topic, payload, options) {
    /* istanbul ignore if */
    if (!topic || (typeof topic !== 'string')) {
        log.error('mqttPub invalid topic', topic);
    } else {
        /* istanbul ignore if */
        if (typeof payload === 'object') {
            payload = JSON.stringify(payload);
        } else if (typeof payload !== 'string') {
            payload = String(payload);
        }
        mqtt.publish(topic, payload, options, err => {
            /* istanbul ignore next */
            if (err) {
                log.error('mqtt publish error ' + err);
            }
        });
    }
}

log.info('using hap-nodejs version', pkgHap.version);

const uuid = HAP.uuid;
const Bridge = HAP.Bridge;
const Accessory = HAP.Accessory;
const Service = HAP.Service;
const Characteristic = HAP.Characteristic;

/* istanbul ignore next */
if (config.storagedir) {
    log.info('using directory ' + config.storagedir + ' for persistent storage');
}
// If storagedir is not set it uses HAP-Nodejs default
// (usually /usr/local/lib/node_modules/homekit2mqtt/node_modules/node-persist/persist)
HAP.init(config.storagedir || undefined);

// Create Bridge which will host all Accessories
const bridge = new Bridge(config.bridgename, uuid.generate(config.bridgename));

// Listen for Bridge identification event
/* istanbul ignore next */
bridge.on('identify', (paired, callback) => {
    log('< hap bridge identify', paired ? '(paired)' : '(unpaired)');
    callback();
});

// Handler for Accessory identification events
/* istanbul ignore next */
function identify(settings, paired, callback) {
    log.debug('< hap identify', settings.name, paired ? '(paired)' : '(unpaired)');
    if (settings.topic.identify) {
        log.debug('> mqtt', settings.topic.identify, settings.payload.identify);
        mqttPub(settings.topic.identify, settings.payload.identify);
    }
    callback();
}

function newAccessory(settings) {
    const acc = new Accessory(settings.name, uuid.generate(settings.id));
    if (settings.manufacturer || settings.model || settings.serial) {
        acc.getService(Service.AccessoryInformation)
            .setCharacteristic(Characteristic.Manufacturer, settings.manufacturer || '-')
            .setCharacteristic(Characteristic.Model, settings.model || '-')
            .setCharacteristic(Characteristic.SerialNumber, settings.serial || '-');
    }
    if (!settings.payload) {
        settings.payload = {};
    }
    if (!settings.config) {
        settings.config = {};
    }
    /* istanbul ignore next */
    acc.on('identify', (paired, callback) => {
        identify(settings, paired, callback);
    });
    return acc;
}

const createAccessory = {};

function loadAccessory(acc) {
    const file = 'accessories/' + acc + '.js';
    log.debug('loading', file);
    createAccessory[acc] = require(path.join(__dirname, file))({mqttPub, mqttSub, mqttStatus, log, newAccessory, Service, Characteristic});
}

// Load and create all accessories
log.info('loading HomeKit to MQTT mapping file ' + config.mapfile);
const mapping = require(config.mapfile);
let accCount = 0;
Object.keys(mapping).forEach(id => {
    const a = mapping[id];
    a.id = id;
    if (!createAccessory[a.service]) {
        loadAccessory(a.service);
    }
    log.debug('addBridgedAccessory ' + a.service + ' ' + a.name);
    bridge.addBridgedAccessory(createAccessory[a.service](a));
    accCount++;
});
log.info('hap created', accCount, 'Accessories');

log('hap publishing bridge "' + config.bridgename + '" username=' + config.username, 'port=' + config.port, 'pincode=' + config.c);
bridge.publish({
    username: config.username,
    port: config.port,
    pincode: config.c,
    category: Accessory.Categories.OTHER
});

bridge._server.on('listening', () => {
    bridgeListening = true;
    mqtt.publish(config.name + '/connected', '2', {retain: true});
    log('hap Bridge listening on port', config.port);
});

bridge._server.on('pair', username => {
    log('hap paired', username);
});

/* istanbul ignore next */
bridge._server.on('unpair', username => {
    log('hap unpaired', username);
});

/* istanbul ignore next */
bridge._server.on('verify', () => {
    log('hap verify');
});
<|endoftext|>


<commit_before>~function() {

    getHashLink = function(){
      var hash = window.location["hash"];
      if (hash){
        var jreg = new RegExp("json\S*\=\S*([^\S]+)");
        var res = jreg.exec(hash);
        if (res){
          return res[1];
        }
      }
      return false;
    };

    getJSON = function(url, callback) {
      var xmlhttp = new XMLHttpRequest();
      xmlhttp.onreadystatechange=function(){
        if (xmlhttp.readyState==4 && xmlhttp.status==200){
          callback(JSON.parse(xmlhttp.responseText));
        } else {
          callback(false);
        }
      };
     xmlhttp.open("GET",url,true);
     xmlhttp.send();
    };

    function Baobab(game, container) {
        this.game = game;
        this.registers = game.registers;
        this.stack = [];

        this.container = container;
    }
    Baobab.prototype.printScene = function(scene) {
        var myself = this;
        var uid = Date.now();
        var active = true;

        var container = this.container;
        var div  = document.createElement("div");
        div.id = uid;

        var text = document.createElement("p");
        text.textContent = scene.description;
        var list = document.createElement("ul");

        var links = [];
        scene.links.forEach(function(link) {
            if (myself.evaluateBytecode(link.condition)) {
                var li = document.createElement("li");
                var a  = document.createElement("a");
                a.href = "#" + uid;
                a.textContent = link.text;

                a.addEventListener("click", function(moi) {
                    if (active) {
                        active = false;
                        div.className += " inactive";
                        a.className += " chosen";

                        myself.evaluateBytecode(link.actions);
                    }
                }, false);

                li.appendChild(a);
                links.push(a);
                list.appendChild(li);
            }
        });
        div.appendChild(text);
        div.appendChild(list);
        container.appendChild(div);
        window.scrollTo(0, document.body.scrollHeight);
    };
    Baobab.prototype.start = function() {
        while (this.container.firstChild) {
            this.container.removeChild(this.container.firstChild);
        }
        document.title = this.game.name + " - baobab";

        var title = document.createElement("h1");
        title.textContent = this.game.name;
        var author = document.createElement("h2");
        author.textContent = this.game.author;

        this.container.appendChild(title);
        this.container.appendChild(author);

        this.printScene(this.game.scenes[this.game.start]);
    };
    Baobab.prototype.evaluateBytecode = function(btc) {
        var myself = this;
        var ins = btc;
        if (ins[0] === "goto") {
            myself.printScene(myself.game.scenes[ins[1]]);
            return true;
        } else if (ins[0] === "display") {
            var p = document.createElement("p");
            p.textContent = myself.evaluateBytecode(ins[1]);
            myself.container.appendChild(p);
            return true;
        } else if (ins[0] === "random") {
            return Math.random();
        } else if (ins[0] === "number") {
            return ins[1];
        } else if (ins[0] === "string") {
            return ins[1];
        } else if (ins[0] === "boolean") {
            return ins[1];
        } else if (ins[0] === "+") {
            return myself.evaluateBytecode(ins[1]) + myself.evaluateBytecode(ins[2]);
        } else if (ins[0] === "-") {
            return myself.evaluateBytecode(ins[1]) - myself.evaluateBytecode(ins[2]);
        } else if (ins[0] === "*") {
            return myself.evaluateBytecode(ins[1]) * myself.evaluateBytecode(ins[2]);
        } else if (ins[0] === "/") {
            return myself.evaluateBytecode(ins[1]) / myself.evaluateBytecode(ins[2]);
        } else if (ins[0] === "and") {
            return myself.evaluateBytecode(ins[1]) && myself.evaluateBytecode(ins[2]);
        } else if (ins[0] === "or") {
            return myself.evaluateBytecode(ins[1]) || myself.evaluateBytecode(ins[2]);
        } else if (ins[0] === "not") {
            return !myself.evaluateBytecode(ins[1]);
        } else if (ins[0] === "<") {
            return myself.evaluateBytecode(ins[1]) < myself.evaluateBytecode(ins[2]);
        } else if (ins[0] === "=") {
            return myself.evaluateBytecode(ins[1]) = myself.evaluateBytecode(ins[2]);
        } else if (ins[0] === ">") {
            return myself.evaluateBytecode(ins[1]) > myself.evaluateBytecode(ins[2]);
        } else if (ins[0] === "reg") {
            return myself.registers[ins[1]];
        } else if (ins[0] === "set") {
            myself.registers[ins[1]] = myself.evaluateBytecode(ins[2]);
            return true;
        } else if (ins[0] === "begin") {
            var a = true;
            ins[1].forEach(function(i) {
                console.log("COWS", i);
                a = myself.evaluateBytecode(i);
            });
            return a;
        } else if (ins[0] === "if") {
            if (myself.evaluateBytecode(ins[1])) {
                return myself.evaluateBytecode(ins[2]);
            } else {
                return myself.evaluateBytecode(ins[3]);
            }
        } else if (ins[0] === "while") {
            while (myself.evaluateBytecode(ins[1])) {
                myself.evaluateBytecode(ins[2]);
            }
        } else {
            console.error("I don't know how to " + ins[0]);
        }
    };

    var test = {"author":"Art Vandelay","description":"A test story.","start":"home","name":"Homewards.","version":"baobab-0.0.1","registers":{"health":10,"owns-dinosaur?":true,"is-raining?":false},"scenes":{"home":{"description":"You are at home, sweet home.","title":"Your humble abode.","links":[{"text":"Walk the dinosaur.","condition":["boolean",true],"actions":["begin",[["goto","outside"]]]},{"text":"Set fire to the rain.","condition":["reg","is-raining?"],"actions":["begin",[["goto","home"]]]}]},"outside":{"description":"You are outside.","title":"You are outside.","links":[{"text":"Go back inside","condition":["boolean",true],"actions":["begin",[["if",[">",["random"],["number",0.5]],["boolean",true],["begin",[["display",["string","It gently begins to rain."]],["set","is-raining?",["boolean",true]]]]],["goto","home"]]]}]}}}

    ;

    var main = function(source){
        var b = new Baobab(source, document.getElementById("main"));
        b.start();
    };

    window.addEventListener("load", function() {
        var link = getHashLink();
        if (link){
            getJSON(link, main);
        } else {
            main(test);
        }
    }, false);
}();
<commit_msg>don't useloadJSON callback unless successful<commit_after>~function() {

    getHashLink = function(){
      var hash = window.location["hash"];
      if (hash){
        var jreg = new RegExp("json\S*\=\S*([^\S]+)");
        var res = jreg.exec(hash);
        if (res){
          return res[1];
        }
      }
      return false;
    };

    getJSON = function(url, callback) {
      var xmlhttp = new XMLHttpRequest();
      xmlhttp.onreadystatechange=function(){
        if (xmlhttp.readyState==4 && xmlhttp.status==200){
          callback(JSON.parse(xmlhttp.responseText));
        }
      };
     xmlhttp.open("GET",url,true);
     xmlhttp.send();
    };

    function Baobab(game, container) {
        this.game = game;
        this.registers = game.registers;
        this.stack = [];

        this.container = container;
    }
    Baobab.prototype.printScene = function(scene) {
        var myself = this;
        var uid = Date.now();
        var active = true;

        var container = this.container;
        var div  = document.createElement("div");
        div.id = uid;

        var text = document.createElement("p");
        text.textContent = scene.description;
        var list = document.createElement("ul");

        var links = [];
        scene.links.forEach(function(link) {
            if (myself.evaluateBytecode(link.condition)) {
                var li = document.createElement("li");
                var a  = document.createElement("a");
                a.href = "#" + uid;
                a.textContent = link.text;

                a.addEventListener("click", function(moi) {
                    if (active) {
                        active = false;
                        div.className += " inactive";
                        a.className += " chosen";

                        myself.evaluateBytecode(link.actions);
                    }
                }, false);

                li.appendChild(a);
                links.push(a);
                list.appendChild(li);
            }
        });
        div.appendChild(text);
        div.appendChild(list);
        container.appendChild(div);
        window.scrollTo(0, document.body.scrollHeight);
    };
    Baobab.prototype.start = function() {
        while (this.container.firstChild) {
            this.container.removeChild(this.container.firstChild);
        }
        document.title = this.game.name + " - baobab";

        var title = document.createElement("h1");
        title.textContent = this.game.name;
        var author = document.createElement("h2");
        author.textContent = this.game.author;

        this.container.appendChild(title);
        this.container.appendChild(author);

        this.printScene(this.game.scenes[this.game.start]);
    };
    Baobab.prototype.evaluateBytecode = function(btc) {
        var myself = this;
        var ins = btc;
        if (ins[0] === "goto") {
            myself.printScene(myself.game.scenes[ins[1]]);
            return true;
        } else if (ins[0] === "display") {
            var p = document.createElement("p");
            p.textContent = myself.evaluateBytecode(ins[1]);
            myself.container.appendChild(p);
            return true;
        } else if (ins[0] === "random") {
            return Math.random();
        } else if (ins[0] === "number") {
            return ins[1];
        } else if (ins[0] === "string") {
            return ins[1];
        } else if (ins[0] === "boolean") {
            return ins[1];
        } else if (ins[0] === "+") {
            return myself.evaluateBytecode(ins[1]) + myself.evaluateBytecode(ins[2]);
        } else if (ins[0] === "-") {
            return myself.evaluateBytecode(ins[1]) - myself.evaluateBytecode(ins[2]);
        } else if (ins[0] === "*") {
            return myself.evaluateBytecode(ins[1]) * myself.evaluateBytecode(ins[2]);
        } else if (ins[0] === "/") {
            return myself.evaluateBytecode(ins[1]) / myself.evaluateBytecode(ins[2]);
        } else if (ins[0] === "and") {
            return myself.evaluateBytecode(ins[1]) && myself.evaluateBytecode(ins[2]);
        } else if (ins[0] === "or") {
            return myself.evaluateBytecode(ins[1]) || myself.evaluateBytecode(ins[2]);
        } else if (ins[0] === "not") {
            return !myself.evaluateBytecode(ins[1]);
        } else if (ins[0] === "<") {
            return myself.evaluateBytecode(ins[1]) < myself.evaluateBytecode(ins[2]);
        } else if (ins[0] === "=") {
            return myself.evaluateBytecode(ins[1]) = myself.evaluateBytecode(ins[2]);
        } else if (ins[0] === ">") {
            return myself.evaluateBytecode(ins[1]) > myself.evaluateBytecode(ins[2]);
        } else if (ins[0] === "reg") {
            return myself.registers[ins[1]];
        } else if (ins[0] === "set") {
            myself.registers[ins[1]] = myself.evaluateBytecode(ins[2]);
            return true;
        } else if (ins[0] === "begin") {
            var a = true;
            ins[1].forEach(function(i) {
                console.log("COWS", i);
                a = myself.evaluateBytecode(i);
            });
            return a;
        } else if (ins[0] === "if") {
            if (myself.evaluateBytecode(ins[1])) {
                return myself.evaluateBytecode(ins[2]);
            } else {
                return myself.evaluateBytecode(ins[3]);
            }
        } else if (ins[0] === "while") {
            while (myself.evaluateBytecode(ins[1])) {
                myself.evaluateBytecode(ins[2]);
            }
        } else {
            console.error("I don't know how to " + ins[0]);
        }
    };

    var test = {"author":"Art Vandelay","description":"A test story.","start":"home","name":"Homewards.","version":"baobab-0.0.1","registers":{"health":10,"owns-dinosaur?":true,"is-raining?":false},"scenes":{"home":{"description":"You are at home, sweet home.","title":"Your humble abode.","links":[{"text":"Walk the dinosaur.","condition":["boolean",true],"actions":["begin",[["goto","outside"]]]},{"text":"Set fire to the rain.","condition":["reg","is-raining?"],"actions":["begin",[["goto","home"]]]}]},"outside":{"description":"You are outside.","title":"You are outside.","links":[{"text":"Go back inside","condition":["boolean",true],"actions":["begin",[["if",[">",["random"],["number",0.5]],["boolean",true],["begin",[["display",["string","It gently begins to rain."]],["set","is-raining?",["boolean",true]]]]],["goto","home"]]]}]}}}

    ;

    var main = function(source){
        var b = new Baobab(source, document.getElementById("main"));
        b.start();
    };

    window.addEventListener("load", function() {
        var link = getHashLink();
        if (link){
            getJSON(link, main);
        } else {
            main(test);
        }
    }, false);
}();
<|endoftext|>