<commit_before>const AWS = require('./AWS_API.js');
const GIT = require('./GITHUB_API.js');
const SLACK = require('./SlackInterface.js');
const pass = process.env.PASS || '';
const DEBUG = module.exports.DEBUG;
AWS.DEBUG = DEBUG;

//Main Controller Code

exports.parseCommand = function(message) {
    var text = message.text;
     if (DEBUG) {console.log("Parsing Command: "+text)}
    if (keyMessage(text, 'aws ')) {
        text = text.substring('aws '.length, text.length);
        if (keyMessage(text, 'check ec2 ')) {
            text = text.substring('check ec2 '.length, text.length);
            if (keyMessage(text, 'instance ')) {
                SLACK.handleMessagePromise(AWS.checkEC2Instance(text.substring('instance '.length, text.length)), message);
            } else {
                SLACK.handleMessagePromise(AWS.checkEC2(), message);
            }
        } else if (keyMessage(text, 'check number of instances ')) {
            SLACK.handleMessagePromise(AWS.checkNumInstances(), message);
        } else if (keyMessage(text, 'get cost of ')) {
            SLACK.handleMessagePromise(AWS.getTotalInstanceCost(text.substring('get cost of '.length, text.length)), message);
        } else {
            SLACK.sendMessage("AWS command does not exist", message);
        }
    } else if (keyMessage(text, 'slack ')) {
        text = text.substring('slack '.length, text.length);
        var userRegex = /<@([A-Z|1-9]+.)>/i;
        var channelRegex = /<?#([A-Z0-9]+)(\|\w+>)?/i;
        if (userRegex.test(text)) {
            SLACK.handleMessagePromise(SLACK.slackUserName(text.replace(userRegex, '$1')), message);
        } else if (channelRegex.test(text)) {
            var key = text.replace(channelRegex, '$1');
            SLACK.handleMessagePromise(SLACK.slackChannelInfo(key), message);
        } else if (keyMessage(text, 'list users ')) {
            SLACK.handleMessagePromise(SLACK.slackTeamList(), message);
        } else if (keyMessage(text, 'whoami ')) {
            SLACK.handleMessagePromise(SLACK.slackWhoAmI(), message);
        } else if (keyMessage(text, 'whos online ')) {
            SLACK.handleMessagePromise(SLACK.slackWhoseOnline(), message);
        } else if (keyMessage(text, 'debug ')) {
            SLACK.sendMessage("Debug: "+JSON.stringify(message), message);
        } else {
            SLACK.sendMessage("Slack command does not exist", message);
        }
    } else if (keyMessage(text, 'git ')) {
        SLACK.handleMessagePromise(GIT.auth(pass), message);
        text = text.substring('git '.length, text.length);
            if (keyMessage(text, 'branches')) {
                SLACK.handleMessagePromise(GIT.checkNumberofFeatureBranches(), message);
            }else if (keyMessage(text, 'list branches')) {
                SLACK.handleMessagePromise(GIT.listBranches(), message);
            }else if (keyMessage(text, 'pushed')){
                text = text.substring('pushed '.length, text.length);
                SLACK.handleMessagePromise(GIT.checkLastPushedtoBranchName(text), message);
            }else if (keyMessage(text, 'open pull')){
                SLACK.handleMessagePromise(GIT.checkLatestPullRequest(), message);
            }else if (keyMessage(text, 'closed pull')){
                SLACK.handleMessagePromise(GIT.checkLatestClosedPullRequest(), message);
            }else if (keyMessage(text, 'time')){
                text = text.substring('time '.length, text.length);
			     SLACK.handleMessagePromise(GIT.checkLatestBranchUpdatgeTime(text), message);
			}else if (keyMessage(text, 'contributors')){
			     SLACK.handleMessagePromise(GIT.checkContributors(), message);
			}else if (keyMessage(text, 'repos')) {
				 text = text.substring('repos '.length, text.length);
				 SLACK.handleMessagePromise(GIT.getRepos(text), message);
			}else if (keyMessage(text, 'get all pull requests')){
			     SLACK.handleMessagePromise(GIT.getAllPullRequests(), message);
			}else if (keyMessage(text, 'merge pull request')){
			     text = text.substring('merge pull request '.length, text.length);
				 SLACK.handleMessagePromise(GIT.mergePullRequest(text), message);
			}else if (keyMessage(text, 'feeds')){
                SLACK.handleMessagePromise(GIT.feeds(), message);
            }else if (keyMessage(text, 'add repo ')){
			     text = text.substring('add repo '.length, text.length);
                message.text = text;
				 SLACK.handleMessagePromise(GIT.addRepo(message), message);

			}else if (keyMessage(text, '-testrepo ')){
			     text = text.substring('-testrepo '.length, text.length);
				 SLACK.handleMessagePromise(GIT.repoTest(text), message);
			}else {
				SLACK.sendMessage("Git Command does not exist", message);
			}
    }else if (keyMessage(text, 'help ')) {
        SLACK.handleMessagePromise(getActiveCommands(), message);
    }
    //SAMPLE CONVERSATION CONSTRUCT
    else if (keyMessage(text, 'wait ')) {
        text = text.substring('wait '.length, text.length);
        if(text.length == 0){
            SLACK.startConversation("wait -1 ",message);
            SLACK.sendMessage("I'm Listening for another command", message);
        }else if (keyMessage(text, '-1 ')){
            text = text.substring('-1 '.length, text.length);
            console.log(text);
                if(keyMessage(text,'sample command ')){
                    SLACK.sendMessage("This is a command accessed by conversation", message);
                }else{
                    SLACK.sendMessage("Try using `wait`, then `sample command` :wink: :wink:", message);
                }
            }
    } else {
        SLACK.sendMessage("I'm sorry, this isn't a command I'm familiar with. use `help` command for list of commands", message);
    }
}

/*******************************************************************************
 * Helper functions
 */

function keyMessage(text, key) {
    var temptext = text + ' ';
    if (temptext.length >= key.length && temptext.substring(0, key.length).toLowerCase() === key) {
        return true;
    }
    return false;
}

getActiveCommands = function(){
    if (exports.DEBUG) {console.log('getActiveCommands called.')}
    return new Promise (function(fulfill,reject) {
        fulfill(`Here are my Current Commands:

aws (Cloud - Amazon Web Services)
\tcheck ec2 [instance]
\tcheck number of instances
\tget cost of [instance]

git (GitHub)
\tbranches
\tlist branches
\tpushed [branch-name]
\topen pull
\tclosed pull
\ttime [branch-name]
\tcontributors
\trepos
\tget all pull requests
\tmerge pull request [pull request number]
\tfeeds

slack
\t#(Channel Name)
\t@(Username)
\twhoami
\twhos online
\tlist users
\twait
`);
    });
}
<commit_msg>Add slack options to the controller<commit_after>const AWS = require('./AWS_API.js');
const GIT = require('./GITHUB_API.js');
const SLACK = require('./SlackInterface.js');
const pass = process.env.PASS || '';
const DEBUG = module.exports.DEBUG;
AWS.DEBUG = DEBUG;

//Main Controller Code

exports.parseCommand = function(message) {
    var text = message.text;
     if (DEBUG) {console.log("Parsing Command: "+text)}
    if (keyMessage(text, 'aws ')) {
        text = text.substring('aws '.length, text.length);
        if (keyMessage(text, 'check ec2 ')) {
            text = text.substring('check ec2 '.length, text.length);
            if (keyMessage(text, 'instance ')) {
                SLACK.handleMessagePromise(AWS.checkEC2Instance(text.substring('instance '.length, text.length)), message);
            } else {
                SLACK.handleMessagePromise(AWS.checkEC2(), message);
            }
        } else if (keyMessage(text, 'check number of instances ')) {
            SLACK.handleMessagePromise(AWS.checkNumInstances(), message);
        } else if (keyMessage(text, 'get cost of ')) {
            text = text.substring('get cost of '.length, text.length);
            if (keyMessage(text, 'account')) {
                SLACK.handleMessagePromise(AWS.getTotalAccountCost(), message);
            } else {
                SLACK.handleMessagePromise(AWS.getTotalInstanceCost(text.substring('get cost of '.length, text.length)), message);
            }
        } else if (keyMessage(text, 'list instances')) {
            SLACK.handleMessagePromise(AWS.listInstances(), message);
        } else {
            SLACK.sendMessage("AWS command does not exist", message);
        }
    } else if (keyMessage(text, 'slack ')) {
        text = text.substring('slack '.length, text.length);
        var userRegex = /<@([A-Z|1-9]+.)>/i;
        var channelRegex = /<?#([A-Z0-9]+)(\|\w+>)?/i;
        if (userRegex.test(text)) {
            SLACK.handleMessagePromise(SLACK.slackUserName(text.replace(userRegex, '$1')), message);
        } else if (channelRegex.test(text)) {
            var key = text.replace(channelRegex, '$1');
            SLACK.handleMessagePromise(SLACK.slackChannelInfo(key), message);
        } else if (keyMessage(text, 'list users ')) {
            SLACK.handleMessagePromise(SLACK.slackTeamList(), message);
        } else if (keyMessage(text, 'whoami ')) {
            SLACK.handleMessagePromise(SLACK.slackWhoAmI(), message);
        } else if (keyMessage(text, 'whos online ')) {
            SLACK.handleMessagePromise(SLACK.slackWhoseOnline(), message);
        } else if (keyMessage(text, 'debug ')) {
            SLACK.sendMessage("Debug: "+JSON.stringify(message), message);
        } else {
            SLACK.sendMessage("Slack command does not exist", message);
        }
    } else if (keyMessage(text, 'git ')) {
        SLACK.handleMessagePromise(GIT.auth(pass), message);
        text = text.substring('git '.length, text.length);
            if (keyMessage(text, 'branches')) {
                SLACK.handleMessagePromise(GIT.checkNumberofFeatureBranches(), message);
            }else if (keyMessage(text, 'list branches')) {
                SLACK.handleMessagePromise(GIT.listBranches(), message);
            }else if (keyMessage(text, 'pushed')){
                text = text.substring('pushed '.length, text.length);
                SLACK.handleMessagePromise(GIT.checkLastPushedtoBranchName(text), message);
            }else if (keyMessage(text, 'open pull')){
                SLACK.handleMessagePromise(GIT.checkLatestPullRequest(), message);
            }else if (keyMessage(text, 'closed pull')){
                SLACK.handleMessagePromise(GIT.checkLatestClosedPullRequest(), message);
            }else if (keyMessage(text, 'time')){
                text = text.substring('time '.length, text.length);
			     SLACK.handleMessagePromise(GIT.checkLatestBranchUpdatgeTime(text), message);
			}else if (keyMessage(text, 'contributors')){
			     SLACK.handleMessagePromise(GIT.checkContributors(), message);
			}else if (keyMessage(text, 'repos')) {
				 text = text.substring('repos '.length, text.length);
				 SLACK.handleMessagePromise(GIT.getRepos(text), message);
			}else if (keyMessage(text, 'get all pull requests')){
			     SLACK.handleMessagePromise(GIT.getAllPullRequests(), message);
			}else if (keyMessage(text, 'merge pull request')){
			     text = text.substring('merge pull request '.length, text.length);
				 SLACK.handleMessagePromise(GIT.mergePullRequest(text), message);
			}else if (keyMessage(text, 'feeds')){
                SLACK.handleMessagePromise(GIT.feeds(), message);
            }else if (keyMessage(text, 'add repo ')){
			     text = text.substring('add repo '.length, text.length);
                message.text = text;
				 SLACK.handleMessagePromise(GIT.addRepo(message), message);

			}else if (keyMessage(text, '-testrepo ')){
			     text = text.substring('-testrepo '.length, text.length);
				 SLACK.handleMessagePromise(GIT.repoTest(text), message);
			}else {
				SLACK.sendMessage("Git Command does not exist", message);
			}
    }else if (keyMessage(text, 'help ')) {
        SLACK.handleMessagePromise(getActiveCommands(), message);
    }
    //SAMPLE CONVERSATION CONSTRUCT
    else if (keyMessage(text, 'wait ')) {
        text = text.substring('wait '.length, text.length);
        if(text.length == 0){
            SLACK.startConversation("wait -1 ",message);
            SLACK.sendMessage("I'm Listening for another command", message);
        }else if (keyMessage(text, '-1 ')){
            text = text.substring('-1 '.length, text.length);
            console.log(text);
                if(keyMessage(text,'sample command ')){
                    SLACK.sendMessage("This is a command accessed by conversation", message);
                }else{
                    SLACK.sendMessage("Try using `wait`, then `sample command` :wink: :wink:", message);
                }
            }
    } else {
        SLACK.sendMessage("I'm sorry, this isn't a command I'm familiar with. use `help` command for list of commands", message);
    }
}

/*******************************************************************************
 * Helper functions
 */

function keyMessage(text, key) {
    var temptext = text + ' ';
    if (temptext.length >= key.length && temptext.substring(0, key.length).toLowerCase() === key) {
        return true;
    }
    return false;
}

getActiveCommands = function(){
    if (exports.DEBUG) {console.log('getActiveCommands called.')}
    return new Promise (function(fulfill,reject) {
        fulfill(`Here are my Current Commands:

aws (Cloud - Amazon Web Services)
\tlist instances
\tcheck ec2 [instance]
\tcheck number of instances
\tget cost of [instance]
\tget cost of account

git (GitHub)
\tbranches
\tlist branches
\tpushed [branch-name]
\topen pull
\tclosed pull
\ttime [branch-name]
\tcontributors
\trepos
\tget all pull requests
\tmerge pull request [pull request number]
\tfeeds

slack
\t#(Channel Name)
\t@(Username)
\twhoami
\twhos online
\tlist users
\twait
`);
    });
}
<|endoftext|>


<commit_before>//= require ./history
//= require ./utils
//= require_self

/*
 * * * * * * * * * * * * * * * * * *
 * Inspired by Backbone.js Router  *
 * * * * * * * * * * * * * * * * * *
 */
(function () {

	"use strict";

	/**
	 * @memberof Marbles
	 * @class
	 * @see Marbles.History
	 * @example
	 *	var MyRouter = Marbles.Router.createClass({
	 *		displayName: "MyRouter",
	 *
	 *		// routes are evaluated in the order they are defined
	 *		routes: [
	 *			{ path: "posts", handler: "posts" },
	 *
	 *			// :id will be available in the params
	 *			{ path: "posts/:id", handler: "posts" },
	 *
	 *			// * will be available in the params as `splat`
	 *			{ path: "posts/:id/*", handler: "posts" },
	 *		],
	 *
	 *		beforeHandler: function (event) { // optional before hook
	 *			// same as handler:before event sent through dispatcher
	 *			// but only called for the router the handler belongs to
	 *			// and called before event is sent through dispatcher
	 *		},
	 *
	 *		posts: function (params, opts) {
	 *			// params is an array of objects,
	 *			// params[0] should be all you need unless
	 *			// you have multiple params of the same name
	 *
	 *			// opts contains any extra properties given in a route object
	 *		}
	 *	});
	 *	new MyRouter(); // bring it to life
	 */
	var Router = Marbles.Utils.createClass({
		displayName: 'Marbles.Router',

		willInitialize: function () {
			this.bindRoutes();
		},

		navigate: function (path, options) {
			return Marbles.history.navigate(path, options);
		},

		// register route handler
		// handler will be called with an array
		// of param objects, the first of which
		// will contain any named params
		route: function (route, handler, opts) {
			if (!Marbles.history) {
				Marbles.history = new Marbles.History();
			}

			var paramNames = [];
			if (typeof route.test !== 'function') {
				paramNames = this.routeParamNames(route);
				route = this.routeToRegExp(route);
			}

			var name;
			if (typeof handler === 'function') {
				name = handler.name || handler.displayName || null;
			} else {
				name = handler;
				handler = this[handler];
			}

			Marbles.history.route(route, name, handler, paramNames, opts, this);
		},

		bindRoutes: function () {
			var ctor = this.constructor;
			if (!ctor.routes) {
				throw new Error("You need to define "+ ctor.displayName || ctor.name +".routes");
			}

			var opts, k;
			for (var i = 0, _ref = ctor.routes, _len = _ref.length; i < _len; i++) {
				opts = {};
				for (k in _ref[i]) {
					if (_ref[i].hasOwnProperty(k) && k !== "path" && k !== "handler") {
						opts[k] = _ref[i][k];
					}
				}
				this.route(_ref[i].path, _ref[i].handler, opts);
			}
		},

		routeToRegExp: function (route) {
			if (route[0] === "/") {
				// trim / prefix
				route = route.substring(1);
			}

			var ctor = this.constructor;
			route = route.replace(ctor.regex.escape, '\\$&').
										replace(ctor.regex.namedParam, '([^\/]+)').
										replace(ctor.regex.splatParam, '(.*?)');
			return new RegExp('^' + route + '$');
		},

		routeParamNames: function (route) {
			var ctor = this.constructor;
			var paramNames = [];
			var _ref = route.match(ctor.regex.namedParam);
			if (_ref && _ref.length) {
				for (var i = 0, _len = _ref.length; i < _len; i++) {
					paramNames.push(_ref[i].slice(1));
				}
			}
			_ref = route.match(ctor.regex.splatParam);
			if (_ref && _ref.length) {
				for (i = 0, _len = _ref.length; i < _len; i++) {
					paramNames.push("splat" + (i > 0 ? i+1 : ""));
				}
			}
			return paramNames;
		},

		extractNamedParams: function (route, path, paramNames) {
			var values = [],
					params = {};

			for (var i = 0, _ref = this.extractParams(route, path), _len = _ref.length; i < _len; i++) {
				values.push(decodeURIComponent(_ref[i]));
			}

			for (i = 0, _len = paramNames.length; i < _len; i++) {
				params[paramNames[i]] = values[i];
			}

			return params;
		},

		extractParams: function (route, path) {
			return route.exec(path).slice(1);
		}

	});

	Marbles.Router = Router;

	Router.regex = {
    namedParam: /:\w+/g,
    splatParam: /\*\w*/g,
    escape: /[-[\]{}()+?.,\\^$|#\s]/g
	};

	Router.routes = [];

	Router.createClass = function (proto) {
		if (!proto.hasOwnProperty('displayName')) {
			proto.displayName = this.displayName;
		}
		var routes = this.routes;
		if (proto.hasOwnProperty('routes')) {
			routes = proto.routes;
			delete proto.routes;
		}
		proto.parentClass = this;
		var ctor =  Marbles.Utils.createClass(proto);
		ctor.routes = routes;
		return ctor;
	};

})();
<commit_msg>Fix subclassing routers<commit_after>//= require ./history
//= require ./utils
//= require_self

/*
 * * * * * * * * * * * * * * * * * *
 * Inspired by Backbone.js Router  *
 * * * * * * * * * * * * * * * * * *
 */
(function () {

	"use strict";

	/**
	 * @memberof Marbles
	 * @class
	 * @see Marbles.History
	 * @example
	 *	var MyRouter = Marbles.Router.createClass({
	 *		displayName: "MyRouter",
	 *
	 *		// routes are evaluated in the order they are defined
	 *		routes: [
	 *			{ path: "posts", handler: "posts" },
	 *
	 *			// :id will be available in the params
	 *			{ path: "posts/:id", handler: "posts" },
	 *
	 *			// * will be available in the params as `splat`
	 *			{ path: "posts/:id/*", handler: "posts" },
	 *		],
	 *
	 *		beforeHandler: function (event) { // optional before hook
	 *			// same as handler:before event sent through dispatcher
	 *			// but only called for the router the handler belongs to
	 *			// and called before event is sent through dispatcher
	 *		},
	 *
	 *		posts: function (params, opts) {
	 *			// params is an array of objects,
	 *			// params[0] should be all you need unless
	 *			// you have multiple params of the same name
	 *
	 *			// opts contains any extra properties given in a route object
	 *		}
	 *	});
	 *	new MyRouter(); // bring it to life
	 */
	var Router = Marbles.Utils.createClass({
		displayName: 'Marbles.Router',

		willInitialize: function () {
			this.bindRoutes();
		},

		navigate: function (path, options) {
			return Marbles.history.navigate(path, options);
		},

		// register route handler
		// handler will be called with an array
		// of param objects, the first of which
		// will contain any named params
		route: function (route, handler, opts) {
			if (!Marbles.history) {
				Marbles.history = new Marbles.History();
			}

			var paramNames = [];
			if (typeof route.test !== 'function') {
				paramNames = this.routeParamNames(route);
				route = this.routeToRegExp(route);
			}

			var name;
			if (typeof handler === 'function') {
				name = handler.name || handler.displayName || null;
			} else {
				name = handler;
				handler = this[handler];
			}

			Marbles.history.route(route, name, handler, paramNames, opts, this);
		},

		bindRoutes: function () {
			var ctor = this.constructor;
			if (!ctor.routes) {
				throw new Error("You need to define "+ ctor.displayName || ctor.name +".routes");
			}

			var opts, k;
			for (var i = 0, _ref = ctor.routes, _len = _ref.length; i < _len; i++) {
				opts = {};
				for (k in _ref[i]) {
					if (_ref[i].hasOwnProperty(k) && k !== "path" && k !== "handler") {
						opts[k] = _ref[i][k];
					}
				}
				this.route(_ref[i].path, _ref[i].handler, opts);
			}
		},

		routeToRegExp: function (route) {
			if (route[0] === "/") {
				// trim / prefix
				route = route.substring(1);
			}

			var ctor = this.constructor;
			route = route.replace(ctor.regex.escape, '\\$&').
										replace(ctor.regex.namedParam, '([^\/]+)').
										replace(ctor.regex.splatParam, '(.*?)');
			return new RegExp('^' + route + '$');
		},

		routeParamNames: function (route) {
			var ctor = this.constructor;
			var paramNames = [];
			var _ref = route.match(ctor.regex.namedParam);
			if (_ref && _ref.length) {
				for (var i = 0, _len = _ref.length; i < _len; i++) {
					paramNames.push(_ref[i].slice(1));
				}
			}
			_ref = route.match(ctor.regex.splatParam);
			if (_ref && _ref.length) {
				for (i = 0, _len = _ref.length; i < _len; i++) {
					paramNames.push("splat" + (i > 0 ? i+1 : ""));
				}
			}
			return paramNames;
		},

		extractNamedParams: function (route, path, paramNames) {
			var values = [],
					params = {};

			for (var i = 0, _ref = this.extractParams(route, path), _len = _ref.length; i < _len; i++) {
				values.push(decodeURIComponent(_ref[i]));
			}

			for (i = 0, _len = paramNames.length; i < _len; i++) {
				params[paramNames[i]] = values[i];
			}

			return params;
		},

		extractParams: function (route, path) {
			return route.exec(path).slice(1);
		}

	});

	Marbles.Router = Router;

	Router.regex = {
    namedParam: /:\w+/g,
    splatParam: /\*\w*/g,
    escape: /[-[\]{}()+?.,\\^$|#\s]/g
	};

	Router.routes = [];

	Router.createClass = function (proto) {
		if (!proto.hasOwnProperty('displayName')) {
			proto.displayName = this.displayName;
		}
		var routes = this.routes;
		if (proto.hasOwnProperty('routes')) {
			routes = proto.routes;
			delete proto.routes;
		}
		proto.parentClass = this;
		var ctor =  Marbles.Utils.createClass(proto);
		ctor.routes = routes;
		ctor.createClass = Router.createClass.bind(ctor);
		return ctor;
	};

})();
<|endoftext|>


<commit_before>/*
 *
 * Find more about this plugin by visiting
 * http://alxgbsn.co.uk/
 *
 * Copyright (c) 2010-2012 Alex Gibson
 * Released under MIT license
 *
 */

(function (window, document) {

    function Shake() {

        //feature detect
        if(!('createEvent' in document)) return false
        this.hasDeviceMotion = 'ondevicemotion' in window;

        //default velocity threshold for shake to register
        this.threshold = 15;

        //use date to prevent multiple shakes firing
        this.lastTime = new Date();

        //accelerometer values
        this.lastX = null;
        this.lastY = null;
        this.lastZ = null;

        //create custom event
        if (typeof CustomEvent === "function") {
            this.event = new CustomEvent('shake', {
                bubbles: true,
                cancelable: true
            });
        } else {
            this.event = document.createEvent('Event');
            this.event.initEvent('shake', true, true);
        }
    }

    //reset timer values
    Shake.prototype.reset = function () {
        this.lastTime = new Date();
        this.lastX = null;
        this.lastY = null;
        this.lastZ = null;
    };

    //start listening for devicemotion
    Shake.prototype.start = function () {
        this.reset();
        if (this.hasDeviceMotion) { window.addEventListener('devicemotion', this, false); }
    };

    //stop listening for devicemotion
    Shake.prototype.stop = function () {

        if (this.hasDeviceMotion) { window.removeEventListener('devicemotion', this, false); }
        this.reset();
    };

    //calculates if shake did occur
    Shake.prototype.devicemotion = function (e) {

        var current = e.accelerationIncludingGravity,
            currentTime,
            timeDifference,
            deltaX = 0,
            deltaY = 0,
            deltaZ = 0;

        if ((this.lastX === null) && (this.lastY === null) && (this.lastZ === null)) {
            this.lastX = current.x;
            this.lastY = current.y;
            this.lastZ = current.z;
            return;
        }

        deltaX = Math.abs(this.lastX - current.x);
        deltaY = Math.abs(this.lastY - current.y);
        deltaZ = Math.abs(this.lastZ - current.z);

        if (((deltaX > this.threshold) && (deltaY > this.threshold)) || ((deltaX > this.threshold) && (deltaZ > this.threshold)) || ((deltaY > this.threshold) && (deltaZ > this.threshold))) {
            //calculate time in milliseconds since last shake registered
            currentTime = new Date();
            timeDifference = currentTime.getTime() - this.lastTime.getTime();

            if (timeDifference > 1000) {
                window.dispatchEvent(this.event);
                this.lastTime = new Date();
            }
        }

        this.lastX = current.x;
        this.lastY = current.y;
        this.lastZ = current.z;

    };

    //event handler
    Shake.prototype.handleEvent = function (e) {

        if (typeof (this[e.type]) === 'function') {
            return this[e.type](e);
        }
    };

    //create a new instance of shake.js.
    var myShakeEvent = new Shake();
    myShakeEvent && myShakeEvent.start();

}(window, document));
<commit_msg>Moved the event detection. Supporting CustomEvent if createEvent is not present<commit_after>/*
 *
 * Find more about this plugin by visiting
 * http://alxgbsn.co.uk/
 *
 * Copyright (c) 2010-2012 Alex Gibson
 * Released under MIT license
 *
 */

(function (window, document) {

    function Shake() {

        //feature detect
        this.hasDeviceMotion = 'ondevicemotion' in window;

        //default velocity threshold for shake to register
        this.threshold = 15;

        //use date to prevent multiple shakes firing
        this.lastTime = new Date();

        //accelerometer values
        this.lastX = null;
        this.lastY = null;
        this.lastZ = null;

        //create custom event
        if (typeof CustomEvent === "function") {
            this.event = new CustomEvent('shake', {
                bubbles: true,
                cancelable: true
            });
        } else if (typeof document.createEvent === "function") {
            this.event = document.createEvent('Event');
            this.event.initEvent('shake', true, true);
        } else {
          return false;
        }
    }

    //reset timer values
    Shake.prototype.reset = function () {
        this.lastTime = new Date();
        this.lastX = null;
        this.lastY = null;
        this.lastZ = null;
    };

    //start listening for devicemotion
    Shake.prototype.start = function () {
        this.reset();
        if (this.hasDeviceMotion) { window.addEventListener('devicemotion', this, false); }
    };

    //stop listening for devicemotion
    Shake.prototype.stop = function () {

        if (this.hasDeviceMotion) { window.removeEventListener('devicemotion', this, false); }
        this.reset();
    };

    //calculates if shake did occur
    Shake.prototype.devicemotion = function (e) {

        var current = e.accelerationIncludingGravity,
            currentTime,
            timeDifference,
            deltaX = 0,
            deltaY = 0,
            deltaZ = 0;

        if ((this.lastX === null) && (this.lastY === null) && (this.lastZ === null)) {
            this.lastX = current.x;
            this.lastY = current.y;
            this.lastZ = current.z;
            return;
        }

        deltaX = Math.abs(this.lastX - current.x);
        deltaY = Math.abs(this.lastY - current.y);
        deltaZ = Math.abs(this.lastZ - current.z);

        if (((deltaX > this.threshold) && (deltaY > this.threshold)) || ((deltaX > this.threshold) && (deltaZ > this.threshold)) || ((deltaY > this.threshold) && (deltaZ > this.threshold))) {
            //calculate time in milliseconds since last shake registered
            currentTime = new Date();
            timeDifference = currentTime.getTime() - this.lastTime.getTime();

            if (timeDifference > 1000) {
                window.dispatchEvent(this.event);
                this.lastTime = new Date();
            }
        }

        this.lastX = current.x;
        this.lastY = current.y;
        this.lastZ = current.z;

    };

    //event handler
    Shake.prototype.handleEvent = function (e) {

        if (typeof (this[e.type]) === 'function') {
            return this[e.type](e);
        }
    };

    //create a new instance of shake.js.
    var myShakeEvent = new Shake();
    myShakeEvent && myShakeEvent.start();

}(window, document));
<|endoftext|>


<commit_before>/*
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

'use strict'

var _ = require('lodash')
var Vorpal = require('vorpal')
var CliTable = require('cli-table')
var procList = []
require('colors')

/**
 * fuge run -> executes through here - runs all and starts a log tail
 * hitting any key will stop the tail
 * need a command history
 */
module.exports = function () {
  var _config
  var _runner
  var vorpal = new Vorpal()

  var tableChars = {
    'top': '', 'top-mid': '', 'top-left': '', 'top-right': '',
    'bottom': '', 'bottom-mid': '', 'bottom-left': '', 'bottom-right': '',
    'left': '', 'left-mid': '', 'mid': '', 'mid-mid': '',
    'right': '', 'right-mid': '', 'middle': ''
  }

  var tableStyle = {
    'padding-left': 0,
    'padding-right': 0
  }

  var stopSystem = function (system) {
    _runner.stopAll(system, function () {
      process.exit(0)
    })
  }

  var autoComp = function (system) {
    _.each(system.topology.containers, function (container) {
      procList.push(container.name)
    })
  }

  var psList = function (args, system, cb) {
    var table = new CliTable({chars: tableChars, style: tableStyle,
                              head: ['name'.white, 'type'.white, 'status'.white, 'watch'.white, 'tail'.white], colWidths: [30, 15, 15, 15, 15]})
    var procs = _runner.processes()

    _.each(system.topology.containers, function (container) {
      if (container.type === 'docker' && _config.runDocker === false) {
        table.push([container.name.gray, container.type.gray, 'not managed'.gray, '', ''])
      } else {
        var procKey = _.find(_.keys(procs), function (key) { return procs[key].identifier === container.name })
        if (procKey) {
          var proc = procs[procKey]
          table.push([container.name.green,
                      container.type.green,
                      container.profiling ? 'profiling'.green : 'running'.green,
                      proc.monitor ? 'yes'.green : 'no'.red,
                      proc.tail ? 'yes'.green : 'no'.red])
        } else {
          table.push([container.name.red,
                      container.type.red,
                      'stopped'.red,
                      container.monitor ? 'yes'.green : 'no'.red,
                      container.tail ? 'yes'.green : 'no'.red])
                     //  '0'.red])
        }
      }
    })
    console.log(table.toString())
    cb()
  }

  var showInfo = function (args, system, cb) {
    if (args.length === 2) {
      _runner.preview(system, args[1], function (err, command) {
        if (err) { cb(err) }
        if (command && command.detail) {
          var env = ''
          console.log('command: ' + command.detail.cmd)
          console.log('directory: ' + command.detail.cwd)
          _.each(_.keys(command.detail.environment), function (key) {
            env += '  ' + key + '=' + command.detail.environment[key] + '\n'
          })
          console.log('environment:\n' + env)
        } else {
          console.log('not managed or unknown process')
        }
        cb()
      })
    } else {
      cb('process not specified')
    }
  }

  var stopProcess = function (args, system, cb) {
    if (args.length === 1 && args[0] === 'exit') {
      stopSystem(system)
    } else if (args.length === 1 || args[1][0] === 'all') {
      _runner.stopAll(system, cb)
    } else {
      for (var i = 0; i < args[1].length; i++) {
        _runner.stop(system, args[1][i], 1, cb)
      }
    }
  }

  var startProcess = function (args, system, cb) {
    if (args.length === 1 || args[1][0] === 'all') {
      _runner.startAll(system, args[2] || 1, cb)
    } else {
      for (var i = 0; i < args[1].length; i++) {
        _runner.start(system, args[1][i], 1, cb)
      }
    }
  }

  var debugProcess = function (args, system, cb) {
    if (args.length === 2) {
      if (!_runner.isProcessRunning(args[1])) {
        _runner.debug(system, args[1], cb)
      } else {
        console.log('process already running - terminate to debug')
        cb()
      }
    } else {
      cb()
    }
  }

  var profileProcess = function (args, system, cb) {
    if (!_runner.isProcessRunning(args.process)) {
      _runner.profile(system, args, cb)
    } else {
      console.log('process already running - terminate to profile')
      cb()
    }
  }

  var profileOptions = function (cmd) {
    cmd
      .option('--preview', 'Generates an SVG file, prerenders SVG inside HTML and outputs a PNG to the terminal (if possible) Depends on imagemagick (brew install imagemagick) If using iTerm 2.9+ image will be output to terminal Warning - depending on the amount of stacks this option can take tens of seconds')
      .option('--delay, -d <delay>', 'Milliseconds. Delay before tracing begins (or before stacks are processed in the Linux case), allows us to ignore initialisation stacks (e.g. module loading).')
      .option('--langs, -l', 'Color code the stacks by JS and C.')
      .option('--tiers, -t', 'Overrides langs, Color code frames by type')
      .option('--exclude, -x <list>', 'Exclude tiers or langs, comma seperated list',
        ['v8', 'regexp', 'nativeC', 'nativeJS', 'core', 'deps', 'app', 'js', 'c'])
      .option('--include <list>', 'Include tiers, Overwrites exclude. Really only useful for including the v8 tier (which is excluded by default).',
        ['v8', 'regexp', 'nativeC', 'nativeJS', 'core', 'deps', 'app', 'js', 'c'])
      .option('--theme <type>', 'Dark or Light theme, default: dark', ['dark', 'light'])
      .option('--stacks-only', 'Don\'t generate the flamegraph, only create the stacks output. If assigned to stacks output will come through stdout. Use this in combination with the -c gen argument to generate the flamegraph from raw stacks.',
        ['false', 'true', '-'])
      .option('--trace-info', 'Show output from dtrace or perf tools')
      .option('--cmd, -c', 'Run a "0x command", possible commands are help and gen.',
        ['help', 'gen'])
      .option('--timestamp-profiles', 'Adds the current timestamp to the Profile Folder\'s name minimizing collisions for in containerized environments')
  }

  var watchProcess = function (args, system, cb) {
    var err = null
    if (args.length === 1 || args[1] === 'all') {
      _runner.watchAll(system)
    } else if (args.length >= 2) {
      err = _runner.watch(system, args[1])
    }
    cb(err)
  }

  var unwatchProcess = function (args, system, cb) {
    var err = null
    if (args.length === 1 || args[1] === 'all') {
      _runner.unwatchAll(system)
    } else if (args.length >= 2) {
      err = _runner.unwatch(system, args[1])
    }
    cb(err)
  }

  var tailProcess = function (args, system, cb) {
    var err = null
    if (args.length === 1 || args[1] === 'all') {
      _runner.tailAll(system)
    } else if (args.length >= 2) {
      err = _runner.tail(system, args[1], args[2] || 0)
    }
    cb(err)
  }

  var untailProcess = function (args, system, cb) {
    var err = null
    if (args.length === 1 || args[1] === 'all') {
      _runner.untailAll(system)
    } else if (args.length >= 2) {
      err = _runner.untail(system, args[1])
    }
    cb(err)
  }

  var grepLogs = function (args, system, cb) {
    if (args[1]) {
      if (args[1].length === 1 || args[1][1] === 'all') {
        _runner.grepAll(system, args[1], cb)
      } else if (args[1].length > 1) {
        _runner.grep(system, args[1][1], args[1][0], cb)
      }
    } else {
      cb()
    }
  }

  var commands = [
    {
      command: 'ps',
      action: psList,
      description: 'list managed processes and containers'
    },
    {
      command: 'info',
      action: showInfo,
      description: 'list environment block injected into each process'
    },
    {
      command: 'stop',
      action: stopProcess,
      description: 'stop process instance and watcher'
    },
    {
      command: 'start',
      action: startProcess,
      description: 'start processe with watch'
    },
    {
      command: 'debug',
      action: debugProcess,
      description: 'start a process in debug mode'
    },
    {
      command: 'profile',
      action: profileProcess,
      description: 'start a process with the profiler (0x)'
    },
    {
      command: 'watch',
      action: watchProcess,
      description: 'turn on watching for a process'
    },
    {
      command: 'unwatch',
      action: unwatchProcess,
      description: 'turn off watching for a process'
    },
    {
      command: 'tail',
      action: tailProcess,
      description: 'tail output for all processes'
    },
    {
      command: 'untail',
      action: untailProcess,
      description: 'tail output for a specific processes'
    },
    {
      command: 'grep',
      action: grepLogs,
      description: 'searches logs for specific process or all logs'
    },
    {
      command: 'exit',
      action: stopProcess,
      description: 'exit system or a single process'
    }
  ]

  var inputStructure = function (command, type, description, action, system) {
    // structures the commands and creates the vorpal instances
    var cmd
    if (type !== null && command !== 'exit') {
      cmd = vorpal
        .command(command + type)
        .autocomplete(procList)
        .description(description)
        .action(function (args, cb) {
          if (command === 'profile') {
            return action(args, system, cb)
          }

          var opt = args.process // optional argument
          var arr = [command]

          if (command === 'send') {
            if (opt !== undefined) {
              for (var i = 0; i < opt.length; i++) {
                arr.push(opt[i])
              }
            }

            action(arr, system, cb)
          } else {
            if (opt !== undefined) {
              arr.push(opt)
            }

            action(arr, system, cb)
          }
        })

      if (command === 'profile') {
        profileOptions(cmd)
      }
    } else if (command === 'exit') {
      vorpal
        .command(command + type)
        .alias('quit')
        .autocomplete(procList)
        .description(description)
        .action(function (args, cb) {
          var opt = args.process // optional argument
          var arr = [command]

          if (opt !== undefined) {
            arr.push(opt)
          }

          action(arr, system, cb)
        })
    } else {
      cmd = vorpal
        .command(command)
        .description(description)
        .action(function (args, cb) {
          var arr = [command]
          action(arr, system, cb)
        })
    }
  }

  var repl = function (system) {
    vorpal.delimiter(' fuge>'.bold).show()

    var exit = vorpal.find('exit')
    if (exit) {
      exit.remove()
    }

    autoComp(system)

    vorpal.sigint(function () {
      stopSystem(system)
    })

    require('death')({uncaughtException: true})(function (signal, err) {
      console.log('ERROR: ')
      console.log(signal)
      console.log(err)
      console.log('cleanup:')
      stopSystem(system)
    })

    commands.forEach(function (com) {
      if (com.command === 'watch' || com.command === 'unwatch' ||
        com.command === 'info' || com.command === 'tail' || com.command === 'untail') {
        inputStructure(com.command, '[process]', com.description, com.action, system)
      } else if (com.command === 'debug') {
        inputStructure(com.command, '<process>', com.description, com.action, system)
      } else if (com.command === 'start' || com.command === 'stop' || com.command === 'exit' || com.command === 'grep') {
        inputStructure(com.command, '[process...]', com.description, com.action, system)
      } else if (com.command === 'profile') {
        inputStructure(com.command, '<process>', com.description, com.action, system)
      } else if (com.command === 'send') {
        inputStructure(com.command, '<process> <message>', com.description, com.action, system)
      } else {
        inputStructure(com.command, null, com.description, com.action, system)
      }
    })
  }

  var run = function (system) {
    _runner = require('fuge-runner')()

    console.log('starting shell..')
    repl(system)
  }

  var runSingleCommand = function (system, command) {
    _runner = require('fuge-runner')()

    require('death')({uncaughtException: true})(function () {
      stopSystem(system)
    })

    var commandName = command.split(' ')[0]
    var commandArgs = command.split(' ').slice(1)
    var cmd = _.find(commands, { command: commandName })
    if (!cmd) { console.error('Unknown command:', cmd); process.exit(0) }
    cmd.action([commandName, commandArgs], system, function (err) {
      if (err) { console.error(err) }
    })
  }

  return {
    run: run,
    runSingleCommand: runSingleCommand
  }
}

<commit_msg>added dns commands<commit_after>/*
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

'use strict'

var _ = require('lodash')
var Vorpal = require('vorpal')
var CliTable = require('cli-table')
var procList = []
var FugeDns = require('fuge-dns')
require('colors')

/**
 * fuge run -> executes through here - runs all and starts a log tail
 * hitting any key will stop the tail
 * need a command history
 */
module.exports = function () {
  var _config
  var _runner
  var _dns = null
  var vorpal = new Vorpal()

  var tableChars = {
    'top': '', 'top-mid': '', 'top-left': '', 'top-right': '',
    'bottom': '', 'bottom-mid': '', 'bottom-left': '', 'bottom-right': '',
    'left': '', 'left-mid': '', 'mid': '', 'mid-mid': '',
    'right': '', 'right-mid': '', 'middle': ''
  }

  var tableStyle = {
    'padding-left': 0,
    'padding-right': 0
  }

  var stopSystem = function (system) {
    _runner.stopAll(system, function () {
      if (_dns) { _dns.stop() }
      process.exit(0)
    })
  }

  var autoComp = function (system) {
    _.each(system.topology.containers, function (container) {
      procList.push(container.name)
    })
  }

  var psList = function (args, system, cb) {
    var table = new CliTable({chars: tableChars, style: tableStyle,
                              head: ['name'.white, 'type'.white, 'status'.white, 'watch'.white, 'tail'.white], colWidths: [30, 15, 15, 15, 15]})
    var procs = _runner.processes()

    _.each(system.topology.containers, function (container) {
      if (container.type === 'docker' && _config.runDocker === false) {
        table.push([container.name.gray, container.type.gray, 'not managed'.gray, '', ''])
      } else {
        var procKey = _.find(_.keys(procs), function (key) { return procs[key].identifier === container.name })
        if (procKey) {
          var proc = procs[procKey]
          table.push([container.name.green,
                      container.type.green,
                      container.profiling ? 'profiling'.green : 'running'.green,
                      proc.monitor ? 'yes'.green : 'no'.red,
                      proc.tail ? 'yes'.green : 'no'.red])
        } else {
          table.push([container.name.red,
                      container.type.red,
                      'stopped'.red,
                      container.monitor ? 'yes'.green : 'no'.red,
                      container.tail ? 'yes'.green : 'no'.red])
                     //  '0'.red])
        }
      }
    })
    if (_dns) {
      table.push(['dns'.green,
                  'internal'.green,
                  'running'.green,
                  'no'.red,
                  'no'.red])
    }
    console.log(table.toString())
    cb()
  }

  var showInfo = function (args, system, cb) {
    if (args.length === 2) {
      _runner.preview(system, args[1], function (err, command) {
        if (err) { cb(err) }
        if (command && command.detail) {
          var env = ''
          console.log('command: ' + command.detail.cmd)
          console.log('directory: ' + command.detail.cwd)
          _.each(_.keys(command.detail.environment), function (key) {
            env += '  ' + key + '=' + command.detail.environment[key] + '\n'
          })
          console.log('environment:\n' + env)
        } else {
          console.log('not managed or unknown process')
        }
        cb()
      })
    } else {
      cb('process not specified')
    }
  }

  var stopProcess = function (args, system, cb) {
    if (args.length === 1 && args[0] === 'exit') {
      stopSystem(system)
    } else if (args.length === 1 || args[1][0] === 'all') {
      _runner.stopAll(system, cb)
    } else {
      for (var i = 0; i < args[1].length; i++) {
        _runner.stop(system, args[1][i], 1, cb)
      }
    }
  }

  var startProcess = function (args, system, cb) {
    if (args.length === 1 || args[1][0] === 'all') {
      _runner.startAll(system, args[2] || 1, cb)
    } else {
      for (var i = 0; i < args[1].length; i++) {
        _runner.start(system, args[1][i], 1, cb)
      }
    }
  }

  var debugProcess = function (args, system, cb) {
    if (args.length === 2) {
      if (!_runner.isProcessRunning(args[1])) {
        _runner.debug(system, args[1], cb)
      } else {
        console.log('process already running - terminate to debug')
        cb()
      }
    } else {
      cb()
    }
  }

  var profileProcess = function (args, system, cb) {
    if (!_runner.isProcessRunning(args.process)) {
      _runner.profile(system, args, cb)
    } else {
      console.log('process already running - terminate to profile')
      cb()
    }
  }

  var profileOptions = function (cmd) {
    cmd
      .option('--preview', 'Generates an SVG file, prerenders SVG inside HTML and outputs a PNG to the terminal (if possible) Depends on imagemagick (brew install imagemagick) If using iTerm 2.9+ image will be output to terminal Warning - depending on the amount of stacks this option can take tens of seconds')
      .option('--delay, -d <delay>', 'Milliseconds. Delay before tracing begins (or before stacks are processed in the Linux case), allows us to ignore initialisation stacks (e.g. module loading).')
      .option('--langs, -l', 'Color code the stacks by JS and C.')
      .option('--tiers, -t', 'Overrides langs, Color code frames by type')
      .option('--exclude, -x <list>', 'Exclude tiers or langs, comma seperated list',
        ['v8', 'regexp', 'nativeC', 'nativeJS', 'core', 'deps', 'app', 'js', 'c'])
      .option('--include <list>', 'Include tiers, Overwrites exclude. Really only useful for including the v8 tier (which is excluded by default).',
        ['v8', 'regexp', 'nativeC', 'nativeJS', 'core', 'deps', 'app', 'js', 'c'])
      .option('--theme <type>', 'Dark or Light theme, default: dark', ['dark', 'light'])
      .option('--stacks-only', 'Don\'t generate the flamegraph, only create the stacks output. If assigned to stacks output will come through stdout. Use this in combination with the -c gen argument to generate the flamegraph from raw stacks.',
        ['false', 'true', '-'])
      .option('--trace-info', 'Show output from dtrace or perf tools')
      .option('--cmd, -c', 'Run a "0x command", possible commands are help and gen.',
        ['help', 'gen'])
      .option('--timestamp-profiles', 'Adds the current timestamp to the Profile Folder\'s name minimizing collisions for in containerized environments')
  }

  var watchProcess = function (args, system, cb) {
    var err = null
    if (args.length === 1 || args[1] === 'all') {
      _runner.watchAll(system)
    } else if (args.length >= 2) {
      err = _runner.watch(system, args[1])
    }
    cb(err)
  }

  var unwatchProcess = function (args, system, cb) {
    var err = null
    if (args.length === 1 || args[1] === 'all') {
      _runner.unwatchAll(system)
    } else if (args.length >= 2) {
      err = _runner.unwatch(system, args[1])
    }
    cb(err)
  }

  var tailProcess = function (args, system, cb) {
    var err = null
    if (args.length === 1 || args[1] === 'all') {
      _runner.tailAll(system)
    } else if (args.length >= 2) {
      err = _runner.tail(system, args[1], args[2] || 0)
    }
    cb(err)
  }

  var untailProcess = function (args, system, cb) {
    var err = null
    if (args.length === 1 || args[1] === 'all') {
      _runner.untailAll(system)
    } else if (args.length >= 2) {
      err = _runner.untail(system, args[1])
    }
    cb(err)
  }

  var grepLogs = function (args, system, cb) {
    if (args[1]) {
      if (args[1].length === 1 || args[1][1] === 'all') {
        _runner.grepAll(system, args[1], cb)
      } else if (args[1].length > 1) {
        _runner.grep(system, args[1][1], args[1][0], cb)
      }
    } else {
      cb()
    }
  }

  var printZone = function (args, system, cb) {
    var table = new CliTable({chars: tableChars, style: tableStyle,
                              head: ['type'.white, 'domain'.white, 'address'.white, 'port'.white], colWidths: [10, 40, 20, 10]})

    var list = _dns.listRecords()
    _.each(list, function (entry) {
      if (entry.record._type === 'A') {
        table.push(['A'.white,
                    entry.domain.white,
                    entry.record.target.white,
                    '-'.white])
      }
      if (entry.record._type === 'SRV') {
        table.push(['SRV'.white,
                    entry.domain.white,
                    entry.record.target.white,
                    entry.record.port.white])
      }
    })
    console.log(table.toString())
    cb()

  }

  var commands = [
    {
      command: 'ps',
      action: psList,
      description: 'list managed processes and containers'
    },
    {
      command: 'info',
      action: showInfo,
      description: 'list environment block injected into each process'
    },
    {
      command: 'stop',
      action: stopProcess,
      description: 'stop process instance and watcher'
    },
    {
      command: 'start',
      action: startProcess,
      description: 'start processe with watch'
    },
    {
      command: 'debug',
      action: debugProcess,
      description: 'start a process in debug mode'
    },
    {
      command: 'profile',
      action: profileProcess,
      description: 'start a process with the profiler (0x)'
    },
    {
      command: 'watch',
      action: watchProcess,
      description: 'turn on watching for a process'
    },
    {
      command: 'unwatch',
      action: unwatchProcess,
      description: 'turn off watching for a process'
    },
    {
      command: 'tail',
      action: tailProcess,
      description: 'tail output for all processes'
    },
    {
      command: 'untail',
      action: untailProcess,
      description: 'tail output for a specific processes'
    },
    {
      command: 'grep',
      action: grepLogs,
      description: 'searches logs for specific process or all logs'
    },
    {
      command: 'zone',
      action: printZone,
      description: 'displays dns zone information if enabled'
    },
    {
      command: 'exit',
      action: stopProcess,
      description: 'exit system or a single process'
    }
  ]

  var inputStructure = function (command, type, description, action, system) {
    // structures the commands and creates the vorpal instances
    var cmd
    if (type !== null && command !== 'exit') {
      cmd = vorpal
        .command(command + type)
        .autocomplete(procList)
        .description(description)
        .action(function (args, cb) {
          if (command === 'profile') {
            return action(args, system, cb)
          }

          var opt = args.process // optional argument
          var arr = [command]

          if (command === 'send') {
            if (opt !== undefined) {
              for (var i = 0; i < opt.length; i++) {
                arr.push(opt[i])
              }
            }

            action(arr, system, cb)
          } else {
            if (opt !== undefined) {
              arr.push(opt)
            }

            action(arr, system, cb)
          }
        })

      if (command === 'profile') {
        profileOptions(cmd)
      }
    } else if (command === 'exit') {
      vorpal
        .command(command + type)
        .alias('quit')
        .autocomplete(procList)
        .description(description)
        .action(function (args, cb) {
          var opt = args.process // optional argument
          var arr = [command]

          if (opt !== undefined) {
            arr.push(opt)
          }

          action(arr, system, cb)
        })
    } else {
      cmd = vorpal
        .command(command)
        .description(description)
        .action(function (args, cb) {
          var arr = [command]
          action(arr, system, cb)
        })
    }
  }

  var repl = function (system) {
    vorpal.delimiter(' fuge>'.bold).show()

    var exit = vorpal.find('exit')
    if (exit) {
      exit.remove()
    }

    autoComp(system)

    vorpal.sigint(function () {
      stopSystem(system)
    })

    require('death')({uncaughtException: true})(function (signal, err) {
      console.log('ERROR: ')
      console.log(signal)
      console.log(err)
      console.log('cleanup:')
      stopSystem(system)
    })

    commands.forEach(function (com) {
      if (com.command === 'watch' || com.command === 'unwatch' ||
        com.command === 'info' || com.command === 'tail' || com.command === 'untail') {
        inputStructure(com.command, '[process]', com.description, com.action, system)
      } else if (com.command === 'debug') {
        inputStructure(com.command, '<process>', com.description, com.action, system)
      } else if (com.command === 'start' || com.command === 'stop' || com.command === 'exit' || com.command === 'grep') {
        inputStructure(com.command, '[process...]', com.description, com.action, system)
      } else if (com.command === 'profile') {
        inputStructure(com.command, '<process>', com.description, com.action, system)
      } else if (com.command === 'send') {
        inputStructure(com.command, '<process> <message>', com.description, com.action, system)
      } else {
        inputStructure(com.command, null, com.description, com.action, system)
      }
    })
  }

  var run = function (system) {
    _runner = require('fuge-runner')()

    if (system.global.dns_enabled) {
      console.log('starting fuge dns [' + system.global.dns_host + ':' + system.global.dns_port + ']..')
      _dns = FugeDns({host: system.global.dns_host, port: system.global.dns_port})
      _dns.addZone(system.global.dns)
      _dns.start(function () {
        console.log('ok')
        console.log('starting shell..')
        repl(system)
      })
    } else {
      console.log('starting shell..')
      repl(system)
    }
  }

  var runSingleCommand = function (system, command) {
    _runner = require('fuge-runner')()

    require('death')({uncaughtException: true})(function () {
      stopSystem(system)
    })

    var commandName = command.split(' ')[0]
    var commandArgs = command.split(' ').slice(1)
    var cmd = _.find(commands, { command: commandName })
    if (!cmd) { console.error('Unknown command:', cmd); process.exit(0) }
    cmd.action([commandName, commandArgs], system, function (err) {
      if (err) { console.error(err) }
    })
  }

  return {
    run: run,
    runSingleCommand: runSingleCommand
  }
}

<|endoftext|>


<commit_before>var Shell = Shell || {
    commands: {},

    // I/O functions

    rawWrite: function(s, to, style, from){
	s = s.replace(/\n/g, "
");
	s = "
" + s + "
";
	if (to){
	    s = "/w " + to.split(" ", 1)[0] + " " + s;
	}
	sendChat((typeof(from) == typeof("") ? from : "Shell"), s);
    },

    write: function(s, to, style, from){
	Shell.rawWrite(s.replace(/</g, "<").replace(/>/g, ">"), to, style, from);
    },

    writeAndLog: function(s, to){
	Shell.write(s, to);
	_.each(s.split("\n"), log);
    },

    writeErr: function(s){
	Shell.writeAndLog(s, "gm");
    },

    // command registration

    registerCommand: function(cmd, sig, desc, fn){
	// error checking
	if (!cmd){
	    var errMsg = "Error: Cannot register empty command";
	    if (sig){
		errMsg += " (signature: " + sig + ")";
	    }
	    Shell.writeErr(errMsg);
	    return;
	}
	if (!fn){
	    Shell.writeErr("Error: Cannot register command \"" + cmd + "\" without a callback");
	    return;
	}

	// fix up the arguments if necessary
	if (cmd.charAt(0) != '!'){
	    cmd = "!" + cmd;
	}
	if (!sig){
	    sig = cmd;
	}

	// check for already-registered command of the same name
	if (Shell.commands[cmd]){
	    if ((Shell.commands[cmd].signature != sig) || (Shell.commands[cmd].description != desc) || (Shell.commands[cmd].callback != fn)){
		Shell.writeErr("Error: Command with name \"" + cmd + "\" already registered");
	    }
	    return;
	}

	// register command
	Shell.commands[cmd] = {
	    signature:		sig,
	    description:	desc,
	    callback:		fn
	};
    },

    unregisterCommand: function(cmd){
	// error checking
	if (!cmd){
	    Shell.writeErr("Error: Cannot unregister empty command");
	    return;
	}

	// fix up argument if necessary
	if (cmd.charAt(0) != '!'){
	    cmd = "!" + cmd;
	}

	// verify command exists
	if (!Shell.commands[cmd]){
	    Shell.writeErr("Error: Command \"" + cmd + "\" not registered");
	    return;
	}

	// unregister command
	delete Shell.commands[cmd];
	if (state.Shell.userPermissions[cmd]){
	    delete state.Shell.userPermissions[cmd];
	}
    },

    // utility functions

    tokenize: function(s){
	var retval = [];
	var curTok = "";
	var quote = false;
	while (s.length > 0){
	    if (quote){
		// in quoted string; look for terminating quote
		var idx = s.indexOf(quote);
		if (idx < 0){
		    return "Error: Unmatched " + quote;
		}
		curTok += s.substr(0, idx);
		s = s.substr(idx + 1);
		quote = "";
		continue;
	    }
	    var idx = s.search(/[\s'"]/);
	    if (idx < 0){
		// no more quotes or whitespace, just add the rest of the string to the current token and terminate
		curTok += s;
		if (curTok){
		    retval.push(curTok);
		}
		break;
	    }
	    curTok += s.substr(0, idx);
	    var c = s.charAt(idx);
	    s = s.substr(idx + 1);
	    if ((c == "'") || (c == '"')){
		// got a quote; start quoted string
		quote = c;
	    }
	    else{
		// got whitespace; push current token and start looking for a new token
		if (curTok){
		    retval.push(curTok);
		}
		curTok = "";
	    }
	}
	return retval;
    },

    // built-in commands

    helpCommand: function(args, msg){
	var commandKeys = [];
	for (var cmd in Shell.commands){
	    if (Shell.hasPermission(msg, cmd)){
		commandKeys.push(cmd);
	    }
	}
	commandKeys.sort();
	var helpMsg = "";
	for (var i = 0; i < commandKeys.length; i++){
	    helpMsg += (i > 0 ? "\n" : "") + Shell.commands[commandKeys[i]].signature;
	    if (Shell.commands[commandKeys[i]].description){
		helpMsg += "\n\t" + Shell.commands[commandKeys[i]].description;
	    }
	}
	if (helpMsg){
	    Shell.write("Shell Commands:", msg.who);
	    Shell.write(helpMsg, msg.who, "font-size: small");
	}
    },

    permissionCommand: function(args, msg){
	function showHelp(){
	    Shell.write(args[0] + " add <command> [player]", msg.who);
	    Shell.write("\tAdd permission for specified player to execute specified command.", msg.who);
	    Shell.write("\tIf no player is specified, adds world-execute permission.", msg.who);
	    Shell.write(args[0] + " remove <command> [player]", msg.who);
	    Shell.write("\tRemove permission for specified player to execute specified command.", msg.who);
	    Shell.write("\tIf no player is specified, removes world-execute permission.", msg.who);
	}

	if ((args.length > 1) && ((args[1] == "-h") || (args[1] == "--help") || (args[1] == "help"))){
	    showHelp();
	    return;
	}
	if (args.length < 3){
	    Shell.write(args[0] + " requires at least two arguments: add|remove and a command", msg.who);
	    showHelp();
	    return;
	}
	if (!args[2]){
	    Shell.write("Unrecognized command: \"\"", msg.who);
	    showHelp();
	    return;
	}
	var cmd = args[2];
	if (cmd.charAt(0) != '!'){
	    cmd = "!" + cmd;
	}
	if (!Shell.commands[cmd]){
	    Shell.write("Unrecognized command: " + cmd, msg.who);
	    return;
	}

	var playerId = (args.length > 3 ? args[3] : "");
	if (playerId){
	    var players = _.union(findObjs({_type: "player", _displayname: playerId}), findObjs({_type: "player", _d20userid: playerId}));
	    if (players.length < 1){
		Shell.write("Unable to find user matching " + playerId, msg.who);
		players = findObjs({_type: "player"});
	    }
	    if (players.length > 1){
		Shell.write("Found more than one user matching " + playerId, msg.who);
	    }
	    if (players.length != 1){
		Shell.write("Please try again using one of: " + (_.map(players, function(p){ return p.get('_d20userid'); })).join(", "), msg.who);
		return;
	    }
	    playerId = players[0].id;
	}

	switch (args[1]){
	case "add":
	    // add userId to state.Shell.userPermissions[cmd] (if not already present), making sure to keep the list sorted
	    if (!state.Shell.userPermissions[cmd]){
		state.Shell.userPermissions[cmd] = [];
	    }
	    if (_.contains(state.Shell.userPermissions[cmd], playerId)){ return; }
	    state.Shell.userPermissions[cmd].splice(_.sortedIndex(state.Shell.userPermissions[cmd], playerId), 0, playerId);
	    break;
	case "remove":
	    // remove playerId from state.Shell.userPermissions[cmd] (if present)
	    if (!state.Shell.userPermissions[cmd]){ return; }
	    var idx = state.Shell.userPermissions[cmd].indexOf(playerId);
	    if (idx < 0){ return; }
	    state.Shell.userPermissions[cmd].splice(idx, 1);
	    break;
	default:
	    Shell.write("Unrecognized operation: " + args[1], msg.who);
	    showHelp();
	    return;
	}
    },

    // internal functions

    isFromGM: function(msg){
	// try to determine if message sender is GM from msg
	var player = getObj("player", msg.playerid);
	if ((player.get('speakingas') == "") || (player.get('speakingas') == "player|" + msg.playerid)){
	    return msg.who != player.get('_displayname');
	}

	// couldn't figure it out from msg; try to use isGM if it exists
	// we'd try this first if there were a way to tell the difference between "player not GM" and "player GM status unknown"
	if ((typeof(isGM) != "undefined") && (isGM) && (_.isFunction(isGM))){
	    return isGM(msg.playerid);
	}
    },

    hasPermission: function(msg, cmd){
	if (Shell.isFromGM(msg)){ return true; }
	if (state.Shell.userPermissions[cmd]){
	    if (_.contains(state.Shell.userPermissions[cmd], msg.playerid, true)){ return true; }
	    if (_.contains(state.Shell.userPermissions[cmd], "", true)){ return true; }
	}
/////
//
	//maybe add handling for groups
//
/////
	return false;
    },

    handleChatMessage: function(msg){
	if (msg.type != "api"){ return; }

	// tokenize command string
	var tokens = Shell.tokenize(msg.content);
	if (typeof(tokens) == typeof("")){
	    Shell.writeAndLog(tokens, msg.who);
	    return;
	}
	if (tokens.length <= 0){ return; }

	if (!Shell.commands[tokens[0]]){
	    // ignore unregistered command
	    return;
	}

	if (!Shell.hasPermission(msg, tokens[0])){
	    Shell.write("Error: You do not have permission to execute command " + tokens[0]);
	    return;
	}

	// execute command callback
	Shell.commands[tokens[0]].callback(tokens, _.clone(msg));
    },

    init: function(){
	// initialize stored state
	state.Shell = state.Shell || {};
	state.Shell.userPermissions = state.Shell.userPermissions || {};

	// register built-in commands
	Shell.registerCommand("!help", "!help", "Show this help message", Shell.helpCommand);
	state.Shell.userPermissions["!help"] = [""];
	Shell.registerCommand("!shell-permission", "!shell-permission add|remove <command> [player]",
			    "Add or remove permission for specified command", Shell.permissionCommand);

	// register chat event handler
	on("chat:message", Shell.handleChatMessage);
    }
};

on("ready", Shell.init);
<commit_msg>Deal with "more than one matching player" case before "no matching player" case so the "list all players" logic in the latter case doesn't trigger the warning message from the former case<commit_after>var Shell = Shell || {
    commands: {},

    // I/O functions

    rawWrite: function(s, to, style, from){
	s = s.replace(/\n/g, "
");
	s = "
" + s + "
";
	if (to){
	    s = "/w " + to.split(" ", 1)[0] + " " + s;
	}
	sendChat((typeof(from) == typeof("") ? from : "Shell"), s);
    },

    write: function(s, to, style, from){
	Shell.rawWrite(s.replace(/</g, "<").replace(/>/g, ">"), to, style, from);
    },

    writeAndLog: function(s, to){
	Shell.write(s, to);
	_.each(s.split("\n"), log);
    },

    writeErr: function(s){
	Shell.writeAndLog(s, "gm");
    },

    // command registration

    registerCommand: function(cmd, sig, desc, fn){
	// error checking
	if (!cmd){
	    var errMsg = "Error: Cannot register empty command";
	    if (sig){
		errMsg += " (signature: " + sig + ")";
	    }
	    Shell.writeErr(errMsg);
	    return;
	}
	if (!fn){
	    Shell.writeErr("Error: Cannot register command \"" + cmd + "\" without a callback");
	    return;
	}

	// fix up the arguments if necessary
	if (cmd.charAt(0) != '!'){
	    cmd = "!" + cmd;
	}
	if (!sig){
	    sig = cmd;
	}

	// check for already-registered command of the same name
	if (Shell.commands[cmd]){
	    if ((Shell.commands[cmd].signature != sig) || (Shell.commands[cmd].description != desc) || (Shell.commands[cmd].callback != fn)){
		Shell.writeErr("Error: Command with name \"" + cmd + "\" already registered");
	    }
	    return;
	}

	// register command
	Shell.commands[cmd] = {
	    signature:		sig,
	    description:	desc,
	    callback:		fn
	};
    },

    unregisterCommand: function(cmd){
	// error checking
	if (!cmd){
	    Shell.writeErr("Error: Cannot unregister empty command");
	    return;
	}

	// fix up argument if necessary
	if (cmd.charAt(0) != '!'){
	    cmd = "!" + cmd;
	}

	// verify command exists
	if (!Shell.commands[cmd]){
	    Shell.writeErr("Error: Command \"" + cmd + "\" not registered");
	    return;
	}

	// unregister command
	delete Shell.commands[cmd];
	if (state.Shell.userPermissions[cmd]){
	    delete state.Shell.userPermissions[cmd];
	}
    },

    // utility functions

    tokenize: function(s){
	var retval = [];
	var curTok = "";
	var quote = false;
	while (s.length > 0){
	    if (quote){
		// in quoted string; look for terminating quote
		var idx = s.indexOf(quote);
		if (idx < 0){
		    return "Error: Unmatched " + quote;
		}
		curTok += s.substr(0, idx);
		s = s.substr(idx + 1);
		quote = "";
		continue;
	    }
	    var idx = s.search(/[\s'"]/);
	    if (idx < 0){
		// no more quotes or whitespace, just add the rest of the string to the current token and terminate
		curTok += s;
		if (curTok){
		    retval.push(curTok);
		}
		break;
	    }
	    curTok += s.substr(0, idx);
	    var c = s.charAt(idx);
	    s = s.substr(idx + 1);
	    if ((c == "'") || (c == '"')){
		// got a quote; start quoted string
		quote = c;
	    }
	    else{
		// got whitespace; push current token and start looking for a new token
		if (curTok){
		    retval.push(curTok);
		}
		curTok = "";
	    }
	}
	return retval;
    },

    // built-in commands

    helpCommand: function(args, msg){
	var commandKeys = [];
	for (var cmd in Shell.commands){
	    if (Shell.hasPermission(msg, cmd)){
		commandKeys.push(cmd);
	    }
	}
	commandKeys.sort();
	var helpMsg = "";
	for (var i = 0; i < commandKeys.length; i++){
	    helpMsg += (i > 0 ? "\n" : "") + Shell.commands[commandKeys[i]].signature;
	    if (Shell.commands[commandKeys[i]].description){
		helpMsg += "\n\t" + Shell.commands[commandKeys[i]].description;
	    }
	}
	if (helpMsg){
	    Shell.write("Shell Commands:", msg.who);
	    Shell.write(helpMsg, msg.who, "font-size: small");
	}
    },

    permissionCommand: function(args, msg){
	function showHelp(){
	    Shell.write(args[0] + " add <command> [player]", msg.who);
	    Shell.write("\tAdd permission for specified player to execute specified command.", msg.who);
	    Shell.write("\tIf no player is specified, adds world-execute permission.", msg.who);
	    Shell.write(args[0] + " remove <command> [player]", msg.who);
	    Shell.write("\tRemove permission for specified player to execute specified command.", msg.who);
	    Shell.write("\tIf no player is specified, removes world-execute permission.", msg.who);
	}

	if ((args.length > 1) && ((args[1] == "-h") || (args[1] == "--help") || (args[1] == "help"))){
	    showHelp();
	    return;
	}
	if (args.length < 3){
	    Shell.write(args[0] + " requires at least two arguments: add|remove and a command", msg.who);
	    showHelp();
	    return;
	}
	if (!args[2]){
	    Shell.write("Unrecognized command: \"\"", msg.who);
	    showHelp();
	    return;
	}
	var cmd = args[2];
	if (cmd.charAt(0) != '!'){
	    cmd = "!" + cmd;
	}
	if (!Shell.commands[cmd]){
	    Shell.write("Unrecognized command: " + cmd, msg.who);
	    return;
	}

	var playerId = (args.length > 3 ? args[3] : "");
	if (playerId){
	    var players = _.union(findObjs({_type: "player", _displayname: playerId}), findObjs({_type: "player", _d20userid: playerId}));
	    if (players.length > 1){
		Shell.write("Found more than one user matching " + playerId, msg.who);
	    }
	    if (players.length < 1){
		Shell.write("Unable to find user matching " + playerId, msg.who);
		players = findObjs({_type: "player"});
	    }
	    if (players.length != 1){
		Shell.write("Please try again using one of: " + (_.map(players, function(p){ return p.get('_d20userid'); })).join(", "), msg.who);
		return;
	    }
	    playerId = players[0].id;
	}

	switch (args[1]){
	case "add":
	    // add userId to state.Shell.userPermissions[cmd] (if not already present), making sure to keep the list sorted
	    if (!state.Shell.userPermissions[cmd]){
		state.Shell.userPermissions[cmd] = [];
	    }
	    if (_.contains(state.Shell.userPermissions[cmd], playerId)){ return; }
	    state.Shell.userPermissions[cmd].splice(_.sortedIndex(state.Shell.userPermissions[cmd], playerId), 0, playerId);
	    break;
	case "remove":
	    // remove playerId from state.Shell.userPermissions[cmd] (if present)
	    if (!state.Shell.userPermissions[cmd]){ return; }
	    var idx = state.Shell.userPermissions[cmd].indexOf(playerId);
	    if (idx < 0){ return; }
	    state.Shell.userPermissions[cmd].splice(idx, 1);
	    break;
	default:
	    Shell.write("Unrecognized operation: " + args[1], msg.who);
	    showHelp();
	    return;
	}
    },

    // internal functions

    isFromGM: function(msg){
	// try to determine if message sender is GM from msg
	var player = getObj("player", msg.playerid);
	if ((player.get('speakingas') == "") || (player.get('speakingas') == "player|" + msg.playerid)){
	    return msg.who != player.get('_displayname');
	}

	// couldn't figure it out from msg; try to use isGM if it exists
	// we'd try this first if there were a way to tell the difference between "player not GM" and "player GM status unknown"
	if ((typeof(isGM) != "undefined") && (isGM) && (_.isFunction(isGM))){
	    return isGM(msg.playerid);
	}
    },

    hasPermission: function(msg, cmd){
	if (Shell.isFromGM(msg)){ return true; }
	if (state.Shell.userPermissions[cmd]){
	    if (_.contains(state.Shell.userPermissions[cmd], msg.playerid, true)){ return true; }
	    if (_.contains(state.Shell.userPermissions[cmd], "", true)){ return true; }
	}
/////
//
	//maybe add handling for groups
//
/////
	return false;
    },

    handleChatMessage: function(msg){
	if (msg.type != "api"){ return; }

	// tokenize command string
	var tokens = Shell.tokenize(msg.content);
	if (typeof(tokens) == typeof("")){
	    Shell.writeAndLog(tokens, msg.who);
	    return;
	}
	if (tokens.length <= 0){ return; }

	if (!Shell.commands[tokens[0]]){
	    // ignore unregistered command
	    return;
	}

	if (!Shell.hasPermission(msg, tokens[0])){
	    Shell.write("Error: You do not have permission to execute command " + tokens[0]);
	    return;
	}

	// execute command callback
	Shell.commands[tokens[0]].callback(tokens, _.clone(msg));
    },

    init: function(){
	// initialize stored state
	state.Shell = state.Shell || {};
	state.Shell.userPermissions = state.Shell.userPermissions || {};

	// register built-in commands
	Shell.registerCommand("!help", "!help", "Show this help message", Shell.helpCommand);
	state.Shell.userPermissions["!help"] = [""];
	Shell.registerCommand("!shell-permission", "!shell-permission add|remove <command> [player]",
			    "Add or remove permission for specified command", Shell.permissionCommand);

	// register chat event handler
	on("chat:message", Shell.handleChatMessage);
    }
};

on("ready", Shell.init);
<|endoftext|>


<commit_before>(function( root, factory ) {

  if (typeof define == 'function' && define.amd) {
    define(factory);
  } else if (typeof exports == 'object') {
    module.exports = factory();
  } else {
    root.short = factory();
  }

})( this, function() {
  "use strict";

  var filters = [];

  var short = function short(text) {
    return short.filter( text );
  };

  short.addFilter = function addFilter( pattern, fn ) {
    filters.push([pattern, fn]);
  };

  short.filter = function filter( text ) {
    var len = filters.length,
        i = 0,
        f, res;

    for (; i<len; i++) {
      f = filters[i];

      if (f[0].test(text)) {
        res = f[1](text);
        if (res !== false) {
          text = res;
        }
      }
    }

    return text;
  };

  /* Builtin Filters */

  // short numbers
  short.addFilter(/^\d+(?:\.\d+)?$/, (function() {
    var units = [
          { suffix: "P", factor: 1e15 },
          { suffix: "T", factor: 1e12 },
          { suffix: "G", factor: 1e9 },
          { suffix: "M", factor: 1e6 },
          { suffix: "k", factor: 1e3 },
        ],

        unitsLen = units.length;

    for (var i=0; i<unitsLen; i++) {
      // if a number is higher than this number, we use this prefix. For 'k',
      // it's 600 (0.6k), for 'M' it's 600'000, etc.
      units[i].threshold = units[i].factor/10 * 6;
    }

    function roundOneDecimal( n ) {
      return (0|(n * 10)) / 10;
    }

    return function( text ) {
      var n = +text,
          unit;

      if (isNaN(n)) {
        return false;
      }

      for (var i=0; i<unitsLen; i++) {
        unit = units[i];

        if (n > unit.threshold) {
          return "" + roundOneDecimal(n/unit.factor) + unit.suffix;
        }
      }

      return "" + roundOneDecimal(n);
    };
  })());

  return short;

});
<commit_msg>License header added<commit_after>/**! github.com/bfontaine/shortjs -- MIT license */
(function( root, factory ) {

  if (typeof define == 'function' && define.amd) {
    define(factory);
  } else if (typeof exports == 'object') {
    module.exports = factory();
  } else {
    root.short = factory();
  }

})( this, function() {
  "use strict";

  var filters = [];

  var short = function short(text) {
    return short.filter( text );
  };

  short.addFilter = function addFilter( pattern, fn ) {
    filters.push([pattern, fn]);
  };

  short.filter = function filter( text ) {
    var len = filters.length,
        i = 0,
        f, res;

    for (; i<len; i++) {
      f = filters[i];

      if (f[0].test(text)) {
        res = f[1](text);
        if (res !== false) {
          text = res;
        }
      }
    }

    return text;
  };

  /* Builtin Filters */

  // short numbers
  short.addFilter(/^\d+(?:\.\d+)?$/, (function() {
    var units = [
          { suffix: "P", factor: 1e15 },
          { suffix: "T", factor: 1e12 },
          { suffix: "G", factor: 1e9 },
          { suffix: "M", factor: 1e6 },
          { suffix: "k", factor: 1e3 },
        ],

        unitsLen = units.length;

    for (var i=0; i<unitsLen; i++) {
      // if a number is higher than this number, we use this prefix. For 'k',
      // it's 600 (0.6k), for 'M' it's 600'000, etc.
      units[i].threshold = units[i].factor/10 * 6;
    }

    function roundOneDecimal( n ) {
      return (0|(n * 10)) / 10;
    }

    return function( text ) {
      var n = +text,
          unit;

      if (isNaN(n)) {
        return false;
      }

      for (var i=0; i<unitsLen; i++) {
        unit = units[i];

        if (n > unit.threshold) {
          return "" + roundOneDecimal(n/unit.factor) + unit.suffix;
        }
      }

      return "" + roundOneDecimal(n);
    };
  })());

  return short;

});
<|endoftext|>


<commit_before>import toBeEven from './toBeEven';
import toBeTrue from './toBeTrue';
import toBeFalse from './toBeFalse';
import toContainValue from './toContainValue';
import toContainValues from './toContainValues';
import toBeArray from './toBeArray';
import toEqualCaseInsensitive from './toEqualCaseInsensitive';
import toStartWith from './toStartWith';
import toBeNegative from './toBeNegative';
import toBeOneOf from './toBeOneOf';
import toContainKey from './toContainKey';
import toBeString from './toBeString';
import toBeExtensible from './toBeExtensible';
import toBeWithin from './toBeWithin';
import toIncludeMultiple from './toIncludeMultiple';
import toEndWith from './toEndWith';
import toBeFrozen from './toBeFrozen';
import toBeObject from './toBeObject';
import toContainAllKeys from './toContainAllKeys';
import toContainAnyKeys from './toContainAnyKeys';
import toContainKeys from './toContainKeys';
import toBeFinite from './toBeFinite';
import toIncludeAnyMembers from './toIncludeAnyMembers';
import toIncludeAllMembers from './toIncludeAllMembers';
import toBeNaN from './toBeNaN';
import toBePositive from './toBePositive';
import toInclude from './toInclude';
import toBeBoolean from './toBeBoolean';
import toBeFunction from './toBeFunction';
import toBeNumber from './toBeNumber';
import toBeOdd from './toBeOdd';

export default [
  toBeEven,
  toBeTrue,
  toBeFalse,
  toContainValue,
  toContainValues,
  toBeArray,
  toEqualCaseInsensitive,
  toStartWith,
  toBeNegative,
  toBeOneOf,
  toContainKey,
  toBeString,
  toBeExtensible,
  toBeWithin,
  toIncludeMultiple,
  toEndWith,
  toBeFrozen,
  toBeObject,
  toContainAllKeys,
  toContainAnyKeys,
  toContainKeys,
  toBeFinite,
  toIncludeAnyMembers,
  toIncludeAllMembers,
  toBeNaN,
  toBePositive,
  toInclude,
  toBeBoolean,
  toBeFunction,
  toBeNumber,
  toBeOdd
].reduce((acc, matcher) => ({ ...acc, ...matcher }), {});
<commit_msg>Add toContainAllValues export<commit_after>import toBeEven from './toBeEven';
import toBeTrue from './toBeTrue';
import toBeFalse from './toBeFalse';
import toContainValue from './toContainValue';
import toContainValues from './toContainValues';
import toBeArray from './toBeArray';
import toEqualCaseInsensitive from './toEqualCaseInsensitive';
import toStartWith from './toStartWith';
import toBeNegative from './toBeNegative';
import toBeOneOf from './toBeOneOf';
import toContainKey from './toContainKey';
import toBeString from './toBeString';
import toBeExtensible from './toBeExtensible';
import toBeWithin from './toBeWithin';
import toIncludeMultiple from './toIncludeMultiple';
import toEndWith from './toEndWith';
import toBeFrozen from './toBeFrozen';
import toBeObject from './toBeObject';
import toContainAllKeys from './toContainAllKeys';
import toContainAnyKeys from './toContainAnyKeys';
import toContainKeys from './toContainKeys';
import toBeFinite from './toBeFinite';
import toIncludeAnyMembers from './toIncludeAnyMembers';
import toIncludeAllMembers from './toIncludeAllMembers';
import toBeNaN from './toBeNaN';
import toBePositive from './toBePositive';
import toInclude from './toInclude';
import toBeBoolean from './toBeBoolean';
import toBeFunction from './toBeFunction';
import toBeNumber from './toBeNumber';
import toBeOdd from './toBeOdd';
import toContainAllValues from './toContainAllValues';

export default [
  toBeEven,
  toBeTrue,
  toBeFalse,
  toContainValue,
  toContainValues,
  toBeArray,
  toEqualCaseInsensitive,
  toStartWith,
  toBeNegative,
  toBeOneOf,
  toContainKey,
  toBeString,
  toBeExtensible,
  toBeWithin,
  toIncludeMultiple,
  toEndWith,
  toBeFrozen,
  toBeObject,
  toContainAllKeys,
  toContainAnyKeys,
  toContainKeys,
  toBeFinite,
  toIncludeAnyMembers,
  toIncludeAllMembers,
  toBeNaN,
  toBePositive,
  toInclude,
  toBeBoolean,
  toBeFunction,
  toBeNumber,
  toBeOdd,
  toContainAllValues
].reduce((acc, matcher) => ({ ...acc, ...matcher }), {});
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2019 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @fileoverview Useragent detection.
 * These methods are not specific to Blockly, and could be factored out into
 * a JavaScript framework such as Closure.
 * @author fraser@google.com (Neil Fraser)
 */
'use strict';

/**
 * @name Blockly.utils.userAgent
 * @namespace
 */
goog.module('Blockly.utils.userAgent');

const {globalThis} = goog.require('Blockly.utils.global');

/**
 * @type {string}
 * The raw useragent string.
 */
let rawUserAgent;

/** @type {boolean} */
let isIe;

/** @type {boolean} */
let isEdge;

/** @type {boolean} */
let isJavaFx;

/** @type {boolean} */
let isChrome;

/** @type {boolean} */
let isWebKit;

/** @type {boolean} */
let isGecko;

/** @type {boolean} */
let isAndroid;

/** @type {boolean} */
let isIPad;

/** @type {boolean} */
let isIPod;

/** @type {boolean} */
let isIPhone;

/** @type {boolean} */
let isMac;

/** @type {boolean} */
let isTablet;

/** @type {boolean} */
let isMobile;

(function(raw) {
rawUserAgent = raw;
const rawUpper = rawUserAgent.toUpperCase();
/**
 * Case-insensitive test of whether name is in the useragent string.
 * @param {string} name Name to test.
 * @return {boolean} True if name is present.
 */
function has(name) {
  return rawUpper.indexOf(name.toUpperCase()) != -1;
}

// Browsers.  Logic from:
// https://github.com/google/closure-library/blob/master/closure/goog/labs/useragent/browser.js
isIe = has('Trident') || has('MSIE');
isEdge = has('Edge');
// Useragent for JavaFX:
// Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.44
//     (KHTML, like Gecko) JavaFX/8.0 Safari/537.44
isJavaFx = has('JavaFX');
isChrome = (has('Chrome') || has('CriOS')) && !isEdge;

// Engines.  Logic from:
// https://github.com/google/closure-library/blob/master/closure/goog/labs/useragent/engine.js
isWebKit = has('WebKit') && !isEdge;
isGecko = has('Gecko') && !isWebKit && !isIe && !isEdge;

// Platforms.  Logic from:
// https://github.com/google/closure-library/blob/master/closure/goog/labs/useragent/platform.js
// and
// https://github.com/google/closure-library/blob/master/closure/goog/labs/useragent/extra.js
isAndroid = has('Android');
const maxTouchPoints =
    globalThis['navigator'] && globalThis['navigator']['maxTouchPoints'];
isIPad = has('iPad') || has('Macintosh') && maxTouchPoints > 0;
isIPod = has('iPod');
isIPhone = has('iPhone') && !isIPad && !isIPod;
isMac = has('Macintosh');

// Devices.  Logic from:
// https://github.com/google/closure-library/blob/master/closure/goog/labs/useragent/device.js
isTablet = isIPad || (isAndroid && !has('Mobile')) || has('Silk');
isMobile = !isTablet && (isIPod || isIPhone || isAndroid || has('IEMobile'));
})((globalThis['navigator'] && globalThis['navigator']['userAgent']) || '');

/** @const {string} */
exports.raw = rawUserAgent;

/** @const {boolean} */
exports.IE = isIe;

/** @const {boolean} */
exports.EDGE = isEdge;

/** @const {boolean} */
exports.JavaFx = isJavaFx;

/** @const {boolean} */
exports.CHROME = isChrome;

/** @const {boolean} */
exports.WEBKIT = isWebKit;

/** @const {boolean} */
exports.GECKO = isGecko;

/** @const {boolean} */
exports.ANDROID = isAndroid;

/** @const {boolean} */
exports.IPAD = isIPad;

/** @const {boolean} */
exports.IPOD = isIPod;

/** @const {boolean} */
exports.IPHONE = isIPhone;

/** @const {boolean} */
exports.MAC = isMac;

/** @const {boolean} */
exports.TABLET = isTablet;

/** @const {boolean} */
exports.MOBILE = isMobile;
<commit_msg>Fix jsdoc in core/utils/useragent.js<commit_after>/**
 * @license
 * Copyright 2019 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @fileoverview Useragent detection.
 * These methods are not specific to Blockly, and could be factored out into
 * a JavaScript framework such as Closure.
 * @author fraser@google.com (Neil Fraser)
 */
'use strict';

/**
 * @name Blockly.utils.userAgent
 * @namespace
 */
goog.module('Blockly.utils.userAgent');

const {globalThis} = goog.require('Blockly.utils.global');

/**
 * The raw useragent string.
 * @type {string}
 */
let rawUserAgent;

/** @type {boolean} */
let isIe;

/** @type {boolean} */
let isEdge;

/** @type {boolean} */
let isJavaFx;

/** @type {boolean} */
let isChrome;

/** @type {boolean} */
let isWebKit;

/** @type {boolean} */
let isGecko;

/** @type {boolean} */
let isAndroid;

/** @type {boolean} */
let isIPad;

/** @type {boolean} */
let isIPod;

/** @type {boolean} */
let isIPhone;

/** @type {boolean} */
let isMac;

/** @type {boolean} */
let isTablet;

/** @type {boolean} */
let isMobile;

(function(raw) {
rawUserAgent = raw;
const rawUpper = rawUserAgent.toUpperCase();
/**
 * Case-insensitive test of whether name is in the useragent string.
 * @param {string} name Name to test.
 * @return {boolean} True if name is present.
 */
function has(name) {
  return rawUpper.indexOf(name.toUpperCase()) != -1;
}

// Browsers.  Logic from:
// https://github.com/google/closure-library/blob/master/closure/goog/labs/useragent/browser.js
isIe = has('Trident') || has('MSIE');
isEdge = has('Edge');
// Useragent for JavaFX:
// Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.44
//     (KHTML, like Gecko) JavaFX/8.0 Safari/537.44
isJavaFx = has('JavaFX');
isChrome = (has('Chrome') || has('CriOS')) && !isEdge;

// Engines.  Logic from:
// https://github.com/google/closure-library/blob/master/closure/goog/labs/useragent/engine.js
isWebKit = has('WebKit') && !isEdge;
isGecko = has('Gecko') && !isWebKit && !isIe && !isEdge;

// Platforms.  Logic from:
// https://github.com/google/closure-library/blob/master/closure/goog/labs/useragent/platform.js
// and
// https://github.com/google/closure-library/blob/master/closure/goog/labs/useragent/extra.js
isAndroid = has('Android');
const maxTouchPoints =
    globalThis['navigator'] && globalThis['navigator']['maxTouchPoints'];
isIPad = has('iPad') || has('Macintosh') && maxTouchPoints > 0;
isIPod = has('iPod');
isIPhone = has('iPhone') && !isIPad && !isIPod;
isMac = has('Macintosh');

// Devices.  Logic from:
// https://github.com/google/closure-library/blob/master/closure/goog/labs/useragent/device.js
isTablet = isIPad || (isAndroid && !has('Mobile')) || has('Silk');
isMobile = !isTablet && (isIPod || isIPhone || isAndroid || has('IEMobile'));
})((globalThis['navigator'] && globalThis['navigator']['userAgent']) || '');

/** @const {string} */
exports.raw = rawUserAgent;

/** @const {boolean} */
exports.IE = isIe;

/** @const {boolean} */
exports.EDGE = isEdge;

/** @const {boolean} */
exports.JavaFx = isJavaFx;

/** @const {boolean} */
exports.CHROME = isChrome;

/** @const {boolean} */
exports.WEBKIT = isWebKit;

/** @const {boolean} */
exports.GECKO = isGecko;

/** @const {boolean} */
exports.ANDROID = isAndroid;

/** @const {boolean} */
exports.IPAD = isIPad;

/** @const {boolean} */
exports.IPOD = isIPod;

/** @const {boolean} */
exports.IPHONE = isIPhone;

/** @const {boolean} */
exports.MAC = isMac;

/** @const {boolean} */
exports.TABLET = isTablet;

/** @const {boolean} */
exports.MOBILE = isMobile;
<|endoftext|>


<commit_before>'use strict';

const fs = require('fs');
const path = require('path');
const { spawnSync } = require('child_process');
const glob = require('glob-gitignore');

const packagesDir = path.join(__dirname, 'packages');
const docsDir = path.join(__dirname, 'docs');

const packages = (process.argv.length > 2 ? [process.argv[2]] : glob.sync('*', { cwd: packagesDir }))
  .map(name => JSON.parse(fs.readFileSync(path.join(packagesDir, name, 'package.json'))))
  .filter(x => !x.private && x.name !== 'enzyme-example-mocha');

packages.forEach((pkg) => {
  const tag = `${pkg.name === 'docs' ? 'enzyme' : pkg.name}@${pkg.version}`;
  const dir = path.join(packagesDir, pkg.name);
  const logArgs = ['--no-pager', 'log', '--oneline', `${tag}..HEAD`, dir].concat(pkg.name === 'enzyme' ? docsDir : []);
  const log = spawnSync('git', logArgs, { stdio: 'pipe' });
  if (log.stdout.length > 0 || log.stderr.length > 0) {
    console.log(tag);
    spawnSync('git', logArgs, { stdio: 'inherit' });
    console.log('\n');
  }
});
<commit_msg>[meta] `since`: exclude eslintrc changes<commit_after>'use strict';

const fs = require('fs');
const path = require('path');
const { spawnSync } = require('child_process');
const glob = require('glob-gitignore');

const packagesDir = path.join(__dirname, 'packages');
const docsDir = path.join(__dirname, 'docs');

const packages = (process.argv.length > 2 ? [process.argv[2]] : glob.sync('*', { cwd: packagesDir }))
  .map(name => JSON.parse(fs.readFileSync(path.join(packagesDir, name, 'package.json'))))
  .filter(x => !x.private && x.name !== 'enzyme-example-mocha');

packages.forEach((pkg) => {
  const tag = `${pkg.name === 'docs' ? 'enzyme' : pkg.name}@${pkg.version}`;
  const dir = path.join(packagesDir, pkg.name);
  const logArgs = ['--no-pager', 'log', '--oneline', `${tag}..HEAD`, dir, ':!**/.eslintrc'].concat(pkg.name === 'enzyme' ? docsDir : []);
  const log = spawnSync('git', logArgs, { stdio: 'pipe' });
  if (log.stdout.length > 0 || log.stderr.length > 0) {
    console.log(tag);
    spawnSync('git', logArgs, { stdio: 'inherit' });
    console.log('\n');
  }
});
<|endoftext|>


<commit_before>import { Schema, arrayOf, normalize } from 'normalizr';
import { camelizeKeys, pascalizeKeys } from 'humps';
import { AUTH_REQUEST } from '../constants/ActionTypes';
import { REHYDRATE } from 'redux-persist/constants';

import { formData, qs } from '../util/request';

let token = '';
const API_ROOT = 'https://leanote.com/api/';

// Fetches an API response and normalizes the result JSON according to schema.
function callApi(url, options, schema) {
  return fetch(API_ROOT + url, options)
    .then(response =>
      response.json().then(json => {
        if (!response.ok) {
          return Promise.reject(json)
        }
        const camelizedJson = camelizeKeys(json)
				if (schema) {
					return normalize(camelizedJson, schema);
				}
				return camelizedJson;
      })
    );
}

// A Redux middleware that interprets actions with url and types info specified.
// Performs the call and promises when such actions are dispatched.
export default store => next => action => {
  if (!token) {
    token = store.getState().user.token;
  }
  if (action.type === REHYDRATE) {
    // REHYDRATE triggers other actions, so token is supposed to be initialized after next() return.
    const result = next(action);
    if (!token) {
      require('electron').ipcRenderer.send('auth-request');
    }
    return result;
  }

	if (!action.types || !action.url) {
		return next(action);
	}

  let { schema, types, query = {}, url, method = 'GET', body = {} } = action;
  if (!Array.isArray(types) || types.length !== 3) {
    throw new Error('Expected an array of three action types.');
  }
  const [ LOADING, SUCCESS, ERROR ] = types;
  if (!token && LOADING !== AUTH_REQUEST) {
    throw new Error('Token has not been initialized');
  }
  LOADING && next({
		type: LOADING,
    payload: action,
	});
  query.token = token;
  return callApi(`${url}?${qs(query)}`, { method, body: formData(pascalizeKeys(body)) }, schema)
		.then(
			(response) => {
				const finalAction = {
					type: SUCCESS,
					payload: {
						...response,
					},
				}
				return SUCCESS ? next(finalAction) : finalAction;
			},
	    (error) => {
				const finalAction = {
					type: ERROR,
					meta: {
						error,
					},
					error: true,
				};
				return ERROR ? next(ERROR) : finalAction;
			}
		);
}
<commit_msg>Register protocol immediately after rehydrate<commit_after>import { Schema, arrayOf, normalize } from 'normalizr';
import { camelizeKeys, pascalizeKeys } from 'humps';
import { AUTH_REQUEST } from '../constants/ActionTypes';
import { REHYDRATE } from 'redux-persist/constants';

import { formData, qs } from '../util/request';

let token = '';
const API_ROOT = 'https://leanote.com/api/';

// Fetches an API response and normalizes the result JSON according to schema.
function callApi(url, options, schema) {
  return fetch(API_ROOT + url, options)
    .then(response =>
      response.json().then(json => {
        if (!response.ok) {
          return Promise.reject(json)
        }
        const camelizedJson = camelizeKeys(json)
				if (schema) {
					return normalize(camelizedJson, schema);
				}
				return camelizedJson;
      })
    );
}

// A Redux middleware that interprets actions with url and types info specified.
// Performs the call and promises when such actions are dispatched.
export default store => next => action => {
  if (!token) {
    token = store.getState().user.token;
  }
  if (action.type === REHYDRATE) {
    // REHYDRATE triggers other actions, so token is supposed to be initialized after next() return.
    const result = next(action);
    if (token) {
      require('electron').ipcRenderer.send('register-protocol', token);
    }
    else {
      require('electron').ipcRenderer.send('auth-request');
    }
    return result;
  }

	if (!action.types || !action.url) {
		return next(action);
	}

  let { schema, types, query = {}, url, method = 'GET', body = {} } = action;
  if (!Array.isArray(types) || types.length !== 3) {
    throw new Error('Expected an array of three action types.');
  }
  const [ LOADING, SUCCESS, ERROR ] = types;
  if (!token && LOADING !== AUTH_REQUEST) {
    throw new Error('Token has not been initialized');
  }
  LOADING && next({
		type: LOADING,
    payload: action,
	});
  query.token = token;
  return callApi(`${url}?${qs(query)}`, { method, body: formData(pascalizeKeys(body)) }, schema)
		.then(
			(response) => {
				const finalAction = {
					type: SUCCESS,
					payload: {
						...response,
					},
				}
				return SUCCESS ? next(finalAction) : finalAction;
			},
	    (error) => {
				const finalAction = {
					type: ERROR,
					meta: {
						error,
					},
					error: true,
				};
				return ERROR ? next(ERROR) : finalAction;
			}
		);
}
<|endoftext|>