<commit_before>/**
 * Command parser
 * Pokemon Showdown - http://pokemonshowdown.com/
 *
 * This is the command parser. Call it with CommandParser.parse
 * (scroll down to its definition for details)
 *
 * Individual commands are put in:
 *   commands.js - "core" commands that shouldn't be modified
 *   config/commands.js - other commands that can be safely modified
 *
 * The command API is (mostly) documented in config/commands.js
 *
 * @license MIT license
 */

/*

To reload chat commands:

/hotpatch chat

*/

const MAX_MESSAGE_LENGTH = 300;

const BROADCAST_COOLDOWN = 20*1000;

const MESSAGE_COOLDOWN = 5*60*1000;

const MAX_PARSE_RECURSION = 10;

var crypto = require('crypto');

var modlog = exports.modlog = modlog || fs.createWriteStream('logs/modlog.txt', {flags:'a+'});

/**
 * Command parser
 *
 * Usage:
 *   CommandParser.parse(message, room, user, connection)
 *
 * message - the message the user is trying to say
 * room - the room the user is trying to say it in
 * user - the user that sent the message
 * connection - the connection the user sent the message from
 *
 * Returns the message the user should say, or a falsy value which
 * means "don't say anything"
 *
 * Examples:
 *   CommandParser.parse("/join lobby", room, user, connection)
 *     will make the user join the lobby, and return false.
 *
 *   CommandParser.parse("Hi, guys!", room, user, connection)
 *     will return "Hi, guys!" if the user isn't muted, or
 *     if he's muted, will warn him that he's muted, and
 *     return false.
 */
