<commit_before>/*
	Pokemon Showdown Bot, for NodeJS

	By: Ecuacion
*/

try {
	require('sugar');

	global.colors = require('colors');
	global.sys = require('sys');
	global.fs = require('fs');
	global.path = require('path');
	global.PSClient = require('node-ps-client');
} catch (e) {
	console.log(e.stack);
	console.log("ERROR: missing dependencies, try 'npm install'");
	process.exit(-1);
}

console.log((
	'-----------------------------------------------\n' +
	'   Welcome to Pokemon Showdown Bot for Node!   \n' +
	'-----------------------------------------------\n'
).yellow);

global.Tools = require('./tools.js');

if (!fs.existsSync('./config.js')) {
	console.log("config.js does not exist - creating one with default settings...");
	fs.writeFileSync('./config.js', fs.readFileSync('./config-example.js'));
}

global.Config = require('./config.js');
Tools.checkConfig();

global.reloadConfig = function () {
	Tools.uncacheTree('./config.js');
	global.Config = require('./config.js');
	Tools.checkConfig();
	CommandParser.reloadTokens();
};

info('Loading globals');

/* Globals */

global.Formats = {};

global.Settings = require('./settings.js');

global.DataDownloader = require('./data-downloader.js');

global.CommandParser = require('./command-parser.js');

/* Commands */

CommandParser.loadCommands();

/* Languages (translations) */

Tools.loadTranslations();

/* Features */

global.Features = {};

var featureList = fs.readdirSync('./features/');

featureList.forEach(function (feature) {
	if (fs.existsSync('./features/' + feature + '/index.js')) {
		try {
			var f = require('./features/' + feature + '/index.js');
			if (f.id) {
				Features[f.id] = f;
				ok("New feature: " + f.id + ' | ' + f.desc);
			} else {
				error("Failed to load feature: " + './features/' + feature);
			}
		} catch (e) {
			errlog(e.stack);
			error("Failed to load feature: " + './features/' + feature);
		}
	}
});

global.reloadFeatures = function () {
	var featureList = fs.readdirSync('./features/');
	var errs = [];
	featureList.forEach(function (feature) {
		if (fs.existsSync('./features/' + feature + '/index.js')) {
			try {
				Tools.uncacheTree('./features/' + feature + '/index.js');
				var f = require('./features/' + feature + '/index.js');
				if (f.id) {
					if (Features[f.id] && typeof Features[f.id].destroy === "function") Features[f.id].destroy();
					Features[f.id] = f;
					Features[f.id].init();
				}
			} catch (e) {
				errlog(e.stack);
				errs.push(feature);
			}
		}
	});
	info('Features reloaded' + (errs.length ? ('. Errors: ' + errs.join(', ')) : ''));
	return errs;
};

/* Bot creation and connection */

function botAfterConnect () {
	//join rooms
	if (typeof Config.rooms === "string") {
		joinByQueryRequest(Config.rooms);
	} else {
		var cmds = [];
		for (var i = 0; i < Config.rooms.length; i++) {
			cmds.push('|/join ' + Config.rooms[i]);
		}
		for (var i = 0; i < Config.initCmds.length; i++) {
			cmds.push(Config.initCmds[i]);
		}
		Bot.send(cmds, 2000);
	}
	if (!Config.disableDownload) {
		DataDownloader.download();
	}
}

function joinByQueryRequest(target) {
	if (target === 'official' || target === 'public' || target === 'all') {
		info('Joining ' + target + ' rooms');
	} else {
		error('Config.rooms, as a string must be "official", "public" or "all"');
		var cmds = [];
		for (var i = 0; i < Config.initCmds.length; i++) {
			cmds.push(Config.initCmds[i]);
		}
		Bot.send(cmds, 2000);
		return;
	}
	Bot.on('queryresponse', function (data) {
		data = data.split('|');
		if (data[0] === 'rooms') {
			data.splice(0, 1);
			var str = data.join('|');
			var cmds = [];
			try {
				var rooms = JSON.parse(str);
				var offRooms = [], publicRooms = [];
				if (rooms.official) {
					for (var i = 0; i < rooms.official.length; i++) {
						if (rooms.official[i].title) offRooms.push(toId(rooms.official[i].title));
					}
				}
				if (rooms.chat) {
					for (var i = 0; i < rooms.chat.length; i++) {
						if (rooms.chat[i].title) publicRooms.push(toId(rooms.chat[i].title));
					}
				}
				if (target === 'all' || target === 'official') {
					for (var i = 0; i < offRooms.length; i++) cmds.push('|/join ' + offRooms[i]);
				}
				if (target === 'all' || target === 'public') {
					for (var i = 0; i < publicRooms.length; i++) cmds.push('|/join ' + publicRooms[i]);
				}
			} catch (e) {}
			for (var i = 0; i < Config.initCmds.length; i++) {
				cmds.push(Config.initCmds[i]);
			}
			Bot.send(cmds, 2000);
			Bot.on('queryresponse', function () {return;});
		}
	});
	Bot.send('|/cmd rooms');
}

var opts = {
	serverid: Config.serverid,
	secprotocols: [],
	connectionTimeout: Config.connectionTimeout,
	loginServer: 'https://play.pokemonshowdown.com/~~' + Config.serverid + '/action.php',
	nickName: null,
	pass: null,
	retryLogin: false,
	autoConnect: false,
	autoReconnect: false,
	autoReconnectDelay: 0,
	autoJoin: [],
	showErrors: (Config.debug ? Config.debug.debug : true),
	debug: (Config.debug ? Config.debug.debug : true)
};

global.Bot = new PSClient(Config.server, Config.port, opts);

var connected = false;
Bot.on('connect', function (con) {
	ok('Connected to server ' + Config.serverid + ' (' + Tools.getDateString() + ')');
	connected = true;
	for (var f in Features) {
		try {
			Features[f].init();
		} catch (e) {
			errlog(e.stack);
			error("Feature Crash: " + f + " | " + sys.inspect(e));
		}
	}
});

Bot.on('formats', function (formats) {
	global.Formats = {};
	var formatsArr = formats.split('|');
	var commaIndex, sharpIndex, f, arg, formatData, spf, nCommas;
	for (var i = 0; i < formatsArr.length; i++) {
		commaIndex = formatsArr[i].indexOf(',');
		if (commaIndex === -1) {
			Formats[toId(formatsArr[i])] = {name: formatsArr[i], team: true, ladder: true, chall: true};
		} else if (commaIndex === 0) {
			continue;
		} else {
			f = formatsArr[i].substr(0, commaIndex);
			arg = formatsArr[i].substr(commaIndex);
			formatData = {name: f, team: true, ladder: true, chall: true};
			sharpIndex = arg.indexOf('#');
			if (sharpIndex >= 0) formatData.team = false;
			spf = arg.split(',');
			nCommas = 0;
			for (var k = 0; k < spf.length; k++) if (!spf[k]) nCommas++;
			if (nCommas === 2) formatData.ladder = false;
			else if (nCommas === 3) formatData.chall = false;
			Formats[toId(f)] = formatData;
		}
	}
	ok('Received battle formats. Total: ' + formatsArr.length);
});

Bot.on('challstr', function (challstr) {
	info('Received challstr, logging in...');
	if (!Config.nick) {
		Bot.rename('Bot ' + Tools.generateRandomNick(10));
	} else {
		Bot.rename(Config.nick, Config.pass);
	}
});

var retryingRename = false;
Bot.on('renamefailure', function (e) {
	if (e === -1)  {
		if (!Config.nick) {
			debug('Login failure - generating another random nickname');
			Bot.rename('Bot ' + Tools.generateRandomNick(10));
		} else {
			error('Login failure - name registered, invalid or no password given');
			if (!Bot.status.named) {
				info("Invalid nick + pass, using a random nickname");
				Config.nick = '';
				Bot.rename('Bot ' + Tools.generateRandomNick(10));
			}
		}
	} else {
		if (Config.autoReloginDelay) {
			error('Login failure, retrying in ' + (Config.autoReloginDelay / 1000) + ' seconds');
			retryingRename = true;
			setTimeout(function () {
				retryingRename = false;
				if (!Config.nick) {
					Bot.rename('Bot ' + Tools.generateRandomNick(10));
				} else {
					Bot.rename(Config.nick, Config.pass);
				}
			}, Config.autoReloginDelay);
		} else {
			error('Login failure');
		}
	}
});

Bot.on('rename', function (name, named) {
	monitor('Bot nickname has changed: ' + (named ? name.green : name.yellow) + (named ? '' : ' [guest]'));
	if (named) {
		if (!Config.nick) {
			if (Bot.roomcount > 0) return; // Namechange, not initial login
			ok('Succesfully logged in as ' + name);
			botAfterConnect();
		} else if (toId(Config.nick) === toId(name)) {
			ok('Succesfully logged in as ' + name);
			botAfterConnect();
		}
	}
});

/* Reconnect timer */

var reconnectTimer = null;
var reconnecting = false;
Bot.on('disconnect', function (e) {
	connected = false;
	if (Config.autoReconnectDelay) {
		if (reconnecting) return;
		reconnecting = true;
		error('Disconnected from server, retrying in ' + (Config.autoReconnectDelay / 1000) + ' seconds');
		reconnectTimer = setTimeout(function () {
			reconnecting = false;
			info('Connecting to server ' + Config.server + ':' + Config.port);
			Bot.connect();
		}, Config.autoReconnectDelay);
	} else {
		error('Disconnected from server, exiting...');
		process.exit(0);
	}
});

/* Commands */

Bot.on('chat', function (room, timeOff, by, msg) {
	CommandParser.parse(room, by, msg);
	Settings.reportSeen(by, room, 'c', []);
});

Bot.on('pm', function (by, msg) {
	CommandParser.parse(',' + by, by, msg);
});

Bot.on('userjoin', function (room, by) {
	Settings.reportSeen(by, room, 'j', []);
});

Bot.on('userleave', function (room, by) {
	Settings.reportSeen(by, room, 'l', []);
});

Bot.on('userrename', function (room, old, by) {
	Settings.reportSeen(old, room, 'n', [by]);
});

/* Features */

Bot.on('line', function (room, message, isIntro, spl) {
	for (var f in Features) {
		try {
			Features[f].parse(room, message, isIntro, spl);
		} catch (e) {
			errlog(e.stack);
			error("Feature Crash: " + f + " | " + sys.inspect(e));
			Features[f].disabled = true;
			Features[f].parse = function () {
				return true;
			};
			info("Feature " + f + " has been disabled");
		}
	}
});

/* Info and debug */

Bot.on('joinroom', function (room, type) {
	if (type === 'chat') monitor('Joined room ' + room, 'room', 'join');
	else if (type === 'battle') monitor('Joined battle ' + room, 'battle', 'join');
	else monitor('Joined room ' + room + ' [' + Bot.rooms[room].type + ']', 'room', 'join');
});

Bot.on('joinfailure', function (room, e, moreInfo) {
	monitor('Could not join ' + room + ': [' + e + '] ' + moreInfo, 'room', 'error');
});

Bot.on('leaveroom', function (room) {
	var roomType = Bot.rooms[room] ? Bot.rooms[room].type : 'chat';
	if (roomType === 'chat') monitor('Left room ' + room, 'room', 'leave');
	else if (roomType === 'battle') monitor('Left battle ' + room, 'battle', 'leave');
	else monitor('Left room ' + room + ' [' + Bot.rooms[room].type + ']', 'room', 'leave');
});

Bot.on('message', function (msg) {
	recv(msg);
});

Bot.on('send', function (msg) {
	sent(msg);
});

ok('Bot object is ready');

/* Global Monitor */