var parse = exports.parse = function(message, room, user, connection, levelsDeep) {
	var cmd = '', target = '';
	if (!message || !message.trim().length) return;
	if (!levelsDeep) {
		levelsDeep = 0;
		// if (config.emergencylog && (connection.ip === '62.195.195.62' || connection.ip === '86.141.154.222' || connection.ip === '189.134.175.221' || message.length > 2048 || message.length > 256 && message.substr(0,5) !== '/utm ' && message.substr(0,5) !== '/trn ')) {
		if (config.emergencylog && (user.userid === 'pindapinda' || connection.ip === '62.195.195.62' || connection.ip === '86.141.154.222' || connection.ip === '189.134.175.221')) {
			config.emergencylog.write('<'+user.name+'@'+connection.ip+'> '+message+'\n');
		}
	}

	if (message.substr(0,3) === '>> ') {
		// multiline eval
		message = '/eval '+message.substr(3);
	} else if (message.substr(0,4) === '>>> ') {
		// multiline eval
		message = '/evalbattle '+message.substr(4);
	}

	if (message.substr(0,2) !== '//' && message.substr(0,1) === '/') {
		var spaceIndex = message.indexOf(' ');
		if (spaceIndex > 0) {
			cmd = message.substr(1, spaceIndex-1);
			target = message.substr(spaceIndex+1);
		} else {
			cmd = message.substr(1);
			target = '';
		}
	} else if (message.substr(0,1) === '!') {
		var spaceIndex = message.indexOf(' ');
		if (spaceIndex > 0) {
			cmd = message.substr(0, spaceIndex);
			target = message.substr(spaceIndex+1);
		} else {
			cmd = message;
			target = '';
		}
	}
	cmd = cmd.toLowerCase();
	var broadcast = false;
	if (cmd.charAt(0) === '!') {
		broadcast = true;
		cmd = cmd.substr(1);
	}

	var commandHandler = commands[cmd];
	if (typeof commandHandler === 'string') {
		// in case someone messed up, don't loop
		commandHandler = commands[commandHandler];
	}
	if (commandHandler) {
		var context = {
			sendReply: function(data) {
				if (this.broadcasting) {
					room.add(data, true);
				} else {
					connection.sendTo(room, data);
				}
			},
			sendReplyBox: function(html) {
				this.sendReply('|raw|
'+html+'
');
			},
			popupReply: function(message) {
				connection.popup(message);
			},
			add: function(data) {
				room.add(data, true);
			},
			send: function(data) {
				room.send(data);
			},
			privateModCommand: function(data) {
				for (var i in room.users) {
					if (room.users[i].isStaff) {
						room.users[i].sendTo(room, data);
					}
				}
				this.logEntry(data);
				this.logModCommand(data);
			},
			logEntry: function(data) {
				room.logEntry(data);
			},
			addModCommand: function(text, logOnlyText) {
				this.add(text);
				this.logModCommand(text+(logOnlyText||''));
			},
			logModCommand: function(result) {
				modlog.write('['+(new Date().toJSON())+'] ('+room.id+') '+result+'\n');
			},
			can: function(permission, target, room) {
				if (!user.can(permission, target, room)) {
					this.sendReply('/'+cmd+' - Access denied.');
					return false;
				}
				return true;
			},
			canBroadcast: function() {
				if (broadcast) {
					message = this.canTalk(message);
					if (!message) return false;
					if (!user.can('broadcast', null, room)) {
						connection.sendTo(room, "You need to be voiced to broadcast this command's information.");
						connection.sendTo(room, "To see it for yourself, use: /"+message.substr(1));
						return false;
					}

					// broadcast cooldown
					var normalized = toId(message);
					if (room.lastBroadcast === normalized &&
							room.lastBroadcastTime >= Date.now() - BROADCAST_COOLDOWN) {
						connection.sendTo(room, "You can't broadcast this because it was just broadcast.")
						return false;
					}
					this.add('|c|'+user.getIdentity(room.id)+'|'+message);
					room.lastBroadcast = normalized;
					room.lastBroadcastTime = Date.now();

					this.broadcasting = true;
				}
				return true;
			},
			parse: function(message) {
				if (levelsDeep > MAX_PARSE_RECURSION) {
					return this.sendReply("Error: Too much recursion");
				}
				return parse(message, room, user, connection, levelsDeep+1);
			},
			canTalk: function(message, relevantRoom) {
				var innerRoom = (relevantRoom !== undefined) ? relevantRoom : room;
				return canTalk(user, innerRoom, connection, message);
			},
			targetUserOrSelf: function(target) {
				if (!target) return user;
				this.splitTarget(target);
				return this.targetUser;
			},
			splitTarget: splitTarget
		};

		var result = commandHandler.call(context, target, room, user, connection, cmd, message);
		if (result === undefined) result = false;

		return result;
	} else {
		// Check for mod/demod/admin/deadmin/etc depending on the group ids
		for (var g in config.groups) {
			if (cmd === config.groups[g].id) {
				return parse('/promote ' + toUserid(target) + ',' + g, room, user, connection);
			} else if (cmd === 'de' + config.groups[g].id || cmd === 'un' + config.groups[g].id) {
				var nextGroup = config.groupsranking[config.groupsranking.indexOf(g) - 1];
				if (!nextGroup) nextGroup = config.groupsranking[0];
				return parse('/demote ' + toUserid(target) + ',' + nextGroup, room, user, connection);
			}
		}

		if (message.substr(0,1) === '/' && cmd) {
			// To guard against command typos, we now emit an error message
			return connection.sendTo(room.id, 'The command "/'+cmd+'" was unrecognized. To send a message starting with "/'+cmd+'", type "//'+cmd+'".');
		}
	}

	message = canTalk(user, room, connection, message);
	if (!message) return false;

	return message;
};

function splitTarget(target, exactName) {
	var commaIndex = target.indexOf(',');
	if (commaIndex < 0) {
		targetUser = Users.get(target, exactName)
		this.targetUser = targetUser;
		this.targetUsername = (targetUser?targetUser.name:target);
		return '';
	}
	var targetUser = Users.get(target.substr(0, commaIndex), exactName);
	if (!targetUser) {
		targetUser = null;
	}
	this.targetUser = targetUser;
	this.targetUsername = (targetUser?targetUser.name:target.substr(0, commaIndex));
	return target.substr(commaIndex+1).trim();
}

/**
 * Can this user talk?
 * Shows an error message if not.
 */
function canTalk(user, room, connection, message) {
	if (!user.named) {
		connection.popup("You must choose a name before you can talk.");
		return false;
	}
	if (room && user.locked) {
		connection.sendTo(room, 'You are locked from talking in chat.');
		return false;
	}
	if (room && user.mutedRooms[room.id]) {
		connection.sendTo(room, 'You are muted and cannot talk in this room.');
		return false;
	}
	if (room && room.modchat) {
		if (room.modchat === 'crash') {
			if (!user.can('ignorelimits')) {
				connection.sendTo(room, 'Because the server has crashed, you cannot speak in lobby chat.');
				return false;
			}
		} else {
			var userGroup = user.group;
			if (room.auth) {
				if (room.auth[user.userid]) {
					userGroup = room.auth[user.userid];
				} else if (userGroup !== ' ') {
					userGroup = '+';
				}
			}
			if (!user.autoconfirmed && (room.auth && room.auth[user.userid] || user.group) === ' ' && room.modchat === 'autoconfirmed') {
				connection.sendTo(room, 'Because moderated chat is set, your account must be at least one week old and you must have won at least one ladder game to speak in this chat.');
				return false;
			} else if (config.groupsranking.indexOf(userGroup) < config.groupsranking.indexOf(room.modchat)) {
				var groupName = config.groups[room.modchat].name;
				if (!groupName) groupName = room.modchat;
				connection.sendTo(room, 'Because moderated chat is set, you must be of rank ' + groupName +' or higher to speak in lobby chat.');
				return false;
			}
		}
	}
	if (room && !(user.userid in room.users)) {
		connection.popup("You can't send a message to this room without being in it.");
		return false;
	}

	if (typeof message === 'string') {
		if (!message) {
			connection.popup("Your message can't be blank.");
			return false;
		}
		if (message.length > MAX_MESSAGE_LENGTH && !user.can('ignorelimits')) {
			connection.popup("Your message is too long:\n\n"+message);
			return false;
		}

		// hardcoded low quality website
		if (/\bnimp\.org\b/i.test(message)) return false;

		// remove zalgo
		message = message.replace(/[\u0300-\u036f\u0E2F-\u0E4F]{3,}/g,'');

		if (room && room.id === 'lobby') {
			var normalized = message.trim();
			if ((normalized === user.lastMessage) &&
					((Date.now() - user.lastMessageTime) < MESSAGE_COOLDOWN)) {
				connection.popup("You can't send the same message again so soon.");
				return false;
			}
			user.lastMessage = message;
			user.lastMessageTime = Date.now();
		}

		if (config.chatfilter) {
			return config.chatfilter(user, room, connection.socket, message);
		}
		return message;
	}

	return true;
}

exports.package = {};
fs.readFile('package.json', function(err, data) {
	if (err) return;
	exports.package = JSON.parse(data);
});

exports.uncacheTree = function(root) {
	var uncache = [require.resolve(root)];
	do {
		var newuncache = [];
		for (var i = 0; i < uncache.length; ++i) {
			if (require.cache[uncache[i]]) {
				newuncache.push.apply(newuncache,
					require.cache[uncache[i]].children.map(function(module) {
						return module.filename;
					})
				);
				delete require.cache[uncache[i]];
			}
		}
		uncache = newuncache;
	} while (uncache.length > 0);
};

// This function uses synchronous IO in order to keep it relatively simple.
// The function takes about 0.023 seconds to run on one tested computer,
// which is acceptable considering how long the server takes to start up
// anyway (several seconds).
exports.computeServerVersion = function() {
	/**
	 * `filelist.txt` is a list of all the files in this project. It is used
	 * for computing a checksum of the project for the /version command. This
	 * information cannot be determined at runtime because the user may not be
	 * using a git repository (for example, the user may have downloaded an
	 * archive of the files).
	 *
	 * `filelist.txt` is generated by running `git ls-files > filelist.txt`.
	 */
	var filenames;
	try {
		var data = fs.readFileSync('filelist.txt', {encoding: 'utf8'});
		filenames = data.split('\n');
	} catch (e) {
		return 0;
	}
	var hash = crypto.createHash('md5');
	for (var i = 0; i < filenames.length; ++i) {
		try {
			hash.update(fs.readFileSync(filenames[i]));
		} catch (e) {}
	}
	return hash.digest('hex');
};

exports.serverVersion = exports.computeServerVersion();

/*********************************************************
 * Commands
 *********************************************************/

var commands = exports.commands = require('./commands.js').commands;

var customCommands = require('./config/commands.js');
if (customCommands && customCommands.commands) {
	Object.merge(commands, customCommands.commands);
}
<commit_msg>Fix overly-strict Zalgo filter It was filtering out some legitimate Thai words.<commit_after>/**
 * Command parser
 * Pokemon Showdown - http://pokemonshowdown.com/
 *
 * This is the command parser. Call it with CommandParser.parse
 * (scroll down to its definition for details)
 *
 * Individual commands are put in:
 *   commands.js - "core" commands that shouldn't be modified
 *   config/commands.js - other commands that can be safely modified
 *
 * The command API is (mostly) documented in config/commands.js
 *
 * @license MIT license
 */

/*

To reload chat commands:

/hotpatch chat

*/

const MAX_MESSAGE_LENGTH = 300;

const BROADCAST_COOLDOWN = 20*1000;

const MESSAGE_COOLDOWN = 5*60*1000;

const MAX_PARSE_RECURSION = 10;

var crypto = require('crypto');

var modlog = exports.modlog = modlog || fs.createWriteStream('logs/modlog.txt', {flags:'a+'});

/**
 * Command parser
 *
 * Usage:
 *   CommandParser.parse(message, room, user, connection)
 *
 * message - the message the user is trying to say
 * room - the room the user is trying to say it in
 * user - the user that sent the message
 * connection - the connection the user sent the message from
 *
 * Returns the message the user should say, or a falsy value which
 * means "don't say anything"
 *
 * Examples:
 *   CommandParser.parse("/join lobby", room, user, connection)
 *     will make the user join the lobby, and return false.
 *
 *   CommandParser.parse("Hi, guys!", room, user, connection)
 *     will return "Hi, guys!" if the user isn't muted, or
 *     if he's muted, will warn him that he's muted, and
 *     return false.
 */
var parse = exports.parse = function(message, room, user, connection, levelsDeep) {
	var cmd = '', target = '';
	if (!message || !message.trim().length) return;
	if (!levelsDeep) {
		levelsDeep = 0;
		// if (config.emergencylog && (connection.ip === '62.195.195.62' || connection.ip === '86.141.154.222' || connection.ip === '189.134.175.221' || message.length > 2048 || message.length > 256 && message.substr(0,5) !== '/utm ' && message.substr(0,5) !== '/trn ')) {
		if (config.emergencylog && (user.userid === 'pindapinda' || connection.ip === '62.195.195.62' || connection.ip === '86.141.154.222' || connection.ip === '189.134.175.221')) {
			config.emergencylog.write('<'+user.name+'@'+connection.ip+'> '+message+'\n');
		}
	}

	if (message.substr(0,3) === '>> ') {
		// multiline eval
		message = '/eval '+message.substr(3);
	} else if (message.substr(0,4) === '>>> ') {
		// multiline eval
		message = '/evalbattle '+message.substr(4);
	}

	if (message.substr(0,2) !== '//' && message.substr(0,1) === '/') {
		var spaceIndex = message.indexOf(' ');
		if (spaceIndex > 0) {
			cmd = message.substr(1, spaceIndex-1);
			target = message.substr(spaceIndex+1);
		} else {
			cmd = message.substr(1);
			target = '';
		}
	} else if (message.substr(0,1) === '!') {
		var spaceIndex = message.indexOf(' ');
		if (spaceIndex > 0) {
			cmd = message.substr(0, spaceIndex);
			target = message.substr(spaceIndex+1);
		} else {
			cmd = message;
			target = '';
		}
	}
	cmd = cmd.toLowerCase();
	var broadcast = false;
	if (cmd.charAt(0) === '!') {
		broadcast = true;
		cmd = cmd.substr(1);
	}

	var commandHandler = commands[cmd];
	if (typeof commandHandler === 'string') {
		// in case someone messed up, don't loop
		commandHandler = commands[commandHandler];
	}
	if (commandHandler) {
		var context = {
			sendReply: function(data) {
				if (this.broadcasting) {
					room.add(data, true);
				} else {
					connection.sendTo(room, data);
				}
			},
			sendReplyBox: function(html) {
				this.sendReply('|raw|
'+html+'
');
			},
			popupReply: function(message) {
				connection.popup(message);
			},
			add: function(data) {
				room.add(data, true);
			},
			send: function(data) {
				room.send(data);
			},
			privateModCommand: function(data) {
				for (var i in room.users) {
					if (room.users[i].isStaff) {
						room.users[i].sendTo(room, data);
					}
				}
				this.logEntry(data);
				this.logModCommand(data);
			},
			logEntry: function(data) {
				room.logEntry(data);
			},
			addModCommand: function(text, logOnlyText) {
				this.add(text);
				this.logModCommand(text+(logOnlyText||''));
			},
			logModCommand: function(result) {
				modlog.write('['+(new Date().toJSON())+'] ('+room.id+') '+result+'\n');
			},
			can: function(permission, target, room) {
				if (!user.can(permission, target, room)) {
					this.sendReply('/'+cmd+' - Access denied.');
					return false;
				}
				return true;
			},
			canBroadcast: function() {
				if (broadcast) {
					message = this.canTalk(message);
					if (!message) return false;
					if (!user.can('broadcast', null, room)) {
						connection.sendTo(room, "You need to be voiced to broadcast this command's information.");
						connection.sendTo(room, "To see it for yourself, use: /"+message.substr(1));
						return false;
					}

					// broadcast cooldown
					var normalized = toId(message);
					if (room.lastBroadcast === normalized &&
							room.lastBroadcastTime >= Date.now() - BROADCAST_COOLDOWN) {
						connection.sendTo(room, "You can't broadcast this because it was just broadcast.")
						return false;
					}
					this.add('|c|'+user.getIdentity(room.id)+'|'+message);
					room.lastBroadcast = normalized;
					room.lastBroadcastTime = Date.now();

					this.broadcasting = true;
				}
				return true;
			},
			parse: function(message) {
				if (levelsDeep > MAX_PARSE_RECURSION) {
					return this.sendReply("Error: Too much recursion");
				}
				return parse(message, room, user, connection, levelsDeep+1);
			},
			canTalk: function(message, relevantRoom) {
				var innerRoom = (relevantRoom !== undefined) ? relevantRoom : room;
				return canTalk(user, innerRoom, connection, message);
			},
			targetUserOrSelf: function(target) {
				if (!target) return user;
				this.splitTarget(target);
				return this.targetUser;
			},
			splitTarget: splitTarget
		};

		var result = commandHandler.call(context, target, room, user, connection, cmd, message);
		if (result === undefined) result = false;

		return result;
	} else {
		// Check for mod/demod/admin/deadmin/etc depending on the group ids
		for (var g in config.groups) {
			if (cmd === config.groups[g].id) {
				return parse('/promote ' + toUserid(target) + ',' + g, room, user, connection);
			} else if (cmd === 'de' + config.groups[g].id || cmd === 'un' + config.groups[g].id) {
				var nextGroup = config.groupsranking[config.groupsranking.indexOf(g) - 1];
				if (!nextGroup) nextGroup = config.groupsranking[0];
				return parse('/demote ' + toUserid(target) + ',' + nextGroup, room, user, connection);
			}
		}

		if (message.substr(0,1) === '/' && cmd) {
			// To guard against command typos, we now emit an error message
			return connection.sendTo(room.id, 'The command "/'+cmd+'" was unrecognized. To send a message starting with "/'+cmd+'", type "//'+cmd+'".');
		}
	}

	message = canTalk(user, room, connection, message);
	if (!message) return false;

	return message;
};

function splitTarget(target, exactName) {
	var commaIndex = target.indexOf(',');
	if (commaIndex < 0) {
		targetUser = Users.get(target, exactName)
		this.targetUser = targetUser;
		this.targetUsername = (targetUser?targetUser.name:target);
		return '';
	}
	var targetUser = Users.get(target.substr(0, commaIndex), exactName);
	if (!targetUser) {
		targetUser = null;
	}
	this.targetUser = targetUser;
	this.targetUsername = (targetUser?targetUser.name:target.substr(0, commaIndex));
	return target.substr(commaIndex+1).trim();
}

/**
 * Can this user talk?
 * Shows an error message if not.
 */
function canTalk(user, room, connection, message) {
	if (!user.named) {
		connection.popup("You must choose a name before you can talk.");
		return false;
	}
	if (room && user.locked) {
		connection.sendTo(room, 'You are locked from talking in chat.');
		return false;
	}
	if (room && user.mutedRooms[room.id]) {
		connection.sendTo(room, 'You are muted and cannot talk in this room.');
		return false;
	}
	if (room && room.modchat) {
		if (room.modchat === 'crash') {
			if (!user.can('ignorelimits')) {
				connection.sendTo(room, 'Because the server has crashed, you cannot speak in lobby chat.');
				return false;
			}
		} else {
			var userGroup = user.group;
			if (room.auth) {
				if (room.auth[user.userid]) {
					userGroup = room.auth[user.userid];
				} else if (userGroup !== ' ') {
					userGroup = '+';
				}
			}
			if (!user.autoconfirmed && (room.auth && room.auth[user.userid] || user.group) === ' ' && room.modchat === 'autoconfirmed') {
				connection.sendTo(room, 'Because moderated chat is set, your account must be at least one week old and you must have won at least one ladder game to speak in this chat.');
				return false;
			} else if (config.groupsranking.indexOf(userGroup) < config.groupsranking.indexOf(room.modchat)) {
				var groupName = config.groups[room.modchat].name;
				if (!groupName) groupName = room.modchat;
				connection.sendTo(room, 'Because moderated chat is set, you must be of rank ' + groupName +' or higher to speak in lobby chat.');
				return false;
			}
		}
	}
	if (room && !(user.userid in room.users)) {
		connection.popup("You can't send a message to this room without being in it.");
		return false;
	}

	if (typeof message === 'string') {
		if (!message) {
			connection.popup("Your message can't be blank.");
			return false;
		}
		if (message.length > MAX_MESSAGE_LENGTH && !user.can('ignorelimits')) {
			connection.popup("Your message is too long:\n\n"+message);
			return false;
		}

		// hardcoded low quality website
		if (/\bnimp\.org\b/i.test(message)) return false;

		// remove zalgo
		message = message.replace(/[\u0300-\u036f\u0E31\u0E34-\u0E3A\u0E47-\u0E4E]{3,}/g,'');

		if (room && room.id === 'lobby') {
			var normalized = message.trim();
			if ((normalized === user.lastMessage) &&
					((Date.now() - user.lastMessageTime) < MESSAGE_COOLDOWN)) {
				connection.popup("You can't send the same message again so soon.");
				return false;
			}
			user.lastMessage = message;
			user.lastMessageTime = Date.now();
		}

		if (config.chatfilter) {
			return config.chatfilter(user, room, connection.socket, message);
		}
		return message;
	}

	return true;
}

exports.package = {};
fs.readFile('package.json', function(err, data) {
	if (err) return;
	exports.package = JSON.parse(data);
});

exports.uncacheTree = function(root) {
	var uncache = [require.resolve(root)];
	do {
		var newuncache = [];
		for (var i = 0; i < uncache.length; ++i) {
			if (require.cache[uncache[i]]) {
				newuncache.push.apply(newuncache,
					require.cache[uncache[i]].children.map(function(module) {
						return module.filename;
					})
				);
				delete require.cache[uncache[i]];
			}
		}
		uncache = newuncache;
	} while (uncache.length > 0);
};

// This function uses synchronous IO in order to keep it relatively simple.
// The function takes about 0.023 seconds to run on one tested computer,
// which is acceptable considering how long the server takes to start up
// anyway (several seconds).
exports.computeServerVersion = function() {
	/**
	 * `filelist.txt` is a list of all the files in this project. It is used
	 * for computing a checksum of the project for the /version command. This
	 * information cannot be determined at runtime because the user may not be
	 * using a git repository (for example, the user may have downloaded an
	 * archive of the files).
	 *
	 * `filelist.txt` is generated by running `git ls-files > filelist.txt`.
	 */
	var filenames;
	try {
		var data = fs.readFileSync('filelist.txt', {encoding: 'utf8'});
		filenames = data.split('\n');
	} catch (e) {
		return 0;
	}
	var hash = crypto.createHash('md5');
	for (var i = 0; i < filenames.length; ++i) {
		try {
			hash.update(fs.readFileSync(filenames[i]));
		} catch (e) {}
	}
	return hash.digest('hex');
};

exports.serverVersion = exports.computeServerVersion();

/*********************************************************
 * Commands
 *********************************************************/

var commands = exports.commands = require('./commands.js').commands;

var customCommands = require('./config/commands.js');
if (customCommands && customCommands.commands) {
	Object.merge(commands, customCommands.commands);
}
<|endoftext|>


<commit_before>/*
 * typedefs.js
 * Normalizes browser-specific prefixes
 */

if (typeof window !== 'undefined') {
    if (!window.requestAnimationFrame) {
        window.requestAnimationFrame = (function () {
            return window.webkitRequestAnimationFrame ||
                window.mozRequestAnimationFrame ||
                window.oRequestAnimationFrame ||
                window.msRequestAnimationFrame ||
                function (/* function FrameRequestCallback */ callback) {
                    window.setTimeout(callback, 1000 / 60);
                };
        }());
    }
}
Math.imul = Math.imul || function(a, b) {
    var ah = (a >>> 16) & 0xffff,
        al = a & 0xffff,
        bh = (b >>> 16) & 0xffff,
        bl = b & 0xffff;
    // the shift by 0 fixes the sign on the high part
    // the final |0 converts the unsigned value into a signed value
    return ((al * bl) + (((ah * bl + al * bh) << 16) >>> 0) | 0);
};

if (typeof Object.assign !== 'function') {
    Object.assign = function(target) { // .length of function is 2
        'use strict';
        if (target === null) { // TypeError if undefined or null
            throw new TypeError('Cannot convert undefined or null to object');
        }

        var to = Object(target);

        for (var index = 1; index < arguments.length; index++) {
            var nextSource = arguments[index];

            if (nextSource !== null) { // Skip over if undefined or null
                for (var nextKey in nextSource) {
                    // Avoid bugs when hasOwnProperty is shadowed
                    if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
                        to[nextKey] = nextSource[nextKey];
                    }
                }
            }
        }
        return to;
    };
}
<commit_msg>minor cleanup to src/common/typedefs<commit_after>/*
 * typedefs.js
 * Normalizes browser-specific prefixes and provide some basic polyfills
 */

if (typeof window !== 'undefined') {
    if (!window.requestAnimationFrame) {
        window.requestAnimationFrame = (function () {
            return window.webkitRequestAnimationFrame ||
                window.mozRequestAnimationFrame ||
                window.oRequestAnimationFrame ||
                window.msRequestAnimationFrame ||
                function (/* function FrameRequestCallback */ callback) {
                    window.setTimeout(callback, 1000 / 60);
                };
        }());
    }
}

if (typeof Math.imul !== 'function') {
    Math.imul = function(a, b) {
        const ah = (a >>> 16) & 0xffff;
        const al = a & 0xffff;
        const bh = (b >>> 16) & 0xffff;
        const bl = b & 0xffff;
        // the shift by 0 fixes the sign on the high part
        // the final |0 converts the unsigned value into a signed value
        return ((al * bl) + (((ah * bl + al * bh) << 16) >>> 0) | 0);
    };
}

if (typeof Object.assign !== 'function') {
    Object.assign = function(target) { // .length of function is 2
        'use strict';
        if (target === null) { // TypeError if undefined or null
            throw new TypeError('Cannot convert undefined or null to object');
        }

        const to = Object(target);

        for (let index = 1; index < arguments.length; index++) {
            const nextSource = arguments[index];

            if (nextSource !== null) { // Skip over if undefined or null
                for (let nextKey in nextSource) {
                    // Avoid bugs when hasOwnProperty is shadowed
                    if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
                        to[nextKey] = nextSource[nextKey];
                    }
                }
            }
        }
        return to;
    };
}
<|endoftext|>


<commit_before>
'use strict';

const koa = require('koa');
const bodyParser = require('koa-bodyparser');
const router = require('koa-router')();
const mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/articles');
const app = koa();

import { Thread, User } from './models';
import { nonEmptyString } from './utils';

app.use(bodyParser());

router.use(function *(next) {
  if (!this.request.headers.alias) {
    yield next;
    return;
  }
  const me = yield User.findOne({ 'alias': this.request.headers.alias }).exec();
  if (me) {
    this.user = me;
  }
  yield next;
});

router.get('/', function *(next) {
  this.body = 'ohcE';
});

router.get('/me', function *(next) {
  this.body = this.user;
});

router.post('/me', function *(next) {
  this.assert(nonEmptyString(this.request.headers.alias), 400, 'need an alias');
  if (!this.user) {
    this.user = new User({
      alias: this.request.headers.alias,
    });
    yield this.user.save();
    this.status = 201;
  }
  this.body = this.user;
});

router.get('/threads', function *(next) {
  this.assert(this.user, 401, 'need to be authenticated');
  const threads = yield Thread.find({ participants: this.user }).exec();
  this.body = threads;
});

router.get('/thread', function *(next) {
  this.assert(this.user, 401, 'need to be authenticated');
  this.assert(nonEmptyString(this.request.query.id), 400, 'need an ID');
  const t = yield Thread.findById(this.request.query.id).exec();
  if (!t) {
    this.status = 404;
    return;
  }
  this.body = t;
});

router.post('/thread', function *(next) {
  this.assert(this.user, 401, 'need to be authenticated');
  this.assert(nonEmptyString(this.request.body.name), 400, 'need a name');
  const t = new Thread({
    participants: [ this.user ].concat(this.request.body.others || []),
    name: this.request.body.name,
  });
  yield t.save();
  this.status = 201;
  this.body = t;
});

router.get('/links', function *(next) {
  this.assert(this.user, 401, 'need to be authenticated');
  this.assert(nonEmptyString(this.request.query.id), 400, 'need a thread ID');
  const t =
    yield Thread.findById(this.request.query.id, { contents: true }).exec();
  if (!t) {
    this.status = 404;
    return;
  }
  this.body = t.contents;
});

app.use(router.routes());

const server = app.listen(8000, () => {
  const host = server.address().address;
  const port = server.address().port;

  console.log(`"ArticlesAPI" listening at http://${host}:${port}`);
});
<commit_msg>[server] creating and getting info on links<commit_after>
'use strict';

const koa = require('koa');
const bodyParser = require('koa-bodyparser');
const router = require('koa-router')();
const mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/articles');
const app = koa();

import { Thread, Link, User } from './models';
import { nonEmptyString } from './utils';

app.use(bodyParser());

router.use(function *(next) {
  if (!this.request.headers.alias) {
    yield next;
    return;
  }
  const me = yield User.findOne({ 'alias': this.request.headers.alias }).exec();
  if (me) {
    this.user = me;
  }
  yield next;
});

router.get('/', function *(next) {
  this.body = 'ohcE';
});

router.get('/me', function *(next) {
  this.body = this.user;
});

router.post('/me', function *(next) {
  this.assert(nonEmptyString(this.request.headers.alias), 400, 'need an alias');
  if (!this.user) {
    this.user = new User({
      alias: this.request.headers.alias,
    });
    yield this.user.save();
    this.status = 201;
  }
  this.body = this.user;
});

router.get('/threads', function *(next) {
  this.assert(this.user, 401, 'need to be authenticated');
  const threads = yield Thread.find({ participants: this.user }).exec();
  this.body = threads;
});

router.get('/thread', function *(next) {
  this.assert(this.user, 401, 'need to be authenticated');
  this.assert(nonEmptyString(this.request.query.id), 400, 'need an ID');
  const t = yield Thread.findById(this.request.query.id).exec();
  if (!t) {
    this.status = 404;
    return;
  }
  this.body = t;
});

router.post('/thread', function *(next) {
  this.assert(this.user, 401, 'need to be authenticated');
  this.assert(nonEmptyString(this.request.body.name), 400, 'need a name');
  const t = new Thread({
    participants: [ this.user ].concat(this.request.body.others || []),
    name: this.request.body.name,
  });
  yield t.save();
  this.status = 201;
  this.body = t;
});

router.get('/links', function *(next) {
  this.assert(this.user, 401, 'need to be authenticated');
  this.assert(nonEmptyString(this.request.query.id), 400, 'need a thread ID');
  const t =
    yield Thread.findById(this.request.query.id, { contents: true }).exec();
  if (!t) {
    this.status = 404;
    return;
  }
  this.body = t.contents;
});

router.get('/link', function *(next) {
  this.assert(this.user, 401, 'need to be authenticated');
  this.assert(nonEmptyString(this.request.query.id), 400, 'need a link ID');
  const l = yield Link.findById(this.request.query.id).exec();
  if (!l) {
    this.status = 404;
    return;
  }
  this.body = l;
});

router.post('/link', function *(next) {
  this.assert(this.user, 401, 'need to be authenticated');
  this.assert(nonEmptyString(this.request.body.id), 400, 'need a thread ID');
  this.assert(nonEmptyString(this.request.body.url), 400, 'need a URL');
  const t = yield Thread.findById(this.request.body.id).exec();
  if (!t) {
    this.throw(400, 'need a valid thread ID');
  }
  let link = yield Link.findOne({ url: this.request.body.url }).exec();
  if (!link) {
    link = new Link({
      url: this.request.body.url,
    });
    yield link.save();
  }
  t.contents.push(link._id);
  yield t.save();
  this.status = 201;
});

app.use(router.routes());

const server = app.listen(8000, () => {
  const host = server.address().address;
  const port = server.address().port;

  console.log(`"ArticlesAPI" listening at http://${host}:${port}`);
});
<|endoftext|>


<commit_before>(function() {
  'use strict';
  angular.module('civic.common')
    .directive('quickSearch', quickSearch)
    .controller('quickSearchCtrl', quickSearchCtrl);

  // @ngInject
  function quickSearch() {
    var directive = {
      templateUrl: 'components/directives/quickSearch.tpl.html',
      restrict: 'E',
      scope: true,
      controller: quickSearchCtrl
    };

    return directive;
  }

  // @ngInject
  function quickSearchCtrl($scope, $state, $log, TypeAheadResults, _) {
    var topResult = {};
    $scope.getVariants = function (val) {
      return TypeAheadResults.query({ query: val }).$promise
        .then(function (response) {
          var labelLimit = 75;
          return _.map(response.result, function (event, index) {
            var result;
            var label = event.entrez_gene + ' / ' + event.variant;

            if (_.includes(event.terms, 'gene_aliases')) {
              var aliasLabel = event.gene_aliases.length > 1 ? 'Aliases' : 'Alias';
              label = label + ' -- ' + aliasLabel + ': ' + event.gene_aliases.join(', ');
            }

            if (_.includes(event.terms, 'drug_names')) {
              var drugLabel = event.drug_names.length > 1 ? 'Drugs' : 'Drug';
              label = label + ' -- ' + drugLabel + ': ' + event.drug_names.join(', ');
            }

            if (_.includes(event.terms, 'disease_names')) {
              var diseaseLabel = event.disease_names.length > 1 ? 'Diseases' : 'Disease';
              label = label + ' -- ' + diseaseLabel + ': ' + event.disease_names.join(', ');
            }

            if (label.length > labelLimit) { label = _.trunc(label, labelLimit); }

            result = {
              /*jshint camelcase: false */
              gene: event.entrez_name,
              geneId: event.gene_id,
              label: label,
              variant: event.variant,
              variantId: event.variant_id
            };

            if(index === 0) { topResult = result; }

            return result;
          });
        });
    };

    $scope.onSelect = function($item) {
      $state.go('events.genes.summary.variants.summary', {geneId: $item.geneId, variantId: $item.variantId});
      $scope.asyncSelected.model = ''; // clear typeahead
    };

    $scope.onGo = function(scope) {
      // NOTE: typeahead control does not make the currently selected item available outside its
      // scope, so we have no way to know which item the user has highlighted. So the Go button
      // cheats and just sends them to the first item on the list.
      // TODO: figure out how to access typeahead dropdown items and current activeIndex
      $state.go('events.genes.summary.variants.summary', {geneId: topResult.geneId, variantId: topResult.variantId});
    }

  }

})();
<commit_msg>added some notes to quicksearch re: clearing typeahead after state trans<commit_after>(function() {
  'use strict';
  angular.module('civic.common')
    .directive('quickSearch', quickSearch)
    .controller('quickSearchCtrl', quickSearchCtrl);

  // @ngInject
  function quickSearch() {
    var directive = {
      templateUrl: 'components/directives/quickSearch.tpl.html',
      restrict: 'E',
      scope: true,
      controller: quickSearchCtrl
    };

    return directive;
  }

  // @ngInject
  function quickSearchCtrl($scope, $state, $log, TypeAheadResults, _) {
    var topResult = {};

    $scope.getVariants = function (val) {
      return TypeAheadResults.query({ query: val }).$promise
        .then(function (response) {
          var labelLimit = 75;
          return _.map(response.result, function (event, index) {
            var result;
            var label = event.entrez_gene + ' / ' + event.variant;

            if (_.includes(event.terms, 'gene_aliases')) {
              var aliasLabel = event.gene_aliases.length > 1 ? 'Aliases' : 'Alias';
              label = label + ' -- ' + aliasLabel + ': ' + event.gene_aliases.join(', ');
            }

            if (_.includes(event.terms, 'drug_names')) {
              var drugLabel = event.drug_names.length > 1 ? 'Drugs' : 'Drug';
              label = label + ' -- ' + drugLabel + ': ' + event.drug_names.join(', ');
            }

            if (_.includes(event.terms, 'disease_names')) {
              var diseaseLabel = event.disease_names.length > 1 ? 'Diseases' : 'Disease';
              label = label + ' -- ' + diseaseLabel + ': ' + event.disease_names.join(', ');
            }

            if (label.length > labelLimit) { label = _.trunc(label, labelLimit); }

            result = {
              /*jshint camelcase: false */
              gene: event.entrez_name,
              geneId: event.gene_id,
              label: label,
              variant: event.variant,
              variantId: event.variant_id
            };

            if(index === 0) { topResult = result; }

            return result;
          });
        });
    };

    $scope.onSelect = function($item) {
      $state.go('events.genes.summary.variants.summary', {geneId: $item.geneId, variantId: $item.variantId});
      $scope.asyncSelected.model = ''; // clear typeahead
    };

    $scope.onGo = function(scope) {
      // NOTE: typeahead control does not make the currently selected item available outside its
      // scope, so we have no way to know which item the user has highlighted. So the Go button
      // cheats and just sends them to the first item on the list.
      // TODO: figure out how to access typeahead dropdown items and current activeIndex
      // TODO: figure out how to clear typeahead after state transition (asyncSelected.model is unavaiable to this function when called). This doesn't work:
      // scope.$$childHead.query= ''; // clear typeahead
      $state.go('events.genes.summary.variants.summary', {geneId: topResult.geneId, variantId: topResult.variantId});

    }

  }

})();
<|endoftext|>


<commit_before><commit_msg>make sure all configs are valid in tests<commit_after><|endoftext|>


<commit_before>/**
 * Command parser
 * Pokemon Showdown - http://pokemonshowdown.com/
 *
 * This is the command parser. Call it with CommandParser.parse
 * (scroll down to its definition for details)
 *
 * Individual commands are put in:
 *   commands.js - "core" commands that shouldn't be modified
 *   config/commands.js - other commands that can be safely modified
 *
 * The command API is (mostly) documented in config/commands.js
 *
 * @license MIT license
 */

/*

To reload chat commands:

/hotpatch chat

*/

const MAX_MESSAGE_LENGTH = 300;

const BROADCAST_COOLDOWN = 20*1000;

const MESSAGE_COOLDOWN = 5*60*1000;

const MAX_PARSE_RECURSION = 10;

var crypto = require('crypto');

var modlog = exports.modlog = modlog || fs.createWriteStream('logs/modlog.txt', {flags:'a+'});

/**
 * Command parser
 *
 * Usage:
 *   CommandParser.parse(message, room, user, connection)
 *
 * message - the message the user is trying to say
 * room - the room the user is trying to say it in
 * user - the user that sent the message
 * connection - the connection the user sent the message from
 *
 * Returns the message the user should say, or a falsy value which
 * means "don't say anything"
 *
 * Examples:
 *   CommandParser.parse("/join lobby", room, user, connection)
 *     will make the user join the lobby, and return false.
 *
 *   CommandParser.parse("Hi, guys!", room, user, connection)
 *     will return "Hi, guys!" if the user isn't muted, or
 *     if he's muted, will warn him that he's muted, and
 *     return false.
 */
var parse = exports.parse = function(message, room, user, connection, levelsDeep) {
	var cmd = '', target = '';
	if (!message || !message.trim().length) return;
	if (!levelsDeep) levelsDeep = 0;

	if (message.substr(0,3) === '>> ') {
		// multiline eval
		message = '/eval '+message.substr(3);
	} else if (message.substr(0,4) === '>>> ') {
		// multiline eval
		message = '/evalbattle '+message.substr(4);
	}

	if (message.substr(0,2) !== '//' && message.substr(0,1) === '/') {
		var spaceIndex = message.indexOf(' ');
		if (spaceIndex > 0) {
			cmd = message.substr(1, spaceIndex-1);
			target = message.substr(spaceIndex+1);
		} else {
			cmd = message.substr(1);
			target = '';
		}
	} else if (message.substr(0,1) === '!') {
		var spaceIndex = message.indexOf(' ');
		if (spaceIndex > 0) {
			cmd = message.substr(0, spaceIndex);
			target = message.substr(spaceIndex+1);
		} else {
			cmd = message;
			target = '';
		}
	}
	cmd = cmd.toLowerCase();
	var broadcast = false;
	if (cmd.charAt(0) === '!') {
		broadcast = true;
		cmd = cmd.substr(1);
	}

	var commandHandler = commands[cmd];
	if (typeof commandHandler === 'string') {
		// in case someone messed up, don't loop
		commandHandler = commands[commandHandler];
	}
	if (commandHandler) {
		var context = {
			sendReply: function(data) {
				if (this.broadcasting) {
					room.add(data, true);
				} else {
					connection.sendTo(room, data);
				}
			},
			sendReplyBox: function(html) {
				this.sendReply('|raw|
'+html+'
');
			},
			popupReply: function(message) {
				connection.popup(message);
			},
			add: function(data) {
				room.add(data, true);
			},
			send: function(data) {
				room.send(data);
			},
			privateModCommand: function(data) {
				for (var i in room.users) {
					if (room.users[i].group in {'%':1, '@':1, '&':1, '~':1}) {
						room.users[i].sendTo(room, data);
					}
				}
				this.logEntry(data);
				this.logModCommand(data);
			},
			logEntry: function(data) {
				room.logEntry(data);
			},
			addModCommand: function(result) {
				this.add(result);
				this.logModCommand(result);
			},
			logModCommand: function(result) {
				modlog.write('['+(new Date().toJSON())+'] ('+room.id+') '+result+'\n');
			},
			can: function(permission, target) {
				if (!user.can(permission, target)) {
					this.sendReply('/'+cmd+' - Access denied.');
					return false;
				}
				return true;
			},
			canBroadcast: function() {
				if (broadcast) {
					if (!this.canTalk(message)) return false;
					if (!user.can('broadcast')) {
						connection.send("You need to be voiced to broadcast this command's information.");
						connection.send("To see it for yourself, use: /"+message.substr(1));
						return false;
					}

					this.add('|c|'+user.getIdentity(room.id)+'|'+message);

					// broadcast cooldown
					var normalized = toId(message);
					if (CommandParser.lastBroadcast === normalized &&
							CommandParser.lastBroadcastTime >= Date.now() - BROADCAST_COOLDOWN) {
						return false;
					}
					CommandParser.lastBroadcast = normalized;
					CommandParser.lastBroadcastTime = Date.now();

					this.broadcasting = true;
				}
				return true;
			},
			parse: function(message) {
				if (levelsDeep > MAX_PARSE_RECURSION) {
					return this.sendReply("Error: Too much recursion");
				}
				return parse(message, room, user, connection, levelsDeep+1);
			},
			canTalk: function(message) {
				return canTalk(user, room, connection, message);
			},
			targetUserOrSelf: function(target) {
				if (!target) return user;
				this.splitTarget(target);
				return this.targetUser;
			},
			splitTarget: splitTarget
		};

		var result = commandHandler.call(context, target, room, user, connection, cmd, message);
		if (result === undefined) result = false;

		return result;
	} else {
		// Check for mod/demod/admin/deadmin/etc depending on the group ids
		for (var g in config.groups) {
			if (cmd === config.groups[g].id) {
				return parse('/promote ' + toUserid(target) + ',' + g, room, user, connection);
			} else if (cmd === 'de' + config.groups[g].id || cmd === 'un' + config.groups[g].id) {
				var nextGroup = config.groupsranking[config.groupsranking.indexOf(g) - 1];
				if (!nextGroup) nextGroup = config.groupsranking[0];
				return parse('/demote' + toUserid(target) + ',' + nextGroup, room, user, connection);
			}
		}

		if (message.substr(0,1) === '/' && cmd) {
			// To guard against command typos, we now emit an error message
			return connection.send('The command "/'+cmd+'" was unrecognized. To send a message starting with "/'+cmd+'", type "//'+cmd+'".');
		}
	}

	message = canTalk(user, room, connection, message);
	if (!message) return false;

	return message;
};

function splitTarget(target, exactName) {
	var commaIndex = target.indexOf(',');
	if (commaIndex < 0) {
		targetUser = Users.get(target, exactName)
		this.targetUser = targetUser;
		this.targetUsername = (targetUser?targetUser.name:target);
		return '';
	}
	var targetUser = Users.get(target.substr(0, commaIndex), exactName);
	if (!targetUser) {
		targetUser = null;
	}
	this.targetUser = targetUser;
	this.targetUsername = (targetUser?targetUser.name:target.substr(0, commaIndex));
	return target.substr(commaIndex+1).trim();
}

/**
 * Can this user talk?
 * Pass the corresponding connection to give the user an error, if not
 */
function canTalk(user, room, connection, message) {
	if (!user.named) return false;
	if (user.locked) {
		if (connection) connection.sendTo(room, 'You are locked from talking in chat.');
		return false;
	}
	if (user.mutedRooms[room.id]) {
		if (connection) connection.sendTo(room, 'You are muted and cannot talk in this room.');
		return false;
	}
	if (config.modchat && room.id === 'lobby') {
		if (config.modchat === 'crash') {
			if (!user.can('ignorelimits')) {
				if (connection) connection.sendTo(room, 'Because the server has crashed, you cannot speak in lobby chat.');
				return false;
			}
		} else {
			if (!user.authenticated && config.modchat === true) {
				if (connection) connection.sendTo(room, 'Because moderated chat is set, you must be registered to speak in lobby chat. To register, simply win a rated battle by clicking the look for battle button');
				return false;
			} else if (config.groupsranking.indexOf(user.group) < config.groupsranking.indexOf(config.modchat)) {
				var groupName = config.groups[config.modchat].name;
				if (!groupName) groupName = config.modchat;
				if (connection) connection.sendTo(room, 'Because moderated chat is set, you must be of rank ' + groupName +' or higher to speak in lobby chat.');
				return false;
			}
		}
	}
	if (!(user.userid in room.users)) {
		connection.popup("You can't send a message to this room without being in it.");
		return false;
	}

	if (message) {
		if (message.length > MAX_MESSAGE_LENGTH && !user.can('ignorelimits')) {
			connection.popup("Your message is too long:\n\n"+message);
			return false;
		}

		// hardcoded low quality website
		if (/\bnimp\.org\b/i.test(message)) return false;

		// remove zalgo
		message = message.replace(/[\u0300-\u036f]{3,}/g,'');

		var normalized = toId(message);
		if ((normalized === user.lastMessage) &&
				((Date.now() - user.lastMessageTime) < MESSAGE_COOLDOWN)) {
			connection.popup("You can't send the same message again so soon.");
			return false;
		}
		user.lastMessage = normalized;
		user.lastMessageTime = Date.now();

		if (config.chatfilter) {
			return config.chatfilter(user, room, connection.socket, message);
		}
		return message;
	}

	return true;
}

exports.package = {};
fs.readFile('package.json', function(err, data) {
	if (err) return;
	exports.package = JSON.parse(data);
});

exports.uncacheTree = function(root) {
	var uncache = [require.resolve(root)];
	do {
		var newuncache = [];
		for (var i = 0; i < uncache.length; ++i) {
			if (require.cache[uncache[i]]) {
				newuncache.push.apply(newuncache,
					require.cache[uncache[i]].children.map(function(module) {
						return module.filename;
					})
				);
				delete require.cache[uncache[i]];
			}
		}
		uncache = newuncache;
	} while (uncache.length > 0);
};

// This function uses synchronous IO in order to keep it relatively simple.
// The function takes about 0.023 seconds to run on one tested computer,
// which is acceptable considering how long the server takes to start up
// anyway (several seconds).
exports.computeServerVersion = function() {
	/**
	 * `filelist.txt` is a list of all the files in this project. It is used
	 * for computing a checksum of the project for the /version command. This
	 * information cannot be determined at runtime because the user may not be
	 * using a git repository (for example, the user may have downloaded an
	 * archive of the files).
	 *
	 * `filelist.txt` is generated by running `git ls-files > filelist.txt`.
	 */
	var filenames;
	try {
		var data = fs.readFileSync('filelist.txt', {encoding: 'utf8'});
		filenames = data.split('\n');
	} catch (e) {
		return 0;
	}
	var hash = crypto.createHash('md5');
	for (var i = 0; i < filenames.length; ++i) {
		try {
			hash.update(fs.readFileSync(filenames[i]));
		} catch (e) {}
	}
	return hash.digest('hex');
};

exports.serverVersion = exports.computeServerVersion();

/*********************************************************
 * Commands
 *********************************************************/

var commands = exports.commands = require('./commands.js').commands;

var customCommands = require('./config/commands.js');
if (customCommands && customCommands.commands) {
	Object.merge(commands, customCommands.commands);
}
<commit_msg>Basic anti-spam function only applies to the lobby<commit_after>/**
 * Command parser
 * Pokemon Showdown - http://pokemonshowdown.com/
 *
 * This is the command parser. Call it with CommandParser.parse
 * (scroll down to its definition for details)
 *
 * Individual commands are put in:
 *   commands.js - "core" commands that shouldn't be modified
 *   config/commands.js - other commands that can be safely modified
 *
 * The command API is (mostly) documented in config/commands.js
 *
 * @license MIT license
 */

/*

To reload chat commands:

/hotpatch chat

*/

const MAX_MESSAGE_LENGTH = 300;

const BROADCAST_COOLDOWN = 20*1000;

const MESSAGE_COOLDOWN = 5*60*1000;

const MAX_PARSE_RECURSION = 10;

var crypto = require('crypto');

var modlog = exports.modlog = modlog || fs.createWriteStream('logs/modlog.txt', {flags:'a+'});

/**
 * Command parser
 *
 * Usage:
 *   CommandParser.parse(message, room, user, connection)
 *
 * message - the message the user is trying to say
 * room - the room the user is trying to say it in
 * user - the user that sent the message
 * connection - the connection the user sent the message from
 *
 * Returns the message the user should say, or a falsy value which
 * means "don't say anything"
 *
 * Examples:
 *   CommandParser.parse("/join lobby", room, user, connection)
 *     will make the user join the lobby, and return false.
 *
 *   CommandParser.parse("Hi, guys!", room, user, connection)
 *     will return "Hi, guys!" if the user isn't muted, or
 *     if he's muted, will warn him that he's muted, and
 *     return false.
 */
var parse = exports.parse = function(message, room, user, connection, levelsDeep) {
	var cmd = '', target = '';
	if (!message || !message.trim().length) return;
	if (!levelsDeep) levelsDeep = 0;

	if (message.substr(0,3) === '>> ') {
		// multiline eval
		message = '/eval '+message.substr(3);
	} else if (message.substr(0,4) === '>>> ') {
		// multiline eval
		message = '/evalbattle '+message.substr(4);
	}

	if (message.substr(0,2) !== '//' && message.substr(0,1) === '/') {
		var spaceIndex = message.indexOf(' ');
		if (spaceIndex > 0) {
			cmd = message.substr(1, spaceIndex-1);
			target = message.substr(spaceIndex+1);
		} else {
			cmd = message.substr(1);
			target = '';
		}
	} else if (message.substr(0,1) === '!') {
		var spaceIndex = message.indexOf(' ');
		if (spaceIndex > 0) {
			cmd = message.substr(0, spaceIndex);
			target = message.substr(spaceIndex+1);
		} else {
			cmd = message;
			target = '';
		}
	}
	cmd = cmd.toLowerCase();
	var broadcast = false;
	if (cmd.charAt(0) === '!') {
		broadcast = true;
		cmd = cmd.substr(1);
	}

	var commandHandler = commands[cmd];
	if (typeof commandHandler === 'string') {
		// in case someone messed up, don't loop
		commandHandler = commands[commandHandler];
	}
	if (commandHandler) {
		var context = {
			sendReply: function(data) {
				if (this.broadcasting) {
					room.add(data, true);
				} else {
					connection.sendTo(room, data);
				}
			},
			sendReplyBox: function(html) {
				this.sendReply('|raw|
'+html+'
');
			},
			popupReply: function(message) {
				connection.popup(message);
			},
			add: function(data) {
				room.add(data, true);
			},
			send: function(data) {
				room.send(data);
			},
			privateModCommand: function(data) {
				for (var i in room.users) {
					if (room.users[i].group in {'%':1, '@':1, '&':1, '~':1}) {
						room.users[i].sendTo(room, data);
					}
				}
				this.logEntry(data);
				this.logModCommand(data);
			},
			logEntry: function(data) {
				room.logEntry(data);
			},
			addModCommand: function(result) {
				this.add(result);
				this.logModCommand(result);
			},
			logModCommand: function(result) {
				modlog.write('['+(new Date().toJSON())+'] ('+room.id+') '+result+'\n');
			},
			can: function(permission, target) {
				if (!user.can(permission, target)) {
					this.sendReply('/'+cmd+' - Access denied.');
					return false;
				}
				return true;
			},
			canBroadcast: function() {
				if (broadcast) {
					if (!this.canTalk(message)) return false;
					if (!user.can('broadcast')) {
						connection.send("You need to be voiced to broadcast this command's information.");
						connection.send("To see it for yourself, use: /"+message.substr(1));
						return false;
					}

					this.add('|c|'+user.getIdentity(room.id)+'|'+message);

					// broadcast cooldown
					var normalized = toId(message);
					if (CommandParser.lastBroadcast === normalized &&
							CommandParser.lastBroadcastTime >= Date.now() - BROADCAST_COOLDOWN) {
						return false;
					}
					CommandParser.lastBroadcast = normalized;
					CommandParser.lastBroadcastTime = Date.now();

					this.broadcasting = true;
				}
				return true;
			},
			parse: function(message) {
				if (levelsDeep > MAX_PARSE_RECURSION) {
					return this.sendReply("Error: Too much recursion");
				}
				return parse(message, room, user, connection, levelsDeep+1);
			},
			canTalk: function(message) {
				return canTalk(user, room, connection, message);
			},
			targetUserOrSelf: function(target) {
				if (!target) return user;
				this.splitTarget(target);
				return this.targetUser;
			},
			splitTarget: splitTarget
		};

		var result = commandHandler.call(context, target, room, user, connection, cmd, message);
		if (result === undefined) result = false;

		return result;
	} else {
		// Check for mod/demod/admin/deadmin/etc depending on the group ids
		for (var g in config.groups) {
			if (cmd === config.groups[g].id) {
				return parse('/promote ' + toUserid(target) + ',' + g, room, user, connection);
			} else if (cmd === 'de' + config.groups[g].id || cmd === 'un' + config.groups[g].id) {
				var nextGroup = config.groupsranking[config.groupsranking.indexOf(g) - 1];
				if (!nextGroup) nextGroup = config.groupsranking[0];
				return parse('/demote' + toUserid(target) + ',' + nextGroup, room, user, connection);
			}
		}

		if (message.substr(0,1) === '/' && cmd) {
			// To guard against command typos, we now emit an error message
			return connection.send('The command "/'+cmd+'" was unrecognized. To send a message starting with "/'+cmd+'", type "//'+cmd+'".');
		}
	}

	message = canTalk(user, room, connection, message);
	if (!message) return false;

	return message;
};

function splitTarget(target, exactName) {
	var commaIndex = target.indexOf(',');
	if (commaIndex < 0) {
		targetUser = Users.get(target, exactName)
		this.targetUser = targetUser;
		this.targetUsername = (targetUser?targetUser.name:target);
		return '';
	}
	var targetUser = Users.get(target.substr(0, commaIndex), exactName);
	if (!targetUser) {
		targetUser = null;
	}
	this.targetUser = targetUser;
	this.targetUsername = (targetUser?targetUser.name:target.substr(0, commaIndex));
	return target.substr(commaIndex+1).trim();
}

/**
 * Can this user talk?
 * Pass the corresponding connection to give the user an error, if not
 */
function canTalk(user, room, connection, message) {
	if (!user.named) return false;
	if (user.locked) {
		if (connection) connection.sendTo(room, 'You are locked from talking in chat.');
		return false;
	}
	if (user.mutedRooms[room.id]) {
		if (connection) connection.sendTo(room, 'You are muted and cannot talk in this room.');
		return false;
	}
	if (config.modchat && room.id === 'lobby') {
		if (config.modchat === 'crash') {
			if (!user.can('ignorelimits')) {
				if (connection) connection.sendTo(room, 'Because the server has crashed, you cannot speak in lobby chat.');
				return false;
			}
		} else {
			if (!user.authenticated && config.modchat === true) {
				if (connection) connection.sendTo(room, 'Because moderated chat is set, you must be registered to speak in lobby chat. To register, simply win a rated battle by clicking the look for battle button');
				return false;
			} else if (config.groupsranking.indexOf(user.group) < config.groupsranking.indexOf(config.modchat)) {
				var groupName = config.groups[config.modchat].name;
				if (!groupName) groupName = config.modchat;
				if (connection) connection.sendTo(room, 'Because moderated chat is set, you must be of rank ' + groupName +' or higher to speak in lobby chat.');
				return false;
			}
		}
	}
	if (!(user.userid in room.users)) {
		connection.popup("You can't send a message to this room without being in it.");
		return false;
	}

	if (message) {
		if (message.length > MAX_MESSAGE_LENGTH && !user.can('ignorelimits')) {
			connection.popup("Your message is too long:\n\n"+message);
			return false;
		}

		// hardcoded low quality website
		if (/\bnimp\.org\b/i.test(message)) return false;

		// remove zalgo
		message = message.replace(/[\u0300-\u036f]{3,}/g,'');

		if (room.id === 'lobby') {
			var normalized = toId(message);
			if ((normalized === user.lastMessage) &&
					((Date.now() - user.lastMessageTime) < MESSAGE_COOLDOWN)) {
				connection.popup("You can't send the same message again so soon.");
				return false;
			}
			user.lastMessage = normalized;
			user.lastMessageTime = Date.now();
		}

		if (config.chatfilter) {
			return config.chatfilter(user, room, connection.socket, message);
		}
		return message;
	}

	return true;
}

exports.package = {};
fs.readFile('package.json', function(err, data) {
	if (err) return;
	exports.package = JSON.parse(data);
});

exports.uncacheTree = function(root) {
	var uncache = [require.resolve(root)];
	do {
		var newuncache = [];
		for (var i = 0; i < uncache.length; ++i) {
			if (require.cache[uncache[i]]) {
				newuncache.push.apply(newuncache,
					require.cache[uncache[i]].children.map(function(module) {
						return module.filename;
					})
				);
				delete require.cache[uncache[i]];
			}
		}
		uncache = newuncache;
	} while (uncache.length > 0);
};

// This function uses synchronous IO in order to keep it relatively simple.
// The function takes about 0.023 seconds to run on one tested computer,
// which is acceptable considering how long the server takes to start up
// anyway (several seconds).
exports.computeServerVersion = function() {
	/**
	 * `filelist.txt` is a list of all the files in this project. It is used
	 * for computing a checksum of the project for the /version command. This
	 * information cannot be determined at runtime because the user may not be
	 * using a git repository (for example, the user may have downloaded an
	 * archive of the files).
	 *
	 * `filelist.txt` is generated by running `git ls-files > filelist.txt`.
	 */
	var filenames;
	try {
		var data = fs.readFileSync('filelist.txt', {encoding: 'utf8'});
		filenames = data.split('\n');
	} catch (e) {
		return 0;
	}
	var hash = crypto.createHash('md5');
	for (var i = 0; i < filenames.length; ++i) {
		try {
			hash.update(fs.readFileSync(filenames[i]));
		} catch (e) {}
	}
	return hash.digest('hex');
};

exports.serverVersion = exports.computeServerVersion();

/*********************************************************
 * Commands
 *********************************************************/

var commands = exports.commands = require('./commands.js').commands;

var customCommands = require('./config/commands.js');
if (customCommands && customCommands.commands) {
	Object.merge(commands, customCommands.commands);
}
<|endoftext|>


<commit_before>const WebSocket = require('ws');
var obj = this;
const Block = require('./xclass/Block');
const Subscriber = require('./objects/Subscriber');
const cowsay = require('cowsay');
const colors = require('colors');
global.Logger = require('./modules/Logger');
global.Commands = require('./modules/Commands');
global.readline = require('readline');
global.rl = readline.createInterface(process.stdin, process.stdout);

class xServer {

constructor() {
  this.id = 1;
  this.webSock = new WebSocket.Server({perMessageDeflate: false, port: 999}, this.onStart.bind(this));
  this.userList = [];
}

xQube() {
    this.commands = new Commands(this).start();
}

start() {

    this.webSock.on('connection', this.onConnection.bind(this));
    Logger.white(cowsay.say({
        text : "x³ ( xQube )",
        e : "oO",
        T : "U "
    }));

    Logger.prompt(this.handleCommand.bind(this));
    Logger.info("x³ authors: Sean Oberoi and Stas Darevskiy ".green);
    Logger.info("Copyright (c) 2016-2017 Mile High Interactive, LLC".green);
}

handleCommand(data) {
	this.commands.parse(data);
	Logger.prompt(this.handleCommand.bind(this));
}

onConnection(ws) {
  var client = new Block(this.getNextID(), ws, this.webSock, this.userList);
  client.ip = ws.upgradeReq.connection.remoteAddress;
  client.socket.on('message', client.onMessage.bind(client));
  client.socket.on('close', client.onCloseConn.bind(client));

  var id = client.id;
  this.userList.push({'id': client.uID.id, 'data': client});

  console.log("Built new Cube Object with ID: " + client.uID.id) + " from client ip: " + client.ip;

  var subObj = new Subscriber('create', client.camID, client.cubeID, client.uID);
  var user = client.uintIfy(subObj);
  client.socket.send(user);

  console.log("UserList: " + this.userList);
}

onStart() {
  Logger.info("WebSocket server successfully deployed!".green);
}

getNextID() {
  return this.id++;
}

}

module.exports = xServer;
<commit_msg>Fix console message<commit_after>const WebSocket = require('ws');
var obj = this;
const Block = require('./xclass/Block');
const Subscriber = require('./objects/Subscriber');
const cowsay = require('cowsay');
const colors = require('colors');
global.Logger = require('./modules/Logger');
global.Commands = require('./modules/Commands');
global.readline = require('readline');
global.rl = readline.createInterface(process.stdin, process.stdout);

class xServer {

constructor() {
  this.id = 1;
  this.webSock = new WebSocket.Server({perMessageDeflate: false, port: 999}, this.onStart.bind(this));
  this.userList = [];
}

xQube() {
    this.commands = new Commands(this).start();
}

start() {

    this.webSock.on('connection', this.onConnection.bind(this));
    Logger.white(cowsay.say({
        text : "x³ ( xQube )",
        e : "oO",
        T : "U "
    }));

    Logger.prompt(this.handleCommand.bind(this));
    Logger.info("x³ authors: Sean Oberoi and Stas Darevskiy ".green);
    Logger.info("Copyright (c) 2016-2017 Mile High Interactive, LLC".green);
}

handleCommand(data) {
	this.commands.parse(data);
	Logger.prompt(this.handleCommand.bind(this));
}

onConnection(ws) {
  var client = new Block(this.getNextID(), ws, this.webSock, this.userList);
  client.ip = ws.upgradeReq.connection.remoteAddress;
  client.socket.on('message', client.onMessage.bind(client));
  client.socket.on('close', client.onCloseConn.bind(client));

  var id = client.id;
  this.userList.push({'id': client.uID.id, 'data': client});

  console.log("Built new Cube Object with ID: " + client.uID.id + " from client ip: " + client.ip);

  var subObj = new Subscriber('create', client.camID, client.cubeID, client.uID);
  var user = client.uintIfy(subObj);
  client.socket.send(user);

  console.log("UserList: " + this.userList);
}

onStart() {
  Logger.info("WebSocket server successfully deployed!".green);
}

getNextID() {
  return this.id++;
}

}

module.exports = xServer;
<|endoftext|>


<commit_before>exports.run = async (client, message, [member]) => {
    const sql = require("sqlite");
    sql.open("./bwd/data/score.sqlite");

    var user = client.funcs.userSearch(client, message, member);

    if (user.username === null || user.username === undefined) { return; }
    if (user.bot === true) { return message.reply("You can't give your credits to a bot user!"); }

    sql.get(`SELECT * FROM scores WHERE userId = "${user.id}"`).then(row => {
        if (!row) {
            if (user.id == message.author.id) {
                sql.run("INSERT INTO scores (userId, credits, level, daily, rep, repDaily) VALUES (?, ?, ?, ?, ?, ?)", [user.id, 100, 0, Date.now(), 0, 0]);
                sql.run("INSERT INTO fish_inv (userId, common, uncommon, rare, epic, trash) VALUES (?, ?, ?, ?, ?, ?)", [user.id, 0, 0, 0, 0, 0]);
                sql.run("INSERT INTO fish_stats (userId, common, uncommon, rare, epic, trash) VALUES (?, ?, ?, ?, ?, ?)", [user.id, 0, 0, 0, 0, 0]);
                sql.run("INSERT INTO badges (userId, betaTester, bugSmasher) VALUES (?, ?, ?)", [user.id, "no", "no"]);
                return message.channel.send("You have recieved your daily amount of 100 credits.");
            } else {
                sql.get(`SELECT * FROM scores WHERE userId = "${message.author.id}"`).then(row => {
                    if (!row) { return message.reply("You have not gotten your first daily yet. Before giving credits to others, you must recieve the daily!"); }
                });
                return message.channel.send(`That user has not gotten their first daily to start off with so you can not give them any credits at the moment. ):`);
            }
        } if ((parseInt(row.daily) + 86400000) > Date.now()) {
            return message.reply("You have already redeemed your daily for today.");
        } else {
            if (user.id == message.author.id) {
                credit = row.credits + 100;
                sql.run(`UPDATE scores SET daily = ${Date.now()} WHERE userId = ${user.id}`);
            } else {
                credit = row.credits + (100 * (1 + Math.random()));
            }
            sql.run(`UPDATE scores SET credits = ${row.credits + 100} WHERE userId = ${user.id}`);
            return message.channel.send(`${user.username} has recieved ${credit - row.credits} credits.`);
        }
    }).catch(error => {
        console.log(error);
        var Report = client.funcs.sqlTables(client, message, user);
        return message.reply(Report);
    });
};

exports.conf = {
    enabled: true,
    runIn: ["text"],
    aliases: [],
    permLevel: 0,
    botPerms: [],
    requiredFuncs: [],
};

exports.help = {
    name: "daily",
    description: "Get a daily amount of credits or give them to someone else.",
    usage: "[member:str]",
    usageDelim: "",
};
<commit_msg>Update daily.js<commit_after>exports.run = async (client, message, [member]) => {
    const sql = require("sqlite");
    sql.open("./bwd/data/score.sqlite");

    var user = client.funcs.userSearch(client, message, member);

    if (user.username === null || user.username === undefined) { return; }
    if (user.bot === true) { return message.reply("You can't give your credits to a bot user!"); }

    sql.get(`SELECT * FROM scores WHERE userId = "${user.id}"`).then(row => {
        if (!row) {
            if (user.id == message.author.id) {
                sql.run("INSERT INTO scores (userId, credits, level, daily, rep, repDaily) VALUES (?, ?, ?, ?, ?, ?)", [user.id, 100, 0, Date.now(), 0, 0]);
                sql.run("INSERT INTO fish_inv (userId, common, uncommon, rare, epic, trash) VALUES (?, ?, ?, ?, ?, ?)", [user.id, 0, 0, 0, 0, 0]);
                sql.run("INSERT INTO fish_stats (userId, common, uncommon, rare, epic, trash) VALUES (?, ?, ?, ?, ?, ?)", [user.id, 0, 0, 0, 0, 0]);
                sql.run("INSERT INTO badges (userId, betaTester, bugSmasher) VALUES (?, ?, ?)", [user.id, "no", "no"]);
                sql.run("INSERT INTO awards (userId, suggest, bugs, minor, major) VALUES (?, ?, ?, ?, ?)", [user.id, 0, 0, 0, 0]);
                return message.channel.send("You have recieved your daily amount of 100 credits.");
            } else {
                sql.get(`SELECT * FROM scores WHERE userId = "${message.author.id}"`).then(row => {
                    if (!row) { return message.reply("You have not gotten your first daily yet. Before giving credits to others, you must recieve the daily!"); }
                });
                return message.channel.send(`That user has not gotten their first daily to start off with so you can not give them any credits at the moment. ):`);
            }
        } if (user.id != message.author.id) {
            credit = Number((100 * (1 + Math.random())).toFixed(0));
            sql.get(`SELECT * FROM scores WHERE userId = "${message.author.id}"`).then(row => {
                if ((parseInt(row.daily) + 86400000) > Date.now()) {
                    return message.reply("You have already redeemed your daily for today.");
                } else {
                    sql.run(`UPDATE scores SET daily = ${Date.now()} WHERE userId = ${message.author.id}`);
                    sql.get(`SELECT * FROM scores WHERE userId = "${user.id}"`).then(row => {
                        sql.run(`UPDATE scores SET credits = ${parseInt(row.credits) + credit} WHERE userId = ${user.id}`);
                    });
                    return message.channel.send(`${user.username} has recieved ${credit} credits.`);
                }
            });
        } else {
            credit = row.credits + 100;
            sql.run(`UPDATE scores SET daily = ${Date.now()} WHERE userId = ${user.id}`);
            sql.run(`UPDATE scores SET credits = ${row.credits + 100} WHERE userId = ${user.id}`);
            return message.channel.send(`${user.username} has recieved ${credit - row.credits} credits.`);
        }
    }).catch(error => {
        console.log(error);
        var Report = client.funcs.sqlTables(client, message, user);
        return message.reply(Report);
    });
};

exports.conf = {
    enabled: true,
    runIn: ["text"],
    aliases: [],
    permLevel: 0,
    botPerms: [],
    requiredFuncs: [],
};

exports.help = {
    name: "daily",
    description: "Get a daily amount of credits or give them to someone else.",
    usage: "[member:str]",
    usageDelim: "",
};
<|endoftext|>


<commit_before>(function () {
  'use strict';
  angular.module('bingo', [])
  .factory('BingoCardService', [function () {
    var ITEMS = [
      'chart showing mobile use exploding',
      'Gartner Hype Cycle',
      'word/tag cloud',
      'meme',
      'presenter makes joke about his/her baldness',
      'demo fails due to poor wi-fi',
      'speaker asks everyone to get off wi-fi',
      'talk too crowded, coding in lobby',
      'slide deck crashes, speaker has to improvise',
      'presentation about power and versatility of HTML5 using PowerPoint or Keynote deck',
      'Prezi',
      'Steve Souders is name checked',
      'Paul Irish is name checked',
      'more than three presenters on stage, all white dudes',
      '"awesome" used twice in less than 60 seconds',
      '"hot" or "hottest" used without apparent irony',
      'presenter makes joke about his/her age',
      'presenter jokes about audience sleeping',
      'presenter mentions yet another JS MV* framework you never heard of before',
      'presenter cites actual text from a W3C standard',
      '#bada55',
      'attendee wearing suspenders',
      'presenter does not show up',
      'presenter drops f-bomb',
      '"dirty checking" pun',
      'mind blown by slide deck animations',
      'feeling like the dumbest person in the room',
      'feeling like the smartest person in the room',
      'thinking "Best. Something. Ever." and actually meaning it',
      'at a CSS talk when you thought it would be a JS talk',
      'at a JS talk when you thought it would be a CSS talk',
      'high fiving another attendee',
      'some annoyance defused by recalling low ticket price',
      't-shirt schwag',
      'sticker schwag',
      'WAT?!',
      'speaker calls out primary sponsor for doing something wrong',
      'watch amazing session only to be told at the end that your target browsers don\'t support it',
      '"phablet" used without hint of irony',
      'lolcat in slide deck',
      'session.title != session.topic',
      'Ilya Grigorik\'s High Performance Network Browsing book is mentioned',
      'Someone tweets asking for the wifi password',
      '"isomorphic" used with explicit scare quotes',
    ];

    return {
      newCard: function () {
        var rv = [];
        var items = ITEMS.slice(0);
        var index;

        for(var i=0; i<5 ; i++){
          rv[i]=[];
          for(var j=0; j<5; j++) {
            if (i==2 && j==2) {
              rv[i][j] = "Free";
            } else {
              index = Math.floor(Math.random()*items.length);
              rv[i][j] = items.splice(index,1)[0];
            }
          }
        }

        return rv;
      }
    };
  }])
  .controller(
    'bingoController',
    ['$scope', 'BingoCardService', function ($scope, BingoCardService) {

      $scope.newCard = function () {
        $scope.card = {};
        $scope.card.rows = BingoCardService.newCard();
        $scope.card.header = ['B', 'I', 'N', 'G', 'O'];
      };

      $scope.newCard();
    }]
  );
}());
<commit_msg>killer app, in our dna<commit_after>(function () {
  'use strict';
  angular.module('bingo', [])
  .factory('BingoCardService', [function () {
    var ITEMS = [
      'chart showing mobile use exploding',
      'Gartner Hype Cycle',
      'word/tag cloud',
      'meme',
      'presenter makes joke about his/her baldness',
      'demo fails due to poor wi-fi',
      'speaker asks everyone to get off wi-fi',
      'talk too crowded, coding in lobby',
      'slide deck crashes, speaker has to improvise',
      'presentation about power and versatility of HTML5 using PowerPoint or Keynote deck',
      'Prezi',
      'Steve Souders is name checked',
      'Paul Irish is name checked',
      'more than three presenters on stage, all white dudes',
      '"awesome" used twice in less than 60 seconds',
      '"hot" or "hottest" used without apparent irony',
      'presenter makes joke about his/her age',
      'presenter jokes about audience sleeping',
      'presenter mentions yet another JS MV* framework you never heard of before',
      'presenter cites actual text from a W3C standard',
      '#bada55',
      'attendee wearing suspenders',
      'presenter does not show up',
      'presenter drops f-bomb',
      '"dirty checking" pun',
      'mind blown by slide deck animations',
      'feeling like the dumbest person in the room',
      'feeling like the smartest person in the room',
      'thinking "Best. Something. Ever." and actually meaning it',
      'at a CSS talk when you thought it would be a JS talk',
      'at a JS talk when you thought it would be a CSS talk',
      'high fiving another attendee',
      'some annoyance defused by recalling low ticket price',
      't-shirt schwag',
      'sticker schwag',
      'WAT?!',
      'speaker calls out primary sponsor for doing something wrong',
      'watch amazing session only to be told at the end that your target browsers don\'t support it',
      '"phablet" used without hint of irony',
      'lolcat in slide deck',
      'session.title != session.topic',
      'Ilya Grigorik\'s High Performance Network Browsing book is mentioned',
      'Someone tweets asking for the wifi password',
      '"isomorphic" used with explicit scare quotes',
      '"the next killer app"',
      '"it\'s in our DNA"',
    ];

    return {
      newCard: function () {
        var rv = [];
        var items = ITEMS.slice(0);
        var index;

        for(var i=0; i<5 ; i++){
          rv[i]=[];
          for(var j=0; j<5; j++) {
            if (i==2 && j==2) {
              rv[i][j] = "Free";
            } else {
              index = Math.floor(Math.random()*items.length);
              rv[i][j] = items.splice(index,1)[0];
            }
          }
        }

        return rv;
      }
    };
  }])
  .controller(
    'bingoController',
    ['$scope', 'BingoCardService', function ($scope, BingoCardService) {

      $scope.newCard = function () {
        $scope.card = {};
        $scope.card.rows = BingoCardService.newCard();
        $scope.card.header = ['B', 'I', 'N', 'G', 'O'];
      };

      $scope.newCard();
    }]
  );
}());
<|endoftext|>


<commit_before>import React from 'react';
import { BaseObject } from './_baseObject';
import Rebase from 're-base';

const base = Rebase.createClass('https://blink-ct.firebaseio.com/classes/1');

class Bericht extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      display: {},
    }
  }

  componentDidMount() {
    this.postMessage();
  }

  componentDidUpdate() {
    this.postMessage();
  }

  postMessage() {
    const object = this.props.data.object;

    if(!object) {
      return;
    }

    this.ref = base.post('display/message', {
      data: object.state
    });
  }

  render() {
    let state;
    if(this.props.data.object)
      state = this.props.data.object.state;

    return

{state}

;
  }
}

export default BaseObject(Bericht, 'bericht');
<commit_msg>Don't update screen message on load.<commit_after>import React from 'react';
import { BaseObject } from './_baseObject';
import Rebase from 're-base';

const base = Rebase.createClass('https://blink-ct.firebaseio.com/classes/1');

class Bericht extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      display: {},
    }
  }

  componentDidUpdate() {
    this.postMessage();
  }

  postMessage() {
    const object = this.props.data.object;

    if(!object) {
      return;
    }

    this.ref = base.post('display/message', {
      data: object.state
    });
  }

  render() {
    let state;
    if(this.props.data.object)
      state = this.props.data.object.state;

    return

{state}

;
  }
}

export default BaseObject(Bericht, 'bericht');
<|endoftext|>


<commit_before>//specify production and development here
<commit_msg>add docu for production and releas<commit_after>//specify production and development here

//for production or release:
//clean, copy-imagemin, copy-fonts, html, styles, browserify, browserSync, watch

//for development or build:
//clean, copy-imagemin, copy-fonts, html, styles, watchify, browserSync, watch
<|endoftext|>


<commit_before><commit_msg>Removed single run to cancel test execution on travis<commit_after><|endoftext|>