var checkSystem = function () {
	var status = '';
	var issue = false;
	status += 'Connection: ';
	if (connected) {
		status += 'connected'.green;
		status += ' | Nickname: ';
		if (Bot.status.named) {
			status += Bot.status.nickName.green;
		} else if (retryingRename) {
			status += Bot.status.nickName.yellow;
		} else {
			status += Bot.status.nickName.red;
			issue = 'login';
		}
	} else if (reconnecting) {
		status += 'retrying'.yellow;
	} else {
		issue = 'connect';
		status += 'disconnected'.red;
	}
	monitor(status + ' (' + Tools.getDateString() + ')', 'status');
	if (issue) {
		switch (issue) {
			case 'connect':
				monitor("Monitor failed: Connection issue. Reconnecting");
				Bot.connect();
				break;
			case 'login':
				monitor("Monitor failed: Login issue. Loging in a random username");
				Config.nick = '';
				Bot.rename('Bot ' + Tools.generateRandomNick(10));
				break;
		}
	}
};
var sysChecker = setInterval(checkSystem, 60 * 60 * 1000);
ok('Global monitor is working');

//CrashGuard
if (Config.crashguard) {
	process.on('uncaughtException', function (err) {
		error(("" + err.message).red);
		errlog(("" + err.stack).red);
	});
	ok("Crashguard enabled");
}

console.log("\n-----------------------------------------------\n".yellow);

//Connection
info('Connecting to server ' + Config.server + ':' + Config.port);
Bot.connect();
Bot.startConnectionTimeOut();
<commit_msg>Update Formats parser<commit_after>/*
	Pokemon Showdown Bot, for NodeJS

	By: Ecuacion
*/

try {
	require('sugar');

	global.colors = require('colors');
	global.sys = require('sys');
	global.fs = require('fs');
	global.path = require('path');
	global.PSClient = require('node-ps-client');
} catch (e) {
	console.log(e.stack);
	console.log("ERROR: missing dependencies, try 'npm install'");
	process.exit(-1);
}

console.log((
	'-----------------------------------------------\n' +
	'   Welcome to Pokemon Showdown Bot for Node!   \n' +
	'-----------------------------------------------\n'
).yellow);

global.Tools = require('./tools.js');

if (!fs.existsSync('./config.js')) {
	console.log("config.js does not exist - creating one with default settings...");
	fs.writeFileSync('./config.js', fs.readFileSync('./config-example.js'));
}

global.Config = require('./config.js');
Tools.checkConfig();

global.reloadConfig = function () {
	Tools.uncacheTree('./config.js');
	global.Config = require('./config.js');
	Tools.checkConfig();
	CommandParser.reloadTokens();
};

info('Loading globals');

/* Globals */

global.Formats = {};

global.Settings = require('./settings.js');

global.DataDownloader = require('./data-downloader.js');

global.CommandParser = require('./command-parser.js');

/* Commands */

CommandParser.loadCommands();

/* Languages (translations) */

Tools.loadTranslations();

/* Features */

global.Features = {};

var featureList = fs.readdirSync('./features/');

featureList.forEach(function (feature) {
	if (fs.existsSync('./features/' + feature + '/index.js')) {
		try {
			var f = require('./features/' + feature + '/index.js');
			if (f.id) {
				Features[f.id] = f;
				ok("New feature: " + f.id + ' | ' + f.desc);
			} else {
				error("Failed to load feature: " + './features/' + feature);
			}
		} catch (e) {
			errlog(e.stack);
			error("Failed to load feature: " + './features/' + feature);
		}
	}
});

global.reloadFeatures = function () {
	var featureList = fs.readdirSync('./features/');
	var errs = [];
	featureList.forEach(function (feature) {
		if (fs.existsSync('./features/' + feature + '/index.js')) {
			try {
				Tools.uncacheTree('./features/' + feature + '/index.js');
				var f = require('./features/' + feature + '/index.js');
				if (f.id) {
					if (Features[f.id] && typeof Features[f.id].destroy === "function") Features[f.id].destroy();
					Features[f.id] = f;
					Features[f.id].init();
				}
			} catch (e) {
				errlog(e.stack);
				errs.push(feature);
			}
		}
	});
	info('Features reloaded' + (errs.length ? ('. Errors: ' + errs.join(', ')) : ''));
	return errs;
};

/* Bot creation and connection */

function botAfterConnect () {
	//join rooms
	if (typeof Config.rooms === "string") {
		joinByQueryRequest(Config.rooms);
	} else {
		var cmds = [];
		for (var i = 0; i < Config.rooms.length; i++) {
			cmds.push('|/join ' + Config.rooms[i]);
		}
		for (var i = 0; i < Config.initCmds.length; i++) {
			cmds.push(Config.initCmds[i]);
		}
		Bot.send(cmds, 2000);
	}
	if (!Config.disableDownload) {
		DataDownloader.download();
	}
}

function joinByQueryRequest(target) {
	if (target === 'official' || target === 'public' || target === 'all') {
		info('Joining ' + target + ' rooms');
	} else {
		error('Config.rooms, as a string must be "official", "public" or "all"');
		var cmds = [];
		for (var i = 0; i < Config.initCmds.length; i++) {
			cmds.push(Config.initCmds[i]);
		}
		Bot.send(cmds, 2000);
		return;
	}
	Bot.on('queryresponse', function (data) {
		data = data.split('|');
		if (data[0] === 'rooms') {
			data.splice(0, 1);
			var str = data.join('|');
			var cmds = [];
			try {
				var rooms = JSON.parse(str);
				var offRooms = [], publicRooms = [];
				if (rooms.official) {
					for (var i = 0; i < rooms.official.length; i++) {
						if (rooms.official[i].title) offRooms.push(toId(rooms.official[i].title));
					}
				}
				if (rooms.chat) {
					for (var i = 0; i < rooms.chat.length; i++) {
						if (rooms.chat[i].title) publicRooms.push(toId(rooms.chat[i].title));
					}
				}
				if (target === 'all' || target === 'official') {
					for (var i = 0; i < offRooms.length; i++) cmds.push('|/join ' + offRooms[i]);
				}
				if (target === 'all' || target === 'public') {
					for (var i = 0; i < publicRooms.length; i++) cmds.push('|/join ' + publicRooms[i]);
				}
			} catch (e) {}
			for (var i = 0; i < Config.initCmds.length; i++) {
				cmds.push(Config.initCmds[i]);
			}
			Bot.send(cmds, 2000);
			Bot.on('queryresponse', function () {return;});
		}
	});
	Bot.send('|/cmd rooms');
}

var opts = {
	serverid: Config.serverid,
	secprotocols: [],
	connectionTimeout: Config.connectionTimeout,
	loginServer: 'https://play.pokemonshowdown.com/~~' + Config.serverid + '/action.php',
	nickName: null,
	pass: null,
	retryLogin: false,
	autoConnect: false,
	autoReconnect: false,
	autoReconnectDelay: 0,
	autoJoin: [],
	showErrors: (Config.debug ? Config.debug.debug : true),
	debug: (Config.debug ? Config.debug.debug : true)
};

global.Bot = new PSClient(Config.server, Config.port, opts);

var connected = false;
Bot.on('connect', function (con) {
	ok('Connected to server ' + Config.serverid + ' (' + Tools.getDateString() + ')');
	connected = true;
	for (var f in Features) {
		try {
			Features[f].init();
		} catch (e) {
			errlog(e.stack);
			error("Feature Crash: " + f + " | " + sys.inspect(e));
		}
	}
});

Bot.on('formats', function (formats) {
	global.Formats = {};
	var formatsArr = formats.split('|');
	var commaIndex, arg, formatData, code, name;
	for (var i = 0; i < formatsArr.length; i++) {
		commaIndex = formatsArr[i].indexOf(',');
		if (commaIndex === -1) {
			Formats[toId(formatsArr[i])] = {name: formatsArr[i], team: true, ladder: true, chall: true};
		} else if (commaIndex === 0) {
			i++;
			continue;
		} else {
			name = formatsArr[i];
			formatData = {name: name, team: true, ladder: true, chall: true};
			code = commaIndex >= 0 ? parseInt(name.substr(commaIndex + 1), 16) : NaN;
			if (!isNaN(code)) {
				name = name.substr(0, commaIndex);
				if (code & 1) formatData.team = false;
				if (!(code & 2)) formatData.ladder = false;
				if (!(code & 4)) formatData.chall = false;
				if (!(code & 8)) formatData.disableTournaments = true;
			} else {
				if (name.substr(name.length - 2) === ',#') { // preset teams
					formatData.team = false;
					name = name.substr(0, name.length - 2);
				}
				if (name.substr(name.length - 2) === ',,') { // search-only
					formatData.chall = false;
					name = name.substr(0, name.length - 2);
				} else if (name.substr(name.length - 1) === ',') { // challenge-only
					formatData.ladder = false;
					name = name.substr(0, name.length - 1);
				}
			}
			formatData.name = name;
			Formats[toId(name)] = formatData;
		}
	}
	ok('Received battle formats. Total: ' + formatsArr.length);
});

Bot.on('challstr', function (challstr) {
	info('Received challstr, logging in...');
	if (!Config.nick) {
		Bot.rename('Bot ' + Tools.generateRandomNick(10));
	} else {
		Bot.rename(Config.nick, Config.pass);
	}
});

var retryingRename = false;
Bot.on('renamefailure', function (e) {
	if (e === -1)  {
		if (!Config.nick) {
			debug('Login failure - generating another random nickname');
			Bot.rename('Bot ' + Tools.generateRandomNick(10));
		} else {
			error('Login failure - name registered, invalid or no password given');
			if (!Bot.status.named) {
				info("Invalid nick + pass, using a random nickname");
				Config.nick = '';
				Bot.rename('Bot ' + Tools.generateRandomNick(10));
			}
		}
	} else {
		if (Config.autoReloginDelay) {
			error('Login failure, retrying in ' + (Config.autoReloginDelay / 1000) + ' seconds');
			retryingRename = true;
			setTimeout(function () {
				retryingRename = false;
				if (!Config.nick) {
					Bot.rename('Bot ' + Tools.generateRandomNick(10));
				} else {
					Bot.rename(Config.nick, Config.pass);
				}
			}, Config.autoReloginDelay);
		} else {
			error('Login failure');
		}
	}
});

Bot.on('rename', function (name, named) {
	monitor('Bot nickname has changed: ' + (named ? name.green : name.yellow) + (named ? '' : ' [guest]'));
	if (named) {
		if (!Config.nick) {
			if (Bot.roomcount > 0) return; // Namechange, not initial login
			ok('Succesfully logged in as ' + name);
			botAfterConnect();
		} else if (toId(Config.nick) === toId(name)) {
			ok('Succesfully logged in as ' + name);
			botAfterConnect();
		}
	}
});

/* Reconnect timer */

var reconnectTimer = null;
var reconnecting = false;
Bot.on('disconnect', function (e) {
	connected = false;
	if (Config.autoReconnectDelay) {
		if (reconnecting) return;
		reconnecting = true;
		error('Disconnected from server, retrying in ' + (Config.autoReconnectDelay / 1000) + ' seconds');
		reconnectTimer = setTimeout(function () {
			reconnecting = false;
			info('Connecting to server ' + Config.server + ':' + Config.port);
			Bot.connect();
		}, Config.autoReconnectDelay);
	} else {
		error('Disconnected from server, exiting...');
		process.exit(0);
	}
});

/* Commands */

Bot.on('chat', function (room, timeOff, by, msg) {
	CommandParser.parse(room, by, msg);
	Settings.reportSeen(by, room, 'c', []);
});

Bot.on('pm', function (by, msg) {
	CommandParser.parse(',' + by, by, msg);
});

Bot.on('userjoin', function (room, by) {
	Settings.reportSeen(by, room, 'j', []);
});

Bot.on('userleave', function (room, by) {
	Settings.reportSeen(by, room, 'l', []);
});

Bot.on('userrename', function (room, old, by) {
	Settings.reportSeen(old, room, 'n', [by]);
});

/* Features */

Bot.on('line', function (room, message, isIntro, spl) {
	for (var f in Features) {
		try {
			Features[f].parse(room, message, isIntro, spl);
		} catch (e) {
			errlog(e.stack);
			error("Feature Crash: " + f + " | " + sys.inspect(e));
			Features[f].disabled = true;
			Features[f].parse = function () {
				return true;
			};
			info("Feature " + f + " has been disabled");
		}
	}
});

/* Info and debug */

Bot.on('joinroom', function (room, type) {
	if (type === 'chat') monitor('Joined room ' + room, 'room', 'join');
	else if (type === 'battle') monitor('Joined battle ' + room, 'battle', 'join');
	else monitor('Joined room ' + room + ' [' + Bot.rooms[room].type + ']', 'room', 'join');
});

Bot.on('joinfailure', function (room, e, moreInfo) {
	monitor('Could not join ' + room + ': [' + e + '] ' + moreInfo, 'room', 'error');
});

Bot.on('leaveroom', function (room) {
	var roomType = Bot.rooms[room] ? Bot.rooms[room].type : 'chat';
	if (roomType === 'chat') monitor('Left room ' + room, 'room', 'leave');
	else if (roomType === 'battle') monitor('Left battle ' + room, 'battle', 'leave');
	else monitor('Left room ' + room + ' [' + Bot.rooms[room].type + ']', 'room', 'leave');
});

Bot.on('message', function (msg) {
	recv(msg);
});

Bot.on('send', function (msg) {
	sent(msg);
});

ok('Bot object is ready');

/* Global Monitor */

var checkSystem = function () {
	var status = '';
	var issue = false;
	status += 'Connection: ';
	if (connected) {
		status += 'connected'.green;
		status += ' | Nickname: ';
		if (Bot.status.named) {
			status += Bot.status.nickName.green;
		} else if (retryingRename) {
			status += Bot.status.nickName.yellow;
		} else {
			status += Bot.status.nickName.red;
			issue = 'login';
		}
	} else if (reconnecting) {
		status += 'retrying'.yellow;
	} else {
		issue = 'connect';
		status += 'disconnected'.red;
	}
	monitor(status + ' (' + Tools.getDateString() + ')', 'status');
	if (issue) {
		switch (issue) {
			case 'connect':
				monitor("Monitor failed: Connection issue. Reconnecting");
				Bot.connect();
				break;
			case 'login':
				monitor("Monitor failed: Login issue. Loging in a random username");
				Config.nick = '';
				Bot.rename('Bot ' + Tools.generateRandomNick(10));
				break;
		}
	}
};
var sysChecker = setInterval(checkSystem, 60 * 60 * 1000);
ok('Global monitor is working');

//CrashGuard
if (Config.crashguard) {
	process.on('uncaughtException', function (err) {
		error(("" + err.message).red);
		errlog(("" + err.stack).red);
	});
	ok("Crashguard enabled");
}

console.log("\n-----------------------------------------------\n".yellow);

//Connection
info('Connecting to server ' + Config.server + ':' + Config.port);
Bot.connect();
Bot.startConnectionTimeOut();
<|endoftext|>


<commit_before>var RLE = require('./run-length-encoding')

module.exports = function (width) {
  function encode (inputs, buf, offset) {
    offset = offset | 0
    var bytes = 0
    //count number of repeats
    var i = 0
    while(i < inputs.length) {
      var _i = i++
      var value = inputs[_i]
      for(; i < inputs.length && inputs[i] === value; i++)
        ;
      if(i > 1) {
        console.log('offset', offset, bytes, offset + bytes)
        RLE.encode({value: value, repeats: i - _i, width: width}, buf, offset + bytes)
        bytes += RLE.encode.bytes
      }
      else
        throw new Error('expected repeat')
    }
    if(i != inputs.length) throw new Error('did not encode all items')

    buf[offset + bytes] = 0xff
    encode.bytes = bytes + 1
    return buf
  }
  function decode (buf, offset) {

  }

  return {
    encode: encode, decode: decode
  }
}

<commit_msg>separate logic to decide when to switch between RLE and BP<commit_after>var RLE = require('./run-length-encoding')
var bitpacking = require('bitpacking')
var varint = require('varint')
var assert = require('assert')

function append(ary, item) {
  ary.push(item)
  return ary
}

function h (width) {
  var runs = []
  var buffer = []
  var previous = 0
  var repeats = 1
  function appendRLE () {
    runs.push({value: previous, repeats: repeats})
  }

  function appendBitpack () {
    var last = runs.length - 1
    if(Array.isArray(runs[last]))
      runs[last] = runs[last].concat(buffer)
    else
      runs.push(buffer)
    repeats = 0
    buffer = []
  }

  return {
    write: function (value) {
      if(value === previous) {
        repeats ++
        //do not add to buffer, because we will RLE
        if(repeats >= 8) return
      }
      else {
        if(repeats >= 8)
          appendRLE()
        repeats = 1
        previous = value
      }
      buffer.push(value)
      if(buffer.length == 8)
        appendBitpack()
    },
    end: function () {
      if(repeats >= 8)
        appendRLE()
      else if(buffer.length > 0) {
        while(buffer.length < 8)
          buffer.push(0)
        appendBitpack()
      }
      return runs
    }
  }
}

function toRuns (input) {
  var _h = h()
  input.forEach(function (value) {
    _h.write(value)
  })
  return _h.end()

  var runs = []
  var buffer = []
  var previous = null
  var repeats = 1
  input.forEach(function (value) {
    if(previous == null) {
      previous = value
    } else if(previous === value) {
      repeats ++
      if(repeats >= 8) return
    } else {
      //new value, but maybe the end of a rle run
      if(repeats >= 8)
        runs.push({value: previous, repeats: repeats})
      repeats = 1
    }

    if(repeats < 8) {
      buffer.push(value)
      previous = value
      if(buffer.length >= 8) {
        //if the previous buffer
        appendBitpack()
      }
    }
  })

  function appendBitpack () {
    var last = runs.length - 1
    console.log('last', runs[last])
    if(Array.isArray(runs[last])) {
//      console.log('CONCAT', runs, buffer)
      runs[last] = runs[last].concat(buffer)
    } else
      runs.push(buffer)
    buffer = []
  }

  if(repeats >= 8)
    runs.push({value: previous, repeats: repeats})
  else
    appendBitpack()
  return runs
}

module.exports = function (width) {
  function encode (inputs, buf, offset) {
    offset = offset | 0
    var bytes = 0
    //count number of repeats
    var i = 0
    while(i < inputs.length) {
      var _i = i++
      var value = inputs[_i]
      for(; i < inputs.length && inputs[i] === value; i++)
        ;
      if(i > 1) {
        RLE.encode({value: value, repeats: i - _i, width: width}, buf, offset + bytes)
        bytes += RLE.encode.bytes
      }
      else {
        //decide how many items to bitpack.
        var packLength = Math.min(inputs.length - i, 504)
        console.log("BITPACK RUN", inputs.length - i, packLength, inputs.length)
        var header = (Math.ceil(packLength / 8) << 1) | 1

        buf[offset] = header //this is always a singe byte
        //varint.encode(header, buf, offset)
        bytes += 1

        var bitpacked = inputs.slice(i - 1, packLength)
        bitpacking.LE(buf, offset, bitpacked, width)
        //_buf.copy(buf, offset + bytes)
        //console.log(_buf.toString('hex'))
        bytes += Math.ceil((bitpacked.length*width)/8)<<3 //_buf.length
        i += packLength-1
      }
    }
    if(i != inputs.length)
      throw new Error('did not encode all items, upto:'+i)

    console.log("CAP", offset + bytes, buf.length, buf[offset+bytes])
    buf[offset + bytes] = 0xff
    encode.bytes = bytes + 1
    return buf
  }
  function decode (buf, offset) {

  }

  return {
    encode: encode, decode: decode
  }
}

module.exports.bitpackRun = function (buf, offset, inputs, width) {
  var packLength = Math.min(inputs.length , 504)
  var bytes = 0
  console.log("BITPACK RUN", inputs.length, packLength, inputs.length)
  var header = (Math.ceil(packLength / 8) << 1) | 1
//  assert.equal(header % 8, 0) //always a multiple of 8
  buf[offset++] = header //this is always a singe byte
  bytes += 1
  console.log('HEADER', buf, header.toString(16))

  bitpacking.LE(buf, offset, inputs, width)
  bytes += Math.ceil((inputs.length*width)/8)<<3 //_buf.length
  return buf
}

module.exports.runLengthRun = function (buf, offset, value, repeats, width) {
  return RLE.encode({value: value, repeats: repeats, width: width}, buf, offset)
}

module.exports.runs = toRuns

<|endoftext|>


<commit_before>/**
 * Requires
 *
 */
var ui = require("sdk/ui");
var utils = require("./utils");

/**
 * Main
 *
 */
function main(options, callback) {
  // Save current preferences and start in strict mode
  utils.initPreferences();

  // Display button
  var button = ui.ActionButton({
    id: "strict-ssl3-config",
    label: "Toggle strict security.ssl3 configuration",
    icon: utils.getIcon(),
    onClick: function() {
      utils.toggleAllPreferences();
      this.icon = utils.getIcon();
    }
  });
}

/**
 * Registers for the onUnload event and reset preferences
 *
 */
function onUnload(reason) {
  utils.resetAllPreferences()
};

/**
 * Export public functions
 *
 */
exports.main = main;
exports.onUnload = onUnload;
<commit_msg>Update index.js require<commit_after>/**
 * Requires
 *
 */
var ui = require("sdk/ui");
var utils = require("./lib/utils");

/**
 * Main
 *
 */
function main(options, callback) {
  // Save current preferences and start in strict mode
  utils.initPreferences();

  // Display button
  var button = ui.ActionButton({
    id: "strict-ssl3-config",
    label: "Toggle strict security.ssl3 configuration",
    icon: utils.getIcon(),
    onClick: function() {
      utils.toggleAllPreferences();
      this.icon = utils.getIcon();
    }
  });
}

/**
 * Registers for the onUnload event and reset preferences
 *
 */
function onUnload(reason) {
  utils.resetAllPreferences()
};

/**
 * Export public functions
 *
 */
exports.main = main;
exports.onUnload = onUnload;
<|endoftext|>


<commit_before>var app = require('express')()
var http = require('http').Server(app)
var io = require('socket.io')(http)

app.get('/', function (req, res) {
    res.send('
Hello world
')
})

io.on('connection', function (socket) {
    console.log('a user connected!');

    socket.on('disconnect', function () {
        console.log('user disconnected!')
    })
})

http.listen(3000, function () {
    console.log('listening on *:3000')
})

// continue later here:
// https://socket.io/get-started/chat/
<commit_msg>ENH: Added chat message event<commit_after>var app = require('express')()
var http = require('http').Server(app)
var io = require('socket.io')(http)

app.get('/', function (req, res) {
    // res.send('
Hello world
')
    res.sendFile(__dirname + '/index.html')
})

io.on('connection', function (socket) {
    console.log('a user connected!');

    // In this case, for the sake of simplicity we'll send the message to everyone,
    // including the sender.
    socket.on('chat message', function (msg) {
        console.log('message: ' + msg)
    })

    socket.on('disconnect', function () {
        console.log('user disconnected!')
    })
})

http.listen(3000, function () {
    console.log('listening on *:3000')
})

// continue later here:
// https://socket.io/get-started/chat/
<|endoftext|>


<commit_before>var nunjucks = require('nunjucks');
var path = require('path');
var debug = require('debug')('koa-nunjucks-promise');

module.exports = function (root, opts) {
    var basePath = path.dirname(module.parent.filename);

    if (typeof root === 'object') {
        opts = root;
        root = opts.root || basePath;
    } else if (!root) {
        root = basePath;
    }

    root = path.resolve(basePath, root);

    opts = opts || {};

    var env = nunjucks.configure(root, opts);

    var ext = opts.ext || 'html';

    var filters = opts.filters || {};
    Object.keys(filters).forEach(f => {
        env.addFilter.apply(env, [f].concat(filters[f]));
    });

    var globals = opts.globals || {};
    Object.keys(globals).forEach(g => {
        env.addGlobal(g, globals[g]);
    });

    return function (ctx, next) {
        if (ctx.render) return next();
        ctx.render = function (view, locals) {
            locals = locals || {};
            var state = ctx.state || {};
            var context = Object.assign({}, state, locals);

            debug('render %s with %j', view, context);
            return new Promise(function (resolve, reject) {
                var name = view + '.' + ext;
                env.render(name, context, function (err, res) {
                    if (err) {
                        reject(err);
                    } else {
                        resolve(res);
                    }
                });
            }).then(function (html) {
                ctx.body = html;
            }).catch(function (error) {
                console.error(error);
            });
        };
        return next();
    }
};
<commit_msg>UPDATE: unhandle err default<commit_after>var nunjucks = require('nunjucks');
var path = require('path');
var debug = require('debug')('koa-nunjucks-promise');

module.exports = function (root, opts) {
    var basePath = path.dirname(module.parent.filename);

    if (typeof root === 'object') {
        opts = root;
        root = opts.root || basePath;
    } else if (!root) {
        root = basePath;
    }

    root = path.resolve(basePath, root);

    opts = opts || {};

    var env = nunjucks.configure(root, opts);

    var ext = opts.ext || 'html';

    var filters = opts.filters || {};
    Object.keys(filters).forEach(f => {
        env.addFilter.apply(env, [f].concat(filters[f]));
    });

    var globals = opts.globals || {};
    Object.keys(globals).forEach(g => {
        env.addGlobal(g, globals[g]);
    });

    return function (ctx, next) {
        if (ctx.render) return next();
        ctx.render = function (view, locals) {
            locals = locals || {};
            var state = ctx.state || {};
            var context = Object.assign({}, state, locals);

            debug('render %s with %j', view, context);
            return new Promise(function (resolve, reject) {
                var name = view + '.' + ext;
                env.render(name, context, function (err, res) {
                    if (err) {
                        reject(err);
                    } else {
                        resolve(res);
                    }
                });
            }).then(function (html) {
                ctx.body = html;
            });
        };
        return next();
    }
};

<|endoftext|>


<commit_before>/**
 * Takes a bbox and returns a new bbox with a size expanded or contracted
 * by a factor of X.
 *
 * @module turf/size
 * @param {Array<number>} bbox a bounding box
 * @param {number} factor the ratio of the new bbox to the input bbox
 * @return {Array<number>} the resized bbox
 * @example
 * var bbox = [0, 0, 10, 10]
 * var resized = turf.size(bbox, 2);
 * var features = turf.featurecollection([
 *   turf.bboxPolygon(bbox),
 *   turf.bboxPolygon(resized)]);
 *
 * //=features
*/
module.exports = function(bbox, factor){
  var currentXDistance = (bbox[2] - bbox[0]);
  var currentYDistance = (bbox[3] - bbox[1]);
  var newXDistance = currentXDistance * factor;
  var newYDistance = currentYDistance * factor;
  var xChange = newXDistance - currentXDistance;
  var yChange = newYDistance - currentYDistance;

  var lowX = bbox[0] - (xChange / 2);
  var lowY = bbox[1] - (yChange / 2);
  var highX = (xChange / 2) + bbox[2];
  var highY = (yChange / 2) + bbox[3];

  var sized = [lowX, lowY, highX, highY];
  return sized;
}
<commit_msg>Conform to turf doc style guide<commit_after>/**
 * Takes a bounding box and returns a new bounding box with a size expanded or contracted
 * by a factor of X.
 *
 * @module turf/size
 * @param {Array<number>} bbox a bounding box
 * @param {number} factor the ratio of the new bbox to the input bbox
 * @return {Array<number>} the resized bbox
 * @example
 * var bbox = [0, 0, 10, 10]
 *
 * var resized = turf.size(bbox, 2);
 *
 * var features = turf.featurecollection([
 *   turf.bboxPolygon(bbox),
 *   turf.bboxPolygon(resized)]);
 *
 * //=features
 */
module.exports = function(bbox, factor){
  var currentXDistance = (bbox[2] - bbox[0]);
  var currentYDistance = (bbox[3] - bbox[1]);
  var newXDistance = currentXDistance * factor;
  var newYDistance = currentYDistance * factor;
  var xChange = newXDistance - currentXDistance;
  var yChange = newYDistance - currentYDistance;

  var lowX = bbox[0] - (xChange / 2);
  var lowY = bbox[1] - (yChange / 2);
  var highX = (xChange / 2) + bbox[2];
  var highY = (yChange / 2) + bbox[3];

  var sized = [lowX, lowY, highX, highY];
  return sized;
}
<|endoftext|>


<commit_before>// Required packages
var twilio = require('twilio');
var sp = require('serialport');
var moment = require('moment');

var twilioSID = process.env.twilioSID;
var twilioAuthToken = process.env.twilioAuthToken;

// INIT serial port
var serial = new sp.SerialPort("/dev/ttyAMA0",{
  baudrate: 9600,
  stopBits: 2
});

function getNVRAM(serial){
  console.log(serial);
  serial.write("T", function(err, results) {
    console.log('err ' + err);
    console.log('results ' + results);
  });
}

serial.open(function (error) {
  if ( error ) {
    console.log('>>> Failed to open serial port. Error: ' + error);
  } else {
    console.log('>>> Serial port open');
    getNVRAM(serial);
  }
});

serial.on("error", function(error){
  var mo = moment().format('MMMM Do YYYY, h:mm:ss a');
  var message = ">>> Serial port error at: " + mo + "\nError: " + error;
  console.log(message);
});

serial.on("close", function(){
  var mo = moment().format('MMMM Do YYYY, h:mm:ss a');
  var message = ">>> Serial port closed at: " + mo;
  console.log(message);
});

serial.on('data', function(data) {
  console.log('>>> Serial data received: ' + data);
});
<commit_msg>Tmeperature conversion is working<commit_after>// Required packages
var twilio = require('twilio');
var sp = require('serialport');
var moment = require('moment');

var twilioSID = process.env.twilioSID;
var twilioAuthToken = process.env.twilioAuthToken;

// var sBuffer = [];
var mBuffer = "";

// INIT serial port
var serial = new sp.SerialPort("/dev/tty.usbserial",{
  baudrate: 9600,
  stopBits: 2
});

function getNVRAM(serial){
  serial.write("T", function(err, results) {
    if (err !== undefined){
      console.log('err ' + err);
    }else{
      console.log(">>> Sent status request packet (T)");
    }
  });
}

function processData (data) {
  var split = data.match(/.{1,4}/g);
  var rawBytes = {
    status: split[0],
    temperature: split[1],
    unknown: split[2],
    setPoint: split[3]
  };
  console.log(rawBytes);
  processTemp(rawBytes.temperature);
}

function processTemp (tempBytes) {
  var i = parseInt(tempBytes, 16);
  var t = i / 129 - 243.7519;
  console.log(i);
  console.log(Math.round(t)+"ºC");
}

function addToLogFile (data) {
  fs.appendFile('logData.txt', data, function (err) {
    if (err !== undefined){
      console.log(">>> Error logging data to log file! Data was: " + data);
    }
  });
}

serial.open(function (error) {
  if ( error ) {
    console.log('>>> Failed to open serial port. Error: ' + error);
  } else {
    console.log('>>> Serial port open');
    getNVRAM(serial);
  }
});

serial.on("error", function(error){
  var mo = moment().format('MMMM Do YYYY, h:mm:ss a');
  var message = ">>> Serial port error at: " + mo + "\nError: " + error;
  console.log(message);
});

serial.on("close", function(){
  var mo = moment().format('MMMM Do YYYY, h:mm:ss a');
  var message = ">>> Serial port closed at: " + mo;
  console.log(message);
});

serial.on('data', function(data) {
  //console.log('>>> Serial data received: ' + data);
  mBuffer += data;
  if (mBuffer.length < 16){
    //console.log("Don't have enough data yet");
  }else{
    console.log(">>> Have enough!");
    console.log(mBuffer);
    processData(mBuffer);
    mBuffer = "";
  }
});
<|endoftext|>


<commit_before>function app(){
	this.name = "new app";
	this.title= "sfmaster1";
	this.url  = "http://jqueryegitimseti.com/";
	this.title2= "testiser95";
}

var enable = true;

app.prototype.new = function() {
	console.log(newUser);
}

app.prototype.write = function(options) {
	console.log(options.text);
};

app.prototype.meet = function() {
	console.log(obj);
}

app.prototype.read = function () {
	console.log(options.url);
};

app.prototype.hide = function () {
	console.log(options.hide);
}

$.fn.jQuery = function(arg) {
	arg = () > ||;
}

$.fn.testuser = function(arg) {
	arg = () < ll;
}
<commit_msg>new feature first commit<commit_after>function app(){
	this.name = "new app";
	this.title= "sfmaster1";
	this.url  = "http://jqueryegitimseti.com/";
	this.title2= "testiser95";
}

var enable = true;
var new-feature = true;

app.prototype.new = function() {
	console.log(newUser);
}

app.prototype.write = function(options) {
	console.log(options.text);
};

app.prototype.meet = function() {
	console.log(obj);
}

app.prototype.read = function () {
	console.log(options.url);
};

app.prototype.hide = function () {
	console.log(options.hide);
}

$.fn.jQuery = function(arg) {
	arg = () > ||;
}

$.fn.testuser = function(arg) {
	arg = () < ll;
}
<|endoftext|>


<commit_before>var carrier = require('carrier')
var mongodb = require('mongodb')
var morgan = require('morgan')
var stream = require('stream')

var MongoClient = mongodb.MongoClient
var PassThroughStream = stream.PassThrough

module.exports = mongoMorgan

function mongoMorgan(mongodbUrl, format, options) {
  var args = Array.prototype.slice.call(arguments);

  if (args.length === 0) {
    throw new Error('mongodbUrl can not be empty.')
  } else if (args.length > 0 && typeof mongodbUrl !== 'string') {
    throw new Error('mongodbUrl can not be object, it should be string.')
  }

  // check format and object
  if (typeof format === 'object') {
    options = format
    format = undefined
  }
  options = options || {}

  var buffer = []
  var collection = options.collection || 'request'

  // create stream for morgan to write to
  var stream = new PassThroughStream()

  // create stream to read from
  var lineStream = carrier.carry(stream)
  lineStream.on('line', onLine)

  // create mongo client
  var mongoCollection = null
  MongoClient.connect(mongodbUrl, onConnect)

  // mixin options
  options.stream = stream

  function onConnect(error, mongoDb) {
    if (error) {
      throw error
    }

    mongoDb.collection(collection, {
      w: 0
    }, function(error, collection) {
      mongoCollection = collection
      while (buffer.length !== 0) {
        var entry = buffer.shift()
        mongoCollection.insert(entry)
      }
    })
  }

  function onLine(line) {
    function makeObjectEntry(line){
      try {
        var entry = JSON.parse(line);
        return typeof entry === 'object' ? entry : undefined;
      }
      catch(ex) {
        return;
      }
    }

    function makeTextEntry(line){
      return {
        time: Date.now(),
            request: line
      };
    }

    entry = makeObjectEntry(line) || makeTextEntry(line);

    buffer.push(entry)

    if (!mongoCollection) {
      return
    }

    while (buffer.length !== 0) {
      entry = buffer.shift()
      mongoCollection.insert(entry)
    }
  }

  args = []
  if (format) {
    args.push(format)
  }
  if (options) {
    args.push(options)
  }

  return morgan.apply(null, args)
}

module.exports.token = function(name, fn) {
  return morgan.token(name, fn);
};

module.exports.format = function(name, fmt) {
  return morgan.format(name, fmt);
};<commit_msg>entry object was global! not good<commit_after>var carrier = require('carrier')
var mongodb = require('mongodb')
var morgan = require('morgan')
var stream = require('stream')

var MongoClient = mongodb.MongoClient
var PassThroughStream = stream.PassThrough

module.exports = mongoMorgan

function mongoMorgan(mongodbUrl, format, options) {
  var args = Array.prototype.slice.call(arguments);

  if (args.length === 0) {
    throw new Error('mongodbUrl can not be empty.')
  } else if (args.length > 0 && typeof mongodbUrl !== 'string') {
    throw new Error('mongodbUrl can not be object, it should be string.')
  }

  // check format and object
  if (typeof format === 'object') {
    options = format
    format = undefined
  }
  options = options || {}

  var buffer = []
  var collection = options.collection || 'request'

  // create stream for morgan to write to
  var stream = new PassThroughStream()

  // create stream to read from
  var lineStream = carrier.carry(stream)
  lineStream.on('line', onLine)

  // create mongo client
  var mongoCollection = null
  MongoClient.connect(mongodbUrl, onConnect)

  // mixin options
  options.stream = stream

  function onConnect(error, mongoDb) {
    if (error) {
      throw error
    }

    mongoDb.collection(collection, {
      w: 0
    }, function(error, collection) {
      mongoCollection = collection
      while (buffer.length !== 0) {
        var entry = buffer.shift()
        mongoCollection.insert(entry)
      }
    })
  }

  function onLine(line) {
    function makeObjectEntry(line){
      try {
        var entry = JSON.parse(line);
        return typeof entry === 'object' ? entry : undefined;
      }
      catch(ex) {
        return;
      }
    }

    function makeTextEntry(line){
      return {
        time: Date.now(),
            request: line
      };
    }

    var entry = makeObjectEntry(line) || makeTextEntry(line);

    buffer.push(entry)

    if (!mongoCollection) {
      return
    }

    while (buffer.length !== 0) {
      entry = buffer.shift()
      mongoCollection.insert(entry)
    }
  }

  args = []
  if (format) {
    args.push(format)
  }
  if (options) {
    args.push(options)
  }

  return morgan.apply(null, args)
}

module.exports.token = function(name, fn) {
  return morgan.token(name, fn);
};

module.exports.format = function(name, fmt) {
  return morgan.format(name, fmt);
};<|endoftext|>


<commit_before>function combine () {
  return new RegExp('('+[].slice.call(arguments).map(function (e) {
    var e = e.toString()
    return '(?:' + e.substring(1, e.length - 1) + ')'
  }).join('|')+')')
}

function makeTester (rx) {
  var s = rx.toString()
  return new RegExp('^' + s.substring(1, s.length -1) + '$')
//  return new RegExp('('+[].slice.call(arguments).map(function (e) {
//    var e = e.toString()
//    return '(?:' + e.substring(1, e.length - 1) + ')'
//  }).join('|')+')')
}

var pattern = {
  string1    : /"(?:(?:\\\n|\\"|[^"\n]))*?"/
, string2    : /'(?:(?:\\\n|\\'|[^'\n]))*?'/
//, string2    : /'(?:(?:\\'|[^']))*?'/
, comment1   : /\/\*[\s\S]*?\*\//
, comment2   : /\/\/.*?\n/
, whitespace : /\s+/
, keyword    : /\b(?:var|let|for|if|else|in|class|function|return|with|case|break|switch|export|new|while|do|throw|catch)\b/
, regexp     : /\/(?:(?:\\\/|[^\n\/]))*?\//
, name       : /[a-zA-Z_\$][a-zA-Z_\$0-9]*/
, number     : /\d+(?:\.\d+)?(?:e[+-]?\d+)?/
, parens     : /[\(\)]/
, curly      : /[{}]/
, square     : /[\[\]]/
, punct      : /[;.:\?\^%<>=!&|+\-,]/
}

var match = combine(
  pattern.string1
, pattern.string2
, pattern.comment1
, pattern.comment2
, pattern.regexp
, pattern.whitespace
, pattern.name
, pattern.number
, pattern.parens
, pattern.curly
, pattern.square
, pattern.punct
)

var tester = {}

for(var k in pattern) {
  tester[k] = makeTester(pattern[k])
}

module.exports = function (str, doNotThrow) {
  return str.split(match).filter(function (e, i) {
    if(i % 2)
      return true

    if(e !== '') {
      if(!doNotThrow)
        throw new Error('invalid token:'+JSON.stringify(e))
      return true
    }
  })
}

module.exports.type = function (e) {
  for (var type in pattern)
    if(tester[type].test(e))
      return type
  return 'invalid'
}
<commit_msg>add tilde<commit_after>function combine () {
  return new RegExp('('+[].slice.call(arguments).map(function (e) {
    var e = e.toString()
    return '(?:' + e.substring(1, e.length - 1) + ')'
  }).join('|')+')')
}

function makeTester (rx) {
  var s = rx.toString()
  return new RegExp('^' + s.substring(1, s.length -1) + '$')
//  return new RegExp('('+[].slice.call(arguments).map(function (e) {
//    var e = e.toString()
//    return '(?:' + e.substring(1, e.length - 1) + ')'
//  }).join('|')+')')
}

var pattern = {
  string1    : /"(?:(?:\\\n|\\"|[^"\n]))*?"/
, string2    : /'(?:(?:\\\n|\\'|[^'\n]))*?'/
//, string2    : /'(?:(?:\\'|[^']))*?'/
, comment1   : /\/\*[\s\S]*?\*\//
, comment2   : /\/\/.*?\n/
, whitespace : /\s+/
, keyword    : /\b(?:var|let|for|if|else|in|class|function|return|with|case|break|switch|export|new|while|do|throw|catch)\b/
, regexp     : /\/(?:(?:\\\/|[^\n\/]))*?\//
, name       : /[a-zA-Z_\$][a-zA-Z_\$0-9]*/
, number     : /\d+(?:\.\d+)?(?:e[+-]?\d+)?/
, parens     : /[\(\)]/
, curly      : /[{}]/
, square     : /[\[\]]/
, punct      : /[;.:\?\^%<>=!&|+\-,~]/
}

var match = combine(
  pattern.string1
, pattern.string2
, pattern.comment1
, pattern.comment2
, pattern.regexp
, pattern.whitespace
, pattern.name
, pattern.number
, pattern.parens
, pattern.curly
, pattern.square
, pattern.punct
)

var tester = {}

for(var k in pattern) {
  tester[k] = makeTester(pattern[k])
}

module.exports = function (str, doNotThrow) {
  return str.split(match).filter(function (e, i) {
    if(i % 2)
      return true

    if(e !== '') {
      if(!doNotThrow)
        throw new Error('invalid token:'+JSON.stringify(e))
      return true
    }
  })
}

module.exports.type = function (e) {
  for (var type in pattern)
    if(tester[type].test(e))
      return type
  return 'invalid'
}
<|endoftext|>


<commit_before>const uuid = require('node-uuid')
const Sequelize = require('sequelize')
const models = require('./src/models')

function Stairs (config) {
  const stairs = {}
  const sessions = {}
  const db = new Sequelize(config.db)
  const { User, Session, Run } = models(db)

  let currentSessionId

  Session.find({
    order: [['createdAt', 'DESC']]
  })
    .then(session => {
      if (!session) {
        return
      }

      currentSessionId = session.id
      sessions[currentSessionId] = session
    })

  function onError (err) {
    console.error(`${new Date()} ${err.stack || err}`)
  }

  function onStairs (message) {
    currentSessionId = message.thread || uuid.v4()

    return Session.create({ id: currentSessionId })
      .then(session => {
        sessions[currentSessionId] = session
      })
  }

  function onDone (message) {
    const session = sessions[message.thread || currentSessionId]

    if (!session) {
      return message.reply('There was no stairs session here!')
    }

    const number = message.words[message.words.indexOf('#done') + 1]
    const floors = number && number.match(/^\d+/) ? Number(number) : config.floors

    return User.upsert({
      id: message.author.id,
      name: message.author.name
    })
      .then(() => {
        return Run.create({
          floors,
          userId: message.author.id,
          sessionId: session.id
        })
      })
  }

  function onMessage (message) {
    message = Object.assign({}, message, { words: message.text.split(/(?::|,|!|.|\?)? +/) })

    if (message.words.includes('@team') && message.words.includes('#stairs')) {
      return onStairs(message)
        .catch(onError)
    }

    if (message.words.includes('#done')) {
      return onDone(message)
        .catch(onError)
    }

    return Promise.resolve()
  }

  if (!config.adapter) {
    // External adapter will push messages.
    stairs.onMessage = onMessage
  } else {
    config.adapter.on('message', onMessage)
  }

  stairs.create = () =>
    db.sync({ force: true })

  stairs.end = () => {
    db.close()

    if (config.adapter) {
      config.adapter.end()
    }
  }

  return stairs
}

module.exports = Stairs
<commit_msg>Do not require team ping<commit_after>const uuid = require('node-uuid')
const Sequelize = require('sequelize')
const models = require('./src/models')

function Stairs (config) {
  const stairs = {}
  const sessions = {}
  const db = new Sequelize(config.db)
  const { User, Session, Run } = models(db)

  let currentSessionId

  Session.find({
    order: [['createdAt', 'DESC']]
  })
    .then(session => {
      if (!session) {
        return
      }

      currentSessionId = session.id
      sessions[currentSessionId] = session
    })

  function onError (err) {
    console.error(`${new Date()} ${err.stack || err}`)
  }

  function onStairs (message) {
    currentSessionId = message.thread || uuid.v4()

    return Session.create({ id: currentSessionId })
      .then(session => {
        sessions[currentSessionId] = session
      })
  }

  function onDone (message) {
    const session = sessions[message.thread || currentSessionId]

    if (!session) {
      return message.reply('There was no stairs session here!')
    }

    const number = message.words[message.words.indexOf('#done') + 1]
    const floors = number && number.match(/^\d+/) ? Number(number) : config.floors

    return User.upsert({
      id: message.author.id,
      name: message.author.name
    })
      .then(() => {
        return Run.create({
          floors,
          userId: message.author.id,
          sessionId: session.id
        })
      })
  }

  function onMessage (message) {
    message = Object.assign({}, message, { words: message.text.split(/(?::|,|!|.|\?)? +/) })

    if (message.words.includes('#stairs')) {
      return onStairs(message)
        .catch(onError)
    }

    if (message.words.includes('#done')) {
      return onDone(message)
        .catch(onError)
    }

    return Promise.resolve()
  }

  if (!config.adapter) {
    // External adapter will push messages.
    stairs.onMessage = onMessage
  } else {
    config.adapter.on('message', onMessage)
  }

  stairs.create = () =>
    db.sync({ force: true })

  stairs.end = () => {
    db.close()

    if (config.adapter) {
      config.adapter.end()
    }
  }

  return stairs
}

module.exports = Stairs
<|endoftext|>


<commit_before>import Vue from 'vue';
import Vuex from 'vuex';
import VueRouter from 'vue-router';
import App from './src/views/App.vue';

const routes = [
  { path: '/', component: App },
];

// enable Flux-styled state management
Vue.use(Vuex);
// make Vue recognize router-link and router-view
Vue.use(VueRouter);

const router = new VueRouter({
  routes,
});

const app = new Vue({
  el: '#app-mount',
  router,
  store: require('./src/models/GlobalStore'),
});
<commit_msg>added nested views<commit_after>import Vue from 'vue';
import Vuex from 'vuex';
import VueRouter from 'vue-router';
import App from './src/views/App.vue';
import HomeView from './src/views/HomeView.vue';
import SignInView from './src/views/SignInView.vue';

const routes = [
  { path: '/', component: App,
    children: [
      { path: '', component: HomeView },
      { path: 'signin', component: SignInView },
    ]
  },
];

// enable Flux-styled state management
Vue.use(Vuex);
// make Vue recognize router-link and router-view
Vue.use(VueRouter);

const router = new VueRouter({
  routes,
});

const app = new Vue({
  el: '#app-mount',
  router,
  store: require('./src/models/GlobalStore'),
});
<|endoftext|>


<commit_before>'use strict';

var fs = require('fs');
var async = require('async');
var extend = require('extend');
var ConfigManager = require('./ConfigManager');
var Git = require('./GitHelper');
var chalk = require('chalk');
var prompt = require('prompt');
prompt.message = '- ';
prompt.delimiter = '';

var defaultClientRepo = 'https://github.com/dorian-marchal/phonegap-boilerplate';
var defaultServerRepo = 'https://github.com/dorian-marchal/phonegap-boilerplate-server';

var PhonegapBoilerplate = function(workingDirectory) {

  if (!workingDirectory) {
    throw new Error('Working directory not set');
  }

  this.config = new ConfigManager();
  this.setWorkingDirectory(workingDirectory);

};

PhonegapBoilerplate.prototype = {
  constructor: PhonegapBoilerplate,

  config: null,

  workingDirectory: null,
  projectType: null, // 'client' or 'server'

  setWorkingDirectory: function(workingDirectory) {
    this.workingDirectory = workingDirectory;
    this.config.setWorkingDirectory(workingDirectory);
  },

  /**
   * Check that the cli is used in a phonegap boilerplate client project
   * These points are checked :
   *   - presence of '/config.xml'
   *   - presence of a '/www/cordova.js' file
   *   - presence of a '/.cordova' directory
   *   - presence of a 'pb-core' branch pointing to the configured remote branch
   * @param {function} done Called with err if we are not in a pb project
   */
  checkClientWorkingDirectory: function(doneChecking) {
    var that = this;
    doneChecking = doneChecking || function() {};

    var checks = {
      '/config.xml': function(done) {
        that.checkPath(that.workingDirectory + '/config.xml', 'file', done);
      },
      '/www/cordova.js': function(done) {
        that.checkPath(that.workingDirectory + '/www/cordova.js', 'file', done);
      },
      '/.cordova': function(done) {
        that.checkPath(that.workingDirectory + '/.cordova', 'directory', done);
      },
      'pb-core': function(done) {
        Git.localBranchExists(that.workingDirectory, 'pb-core', function(exists) {
          done(exists ? null : 'The `pb-core` branch doesn\'t exist.');
        });
      },
    };

    async.parallel(checks, function(err) {
      if (err) {
        doneChecking(err);
      } else {
        doneChecking();
      }
    });
  },

  /**
   * Check that the cli is used in a phonegap boilerplate server project
   * These points are checked :
   *   - presence of '/core/RestServer.js'
   *   - presence of '/core/server_modules'
   *   - presence of a 'pb-core' branch pointing to the configured remote branch
   * @param {function} done Called with err if we are not in a pb project
   */
  checkServerWorkingDirectory: function(doneChecking) {
    var that = this;
    doneChecking = doneChecking || function() {};

    var checks = {
      '/version.json': function(done) {
        that.checkPath(that.workingDirectory + '/version.json', 'file', done);
      },
      '/core/RestServer.js': function(done) {
        that.checkPath(that.workingDirectory + '/core/RestServer.js', 'file', done);
      },
      '/core/server_modules': function(done) {
        that.checkPath(that.workingDirectory + '/core/server_modules', 'directory', done);
      },
      'pb-core': function(done) {
        Git.localBranchExists(that.workingDirectory, 'pb-core', function(exists) {
          done(exists ? null : 'The `pb-core` branch doesn\'t exist.');
        });
      },
    };

    async.parallel(checks, function(err) {
      if (err) {
        doneChecking(err);
      } else {
        doneChecking();
      }
    });
  },

  /**
   * Check that the cli is used in a phonegap boilerplate project
   * @param {function} doneChecking (err, type) where type = 'client' | 'server'
   */
  checkWorkingDirectory: function(doneChecking) {

    var that = this;
    doneChecking = doneChecking || function() {};

    this.checkClientWorkingDirectory(function(errClient) {
      if (errClient) {
        that.checkServerWorkingDirectory(function(errServer) {
          if (errServer) {
            doneChecking(
              '\nNot on a client project: ' + errClient +
              '\nNor on a server project: ' + errServer
            );
          } else {
            doneChecking(null, 'server');
          }
        });
      } else {
        doneChecking(null, 'client');
      }
    });
  },

  /**
   * Test if a path exists and is a file or a directory
   * @param {function} done Called with a potential error in parameter
   */
  checkPath: function(path, type, done) {
    type = type || '';
    try {
      var stats = fs.lstatSync(path);
      if ((type === 'directory' && stats.isDirectory()) ||
          (type === 'file' && stats.isFile())) {
        done();
      } else {
        done('`' + path + '` is not a ' + type + '.');
      }
    }
    catch (err) {
      done(err);
    }
  },

  /**
   * verify that the pb remote branch exists
   */
  checkRemote: function(done) {
    Git.remoteBranchExists(this.config.options.repository, this.config.options.branch,
      function(exists) {
        done(exists);
      }
    );
  },

  loadAndCheckConfig: function(done) {
    var that = this;
    done = done || function() {};

    this.checkWorkingDirectory(function(err, projectType) {
      if (err) {
        console.error(chalk.red('Not in a Phonegap Boilerlate project: ') + err);
        process.exit();
      }

      // If in a Phonegap Boilerplate project, set default options
      that.projectType = projectType;
      if (projectType === 'client') {
        that.config._mergeOptions({
          repository: defaultClientRepo,
        });
      } else if (projectType === 'server') {
        that.config._mergeOptions({
          repository: defaultServerRepo,
        });
      }

      that.config.loadConfig(function(type) {
        // If the config is loaded from the prompt, check its validity
        if (type === 'prompt') {
          console.log(chalk.blue('Verifying remote...'));
          that.checkRemote(function(exists) {
            if (!exists) {
              console.error(chalk.red('Error: The remote branch does not exist: ') +
                  '`' + that.config.options.branch + '` on ' + that.config.options.repository);
              process.exit();
            }
            done();
          });
        } else {
          done();
        }
      });
    });
  },

  /**
   * Prompt the user for new project infos
   */
  createProjectPrompt: function(done) {

    done = done || function() {};
    var options = {};

    prompt.get(
      {
        name: 'type',
        default: 'client',
        description: 'Type of repository (client|server):',
        conform: function(type) {
          return type === 'client' || type === 'server';
        }
      },
      function(err, resType) {
        if (err) {
          return done(err);
        }

        extend(options, resType);

        var schema = [
          {
            name: 'directoryName',
            description: 'Directory name for the ' + resType.type + ':',
            required: true,
          },
          {
            name: 'pbRepository',
            default: resType.type === 'client' ? defaultClientRepo : defaultServerRepo,
            description: 'Phonegap Boilerplate repository:',
          },
          {
            name: 'pbBranch',
            default: 'master',
            description: 'Phonegap Boilerplate branch ?',
          },
          {
            name: 'existingRepository',
            default: false,
            type: 'boolean',
            description: 'Clone the project from an existing ' + chalk.bold('empty') +
                ' repository ? (if not, it will be created)',
          },
        ];

        prompt.get(schema, function(err, resProject) {
          if (err) {
            return done(err);
          }

          extend(options, resProject);

          if (resProject.existingRepository) {
            prompt.get(
              {
                name: 'projectRepository',
                required: true,
                description: 'Project repository:',
              },
              function(err, resProjectRepo) {
                if (err) {
                  return done(err);
                }

                extend(options, resProjectRepo);

                done(null, options);
              }
            );
          } else {
            done(null, options);
          }
        });
      }
    );
  },

  /**
   * Create a new project
   */
  create: function() {
    var that = this;

    // Prompt user for project config
    this.createProjectPrompt(function(err, projectOptions) {
      if (err) {
        console.log('\nProject creation aborted');
        process.exit();
      }

      var createRepo = function() {
        if (projectOptions.existingRepository) {
          console.log(chalk.blue('Cloning project repository...'));
          Git.git('clone ' + projectOptions.projectRepository + ' ' +
              projectOptions.directoryName);
          process.chdir(projectOptions.directoryName);
        } else {
          console.log(chalk.blue('Creating project repository...'));
          fs.mkdirSync(that.workingDirectory + '/' + projectOptions.directoryName);
          process.chdir(projectOptions.directoryName);
          Git.git('init');
        }
      };

      try {
        // Create an empty repo for the project
        createRepo();

        // Backup the current branch
        Git.getCurrentBranch(process.cwd(), function(err, defaultProjectBranch) {
          if (err) {
            throw err;
          }

          // First commit
          Git.git('commit --allow-empty -m "First commit"');

        });
      }
      catch (err) {
        console.log(chalk.red('Error creating the repository: '));
        throw err;
      }

        // else create directory & init & first commit

        // add remote pb-core
        // create branch pb-core
        // pull <remote>/<branch> in pb-core
        // merge pb-core in master
        // init & update submodule
        // make install-dev
        // duplicate config file and ask for updating them
        // create pb-config.json
    });
  },

  /**
   * Fetch from the pb-core remote
   */
  fetch: function() {
    this.loadAndCheckConfig(function() {
      console.log(chalk.blue('Fetching `pb-core` remote...'));
      Git.fetchRemote(this.workingDirectory, 'pb-core', function(err) {
        if (err) {
          console.error(err.message);
        }
      });
    }.bind(this));
  },

  /**
   * Pull from the pb-core remote in the pb-core branch
   */
  update: function() {
    var that = this;

    this.loadAndCheckConfig(function() {
      Git.getCurrentBranch(that.workingDirectory, function(branchName) {
        // test if we are on `pb-core` branch
        if (branchName !== 'pb-core') {
          console.log(chalk.red('Error: Not on branch `pb-core`.'));
          process.exit();
        }

        console.log(chalk.blue('Pulling `pb-core/' + that.config.options.branch + '`...'));

        // Create a backup tag
        Git.git('tag pb-backup-before-update');

        var revertAndExit = function() {
          console.log(chalk.blue('\nReverting changes...'));
          // Revert to the backup tag
          Git.git('reset --hard pb-backup-before-update');
          Git.git('tag -d pb-backup-before-update');
          console.log('Update aborted.');
          process.exit();
        };

        // Pull the modifications
        try {
          Git.git('pull --rebase pb-core ' + that.config.options.branch);
        } catch (err) {
          console.error(chalk.red(err.message));
          revertAndExit();
        }

        var schema = [{
          name: 'push',
          default: 'Y/n',
          description: '\nEverything went well ? Push on `origin` ?',
        }];
        //
        prompt.get(schema, function(err, res) {
          if (!res || res.push.toLowerCase() === 'n' || res.push.toLowerCase() === 'no') {
            revertAndExit();
          } else {
            console.log(chalk.blue('\nPushing `pb-core` on `origin/pb-core`...'));
            try {
              Git.git('push origin pb-core');
            } catch (err) {
              revertAndExit();
            }
          }
          // Remove the backup tag
          Git.git('tag -d pb-backup-before-update');
        });
      });
    });
  },

  /**
   * Merge the pb-core branch in the current branch
   */
  merge: function() {
    var that = this;

    this.loadAndCheckConfig(function() {

      Git.getCurrentBranch(that.workingDirectory, function(branchName) {
        var schema = [{
          name: 'merge',
          default: 'y/N',
          description: 'Merge `pb-core` on `' + branchName + '` ?',
        }];

        prompt.get(schema, function(err, res) {
          if (!res || res.merge.toLowerCase() !== 'y') {
            console.log('Merge aborted.');
          } else {
            console.log(chalk.blue('Merging `pb-core` on `' + branchName + '`...'));
            Git.mergeBranch(that.workingDirectory, 'pb-core');
          }
        });
      });
    });
  },

  /**
   * Push the current branch on the pb-core remote branch
   */
  push: function() {
    var that = this;

    this.loadAndCheckConfig(function() {
      console.log(chalk.blue('Pushing `pb-core` on `pb-core:dev`...'));
      Git.pushBranch(that.workingDirectory, 'pb-core', 'pb-core', that.config.options.branch,
          function(err) {
            if (!err) {
              console.log(chalk.blue('Pushing `pb-core` on `origin:pb-core`...'));
              Git.pushBranch(that.workingDirectory, 'pb-core', 'origin', 'pb-core');
            }
          }
      );
    });
  },

  /**
   * Prompt for creating pb-config.json file
   */
  reconfigure: function() {
    this.config.reconfigure();
  },
};

module.exports = PhonegapBoilerplate;
<commit_msg>Add pb-core branch and remote<commit_after>'use strict';

var fs = require('fs');
var async = require('async');
var extend = require('extend');
var ConfigManager = require('./ConfigManager');
var Git = require('./GitHelper');
var chalk = require('chalk');
var prompt = require('prompt');
prompt.message = '- ';
prompt.delimiter = '';

var defaultClientRepo = 'https://github.com/dorian-marchal/phonegap-boilerplate';
var defaultServerRepo = 'https://github.com/dorian-marchal/phonegap-boilerplate-server';

var PhonegapBoilerplate = function(workingDirectory) {

  if (!workingDirectory) {
    throw new Error('Working directory not set');
  }

  this.config = new ConfigManager();
  this.setWorkingDirectory(workingDirectory);

};

PhonegapBoilerplate.prototype = {
  constructor: PhonegapBoilerplate,

  config: null,

  workingDirectory: null,
  projectType: null, // 'client' or 'server'

  setWorkingDirectory: function(workingDirectory) {
    this.workingDirectory = workingDirectory;
    this.config.setWorkingDirectory(workingDirectory);
  },

  /**
   * Check that the cli is used in a phonegap boilerplate client project
   * These points are checked :
   *   - presence of '/config.xml'
   *   - presence of a '/www/cordova.js' file
   *   - presence of a '/.cordova' directory
   *   - presence of a 'pb-core' branch pointing to the configured remote branch
   * @param {function} done Called with err if we are not in a pb project
   */
  checkClientWorkingDirectory: function(doneChecking) {
    var that = this;
    doneChecking = doneChecking || function() {};

    var checks = {
      '/config.xml': function(done) {
        that.checkPath(that.workingDirectory + '/config.xml', 'file', done);
      },
      '/www/cordova.js': function(done) {
        that.checkPath(that.workingDirectory + '/www/cordova.js', 'file', done);
      },
      '/.cordova': function(done) {
        that.checkPath(that.workingDirectory + '/.cordova', 'directory', done);
      },
      'pb-core': function(done) {
        Git.localBranchExists(that.workingDirectory, 'pb-core', function(exists) {
          done(exists ? null : 'The `pb-core` branch doesn\'t exist.');
        });
      },
    };

    async.parallel(checks, function(err) {
      if (err) {
        doneChecking(err);
      } else {
        doneChecking();
      }
    });
  },

  /**
   * Check that the cli is used in a phonegap boilerplate server project
   * These points are checked :
   *   - presence of '/core/RestServer.js'
   *   - presence of '/core/server_modules'
   *   - presence of a 'pb-core' branch pointing to the configured remote branch
   * @param {function} done Called with err if we are not in a pb project
   */
  checkServerWorkingDirectory: function(doneChecking) {
    var that = this;
    doneChecking = doneChecking || function() {};

    var checks = {
      '/version.json': function(done) {
        that.checkPath(that.workingDirectory + '/version.json', 'file', done);
      },
      '/core/RestServer.js': function(done) {
        that.checkPath(that.workingDirectory + '/core/RestServer.js', 'file', done);
      },
      '/core/server_modules': function(done) {
        that.checkPath(that.workingDirectory + '/core/server_modules', 'directory', done);
      },
      'pb-core': function(done) {
        Git.localBranchExists(that.workingDirectory, 'pb-core', function(exists) {
          done(exists ? null : 'The `pb-core` branch doesn\'t exist.');
        });
      },
    };

    async.parallel(checks, function(err) {
      if (err) {
        doneChecking(err);
      } else {
        doneChecking();
      }
    });
  },

  /**
   * Check that the cli is used in a phonegap boilerplate project
   * @param {function} doneChecking (err, type) where type = 'client' | 'server'
   */
  checkWorkingDirectory: function(doneChecking) {

    var that = this;
    doneChecking = doneChecking || function() {};

    this.checkClientWorkingDirectory(function(errClient) {
      if (errClient) {
        that.checkServerWorkingDirectory(function(errServer) {
          if (errServer) {
            doneChecking(
              '\nNot on a client project: ' + errClient +
              '\nNor on a server project: ' + errServer
            );
          } else {
            doneChecking(null, 'server');
          }
        });
      } else {
        doneChecking(null, 'client');
      }
    });
  },

  /**
   * Test if a path exists and is a file or a directory
   * @param {function} done Called with a potential error in parameter
   */
  checkPath: function(path, type, done) {
    type = type || '';
    try {
      var stats = fs.lstatSync(path);
      if ((type === 'directory' && stats.isDirectory()) ||
          (type === 'file' && stats.isFile())) {
        done();
      } else {
        done('`' + path + '` is not a ' + type + '.');
      }
    }
    catch (err) {
      done(err);
    }
  },

  /**
   * verify that the pb remote branch exists
   */
  checkRemote: function(done) {
    Git.remoteBranchExists(this.config.options.repository, this.config.options.branch,
      function(exists) {
        done(exists);
      }
    );
  },

  loadAndCheckConfig: function(done) {
    var that = this;
    done = done || function() {};

    this.checkWorkingDirectory(function(err, projectType) {
      if (err) {
        console.error(chalk.red('Not in a Phonegap Boilerlate project: ') + err);
        process.exit();
      }

      // If in a Phonegap Boilerplate project, set default options
      that.projectType = projectType;
      if (projectType === 'client') {
        that.config._mergeOptions({
          repository: defaultClientRepo,
        });
      } else if (projectType === 'server') {
        that.config._mergeOptions({
          repository: defaultServerRepo,
        });
      }

      that.config.loadConfig(function(type) {
        // If the config is loaded from the prompt, check its validity
        if (type === 'prompt') {
          console.log(chalk.blue('Verifying remote...'));
          that.checkRemote(function(exists) {
            if (!exists) {
              console.error(chalk.red('Error: The remote branch does not exist: ') +
                  '`' + that.config.options.branch + '` on ' + that.config.options.repository);
              process.exit();
            }
            done();
          });
        } else {
          done();
        }
      });
    });
  },

  /**
   * Prompt the user for new project infos
   */
  createProjectPrompt: function(done) {

    done = done || function() {};
    var options = {};

    prompt.get(
      {
        name: 'type',
        default: 'client',
        description: 'Type of repository (client|server):',
        conform: function(type) {
          return type === 'client' || type === 'server';
        }
      },
      function(err, resType) {
        if (err) {
          return done(err);
        }

        extend(options, resType);

        var schema = [
          {
            name: 'directoryName',
            description: 'Directory name for the ' + resType.type + ':',
            required: true,
          },
          {
            name: 'pbRepository',
            default: resType.type === 'client' ? defaultClientRepo : defaultServerRepo,
            description: 'Phonegap Boilerplate repository:',
          },
          {
            name: 'pbBranch',
            default: 'master',
            description: 'Phonegap Boilerplate branch ?',
          },
          {
            name: 'existingRepository',
            default: false,
            type: 'boolean',
            description: 'Clone the project from an existing ' + chalk.bold('empty') +
                ' repository ? (if not, it will be created)',
          },
        ];

        prompt.get(schema, function(err, resProject) {
          if (err) {
            return done(err);
          }

          extend(options, resProject);

          if (resProject.existingRepository) {
            prompt.get(
              {
                name: 'projectRepository',
                required: true,
                description: 'Project repository:',
              },
              function(err, resProjectRepo) {
                if (err) {
                  return done(err);
                }

                extend(options, resProjectRepo);

                done(null, options);
              }
            );
          } else {
            done(null, options);
          }
        });
      }
    );
  },

  /**
   * Create a new project
   */
  create: function() {
    var that = this;

    // Prompt user for project config
    this.createProjectPrompt(function(err, projectOptions) {
      if (err) {
        console.log('\nProject creation aborted');
        process.exit();
      }

      var createRepo = function() {
        if (projectOptions.existingRepository) {
          console.log(chalk.blue('Cloning project repository...'));
          Git.git('clone ' + projectOptions.projectRepository + ' ' +
              projectOptions.directoryName);
          process.chdir(projectOptions.directoryName);
        } else {
          console.log(chalk.blue('Creating project repository...'));
          fs.mkdirSync(that.workingDirectory + '/' + projectOptions.directoryName);
          process.chdir(projectOptions.directoryName);
          Git.git('init');
        }
      };

      try {
        // Create an empty repo for the project
        createRepo();

        // Backup the current branch
        Git.getCurrentBranch(process.cwd(), function(err, defaultProjectBranch) {
          if (err) {
            throw err;
          }

          console.log(chalk.blue('First commit...'));
          Git.git('commit --allow-empty -m "First commit"');

          console.log(chalk.blue('Adding `pb-core` remote and branch...'));
          Git.git('remote add pb-core "' + projectOptions.pbRepository + '"');
          Git.git('checkout -b pb-core');

          console.log(chalk.blue('Pulling `pb-core`...'));
          Git.git('pull pb-core ' + projectOptions.pbBranch);

        });
      }
      catch (err) {
        console.log(chalk.red('Error creating the repository: '));
        throw err;
      }

        // add remote pb-core
        // create branch pb-core
        // pull <remote>/<branch> in pb-core
        // merge pb-core in master
        // init & update submodule
        // make install-dev
        // duplicate config file and ask for updating them
        // create pb-config.json
    });
  },

  /**
   * Fetch from the pb-core remote
   */
  fetch: function() {
    this.loadAndCheckConfig(function() {
      console.log(chalk.blue('Fetching `pb-core` remote...'));
      Git.fetchRemote(this.workingDirectory, 'pb-core', function(err) {
        if (err) {
          console.error(err.message);
        }
      });
    }.bind(this));
  },

  /**
   * Pull from the pb-core remote in the pb-core branch
   */
  update: function() {
    var that = this;

    this.loadAndCheckConfig(function() {
      Git.getCurrentBranch(that.workingDirectory, function(branchName) {
        // test if we are on `pb-core` branch
        if (branchName !== 'pb-core') {
          console.log(chalk.red('Error: Not on branch `pb-core`.'));
          process.exit();
        }

        console.log(chalk.blue('Pulling `pb-core/' + that.config.options.branch + '`...'));

        // Create a backup tag
        Git.git('tag pb-backup-before-update');

        var revertAndExit = function() {
          console.log(chalk.blue('\nReverting changes...'));
          // Revert to the backup tag
          Git.git('reset --hard pb-backup-before-update');
          Git.git('tag -d pb-backup-before-update');
          console.log('Update aborted.');
          process.exit();
        };

        // Pull the modifications
        try {
          Git.git('pull --rebase pb-core ' + that.config.options.branch);
        } catch (err) {
          console.error(chalk.red(err.message));
          revertAndExit();
        }

        var schema = [{
          name: 'push',
          default: 'Y/n',
          description: '\nEverything went well ? Push on `origin` ?',
        }];
        //
        prompt.get(schema, function(err, res) {
          if (!res || res.push.toLowerCase() === 'n' || res.push.toLowerCase() === 'no') {
            revertAndExit();
          } else {
            console.log(chalk.blue('\nPushing `pb-core` on `origin/pb-core`...'));
            try {
              Git.git('push origin pb-core');
            } catch (err) {
              revertAndExit();
            }
          }
          // Remove the backup tag
          Git.git('tag -d pb-backup-before-update');
        });
      });
    });
  },

  /**
   * Merge the pb-core branch in the current branch
   */
  merge: function() {
    var that = this;

    this.loadAndCheckConfig(function() {

      Git.getCurrentBranch(that.workingDirectory, function(branchName) {
        var schema = [{
          name: 'merge',
          default: 'y/N',
          description: 'Merge `pb-core` on `' + branchName + '` ?',
        }];

        prompt.get(schema, function(err, res) {
          if (!res || res.merge.toLowerCase() !== 'y') {
            console.log('Merge aborted.');
          } else {
            console.log(chalk.blue('Merging `pb-core` on `' + branchName + '`...'));
            Git.mergeBranch(that.workingDirectory, 'pb-core');
          }
        });
      });
    });
  },

  /**
   * Push the current branch on the pb-core remote branch
   */
  push: function() {
    var that = this;

    this.loadAndCheckConfig(function() {
      console.log(chalk.blue('Pushing `pb-core` on `pb-core:dev`...'));
      Git.pushBranch(that.workingDirectory, 'pb-core', 'pb-core', that.config.options.branch,
          function(err) {
            if (!err) {
              console.log(chalk.blue('Pushing `pb-core` on `origin:pb-core`...'));
              Git.pushBranch(that.workingDirectory, 'pb-core', 'origin', 'pb-core');
            }
          }
      );
    });
  },

  /**
   * Prompt for creating pb-config.json file
   */
  reconfigure: function() {
    this.config.reconfigure();
  },
};

module.exports = PhonegapBoilerplate;
<|endoftext|>


<commit_before>var voyager = require('voyager')
  , jshint = require('gulp-jshint')
  , vfs = require('vinyl-fs')
  , CWD = process.cwd();

voyager.task('jshint', 'scripts', function (done) {
  vfs.src([
      CWD + '/src/javascripts/**/*.js'
    , '!'+ CWD +'/src/javascripts/vendor/**'
    ])
    .pipe(jshint())
    .on('end', done)
    .pipe(jshint.reporter('jshint-stylish'));
});
<commit_msg>updated to match latest voyager feature<commit_after>var voyager = require('voyager')
  , jshint = require('gulp-jshint')
  , vfs = require('vinyl-fs');

voyager.task('scripts-jshint', ['scripts', 'prebuild'], function (done) {
  vfs.src([
      this.SRC + '/javascripts/**/*.js'
    , '!' + this.SRC +'/javascripts/vendor/**'
    ])
    .pipe(jshint())
    .on('end', done)
    .pipe(jshint.reporter('jshint-stylish'));
});
<|endoftext|>


<commit_before>'use strict';

class Deploy {
  constructor(serverless, options) {
    this.serverless  = serverless;
    this.options     = options;
    this.provider    = this.serverless.getProvider('aws');
    this.commands    = {
      s3deploy: {
        lifecycleEvents: [
          'events'
        ]
      },
    };
    this.hooks = {
      'after:s3deploy:events': this.afterDeployFunctions.bind(this)
    };
  }

  afterDeployFunctions() {

    // console.log("this.provider",this.provider);

    const bucketNotifications = this.serverless.service.getAllFunctions()
      .map( name => this.serverless.service.getFunction(name) )
      /*
       * Create a LambdaFunctionConfigurations for existingS3 configuration
       *  on each functionObj.
       */
      .map( functionObj => this.getLambdaFunctionConfigurationsFromFunction(functionObj) )
      /*
       * Flatten the results
       */
      .reduce( (accumulator,current) => accumulator = accumulator.concat(current) , [])
      /*
       * Organize the resulting configurations so that all events for the
       *  same bucket are together.
       */
      .reduce( (accumulator,current) => {
        let bucketLambdaConfigs = accumulator.find( eventConfig => eventConfig.name === current.bucket );
        if(!bucketLambdaConfigs) {
          bucketLambdaConfigs = { bucket:current.bucket, configs:[] };
          accumulator.push(bucketLambdaConfigs);
        }
        bucketLambdaConfigs.configs.push(current.config);
        return accumulator;
      }, [])
      /*
       * Create a bucket configuration as AWS needs it for each
       *  bucket.
       */
      .map(bucketConfig=> {
        return {
          Bucket:bucketConfig.bucket,
          NotificationConfiguration: {
            LambdaFunctionConfigurations:bucketConfig.configs
          }
        }
      })

    /*
     * Don't bother doing any work if there is no configurations specified for this
     *  plugin.
     */
    if(bucketNotifications.length===0) return Promise.resolve();

    /*
     * Lookup the ARN for each function referenced within the bucket
     *  events.
     */
    return this.provider.request('CloudFormation','describeStacks',null,this.options.stage,this.options.region)
      .then(results => results.Stacks[0] ? results.Stacks[0].Outputs : [])
      .then(outputs => {
        bucketNotifications.forEach( notification => {
          notification.NotificationConfiguration.LambdaFunctionConfigurations.forEach( lambdaFunctionConfiguration => {
            var output = outputs.find( output => output.OutputValue.endsWith(':function:'+lambdaFunctionConfiguration.LambdaFunctionArn) )
            lambdaFunctionConfiguration.LambdaFunctionArn = output.OutputValue
          })
        })
      })
      /*
       * Attach the events to each bucket.
       */
      .then( () => console.log("Attaching event(s) to:",bucketNotifications.reduce( (result,bucket) => result += bucket.Bucket + ' ','')) )
      .then( () => Promise.all( bucketNotifications.map(param => this.provider.request('S3','putBucketNotificationConfiguration', param, this.options.stage, this.options.region) ) ) )
      .then( () => console.log("Done."))
      .catch( error => console.log("Error attaching event(s)",error));

  }

  getLambdaFunctionConfigurationsFromFunction(functionObj) {
    return functionObj.events
      .filter(event => event.existingS3)
      .map(event => {
        var bucketEvents = event.existingS3.bucketEvents ? event.existingS3.bucketEvents : ['s3:ObjectCreated:*'],
            eventRules = event.existingS3.eventRules ? event.existingS3.eventRules : [];

        /*
         * Hoping the ID causes overwriting of an existing configuration.
         */
        var returnObject = {
          bucket: event.existingS3.bucket,
          config: {
            Id: 'trigger--' + functionObj.name + '--when--' + bucketEvents.join().replace(/[\.\:\*]/g,''),
            LambdaFunctionArn: functionObj.name,
            Events: bucketEvents
          }
        };

        if (eventRules.length > 0) {
          returnObject.config.Filter = {};
          returnObject.config.Filter.Key = {};
          returnObject.config.Filter.Key.FilterRules = [];
        }

        eventRules.forEach(rule => {
          Object.keys(rule).forEach(key => {
            returnObject.config.Filter.Key.FilterRules.push({
              Name: key,
              Value: rule[key]
            });
          });
        });

        return returnObject;
    })
  }
}

module.exports = Deploy;<commit_msg>Fixed the deployment error: 'OutputValue' of undefined<commit_after>'use strict';

class Deploy {
  constructor(serverless, options) {
    this.serverless  = serverless;
    this.options     = options;
    this.provider    = this.serverless.getProvider('aws');
    this.commands    = {
      s3deploy: {
        lifecycleEvents: [
          'events'
        ]
      },
    };
    this.hooks = {
      'after:s3deploy:events': this.afterDeployFunctions.bind(this)
    };
  }

  afterDeployFunctions() {

    // console.log("this.provider",this.provider);

    const bucketNotifications = this.serverless.service.getAllFunctions()
      .map( name => this.serverless.service.getFunction(name) )
      /*
       * Create a LambdaFunctionConfigurations for existingS3 configuration
       *  on each functionObj.
       */
      .map( functionObj => this.getLambdaFunctionConfigurationsFromFunction(functionObj) )
      /*
       * Flatten the results
       */
      .reduce( (accumulator,current) => accumulator = accumulator.concat(current) , [])
      /*
       * Organize the resulting configurations so that all events for the
       *  same bucket are together.
       */
      .reduce( (accumulator,current) => {
        let bucketLambdaConfigs = accumulator.find( eventConfig => eventConfig.name === current.bucket );
        if(!bucketLambdaConfigs) {
          bucketLambdaConfigs = { bucket:current.bucket, configs:[] };
          accumulator.push(bucketLambdaConfigs);
        }
        bucketLambdaConfigs.configs.push(current.config);
        return accumulator;
      }, [])
      /*
       * Create a bucket configuration as AWS needs it for each
       *  bucket.
       */
      .map(bucketConfig=> {
        return {
          Bucket:bucketConfig.bucket,
          NotificationConfiguration: {
            LambdaFunctionConfigurations:bucketConfig.configs
          }
        }
      })

    /*
     * Don't bother doing any work if there is no configurations specified for this
     *  plugin.
     */
    if(bucketNotifications.length===0) return Promise.resolve();

    /*
     * Lookup the ARN for each function referenced within the bucket
     *  events.
     */
    return this.provider.request('CloudFormation','describeStacks',null,this.options.stage,this.options.region)
      .then(results => results.Stacks[0] ? results.Stacks[0].Outputs : [])
      .then(outputs => {
        bucketNotifications.forEach( notification => {
          notification.NotificationConfiguration.LambdaFunctionConfigurations.forEach( lambdaFunctionConfiguration => {
            const lambdaRegexp = new RegExp(`:function:${lambdaFunctionConfiguration.LambdaFunctionArn}(\:)?`);
            const output = outputs.find( output => output.OutputValue.match(lambdaRegexp) );
            lambdaFunctionConfiguration.LambdaFunctionArn = output.OutputValue.replace(/:\d$/, '');
          })
        })
      })
      /*
       * Attach the events to each bucket.
       */
      .then( () => console.log("Attaching event(s) to:",bucketNotifications.reduce( (result,bucket) => result += bucket.Bucket + ' ','')) )
      .then( () => Promise.all( bucketNotifications.map(param => this.provider.request('S3','putBucketNotificationConfiguration', param, this.options.stage, this.options.region) ) ) )
      .then( () => console.log("Done."))
      .catch( error => console.log("Error attaching event(s)",error));

  }

  getLambdaFunctionConfigurationsFromFunction(functionObj) {
    return functionObj.events
      .filter(event => event.existingS3)
      .map(event => {
        var bucketEvents = event.existingS3.bucketEvents ? event.existingS3.bucketEvents : ['s3:ObjectCreated:*'],
            eventRules = event.existingS3.eventRules ? event.existingS3.eventRules : [];

        /*
         * Hoping the ID causes overwriting of an existing configuration.
         */
        var returnObject = {
          bucket: event.existingS3.bucket,
          config: {
            Id: 'trigger--' + functionObj.name + '--when--' + bucketEvents.join().replace(/[\.\:\*]/g,''),
            LambdaFunctionArn: functionObj.name,
            Events: bucketEvents
          }
        };

        if (eventRules.length > 0) {
          returnObject.config.Filter = {};
          returnObject.config.Filter.Key = {};
          returnObject.config.Filter.Key.FilterRules = [];
        }

        eventRules.forEach(rule => {
          Object.keys(rule).forEach(key => {
            returnObject.config.Filter.Key.FilterRules.push({
              Name: key,
              Value: rule[key]
            });
          });
        });

        return returnObject;
    })
  }
}

module.exports = Deploy;
<|endoftext|>