<commit_before>var _ = require('underscore'),
	keystone = require('../'),
	fs = require('fs'),
	util = require('util'),
	path = require('path'),
	async = require('async'),
	moment = require('moment'),
	utils = require('keystone-utils'),
	mandrillapi = require('mandrill-api');

var templateCache = {};
var DEFAULT_CONFIGURATION = {
	templateExt: 'jade',
	templateEngine: require('jade'),
	templateBasePath: path.normalize(path.join(__dirname, '..', 'templates', 'helpers', 'emails')),
	mandrill: {
		track_opens: true,
		track_clicks: true,
		preserve_recipients: false,
		inline_css: true
	}
};

var ErrorNoEmailTemplateName = function(){
  Error.apply(this, arguments);
	Error.captureStackTrace(this, arguments.callee);
	this.message = 'No email templateName specified.';
	this.name = 'ErrorNoEmailTemplateName';
};
util.inherits(ErrorNoEmailTemplateName, Error);

var ErrorEmailsPathNotSet = function(){
  Error.apply(this, arguments);
	Error.captureStackTrace(this, arguments.callee);
	this.message = 'Keystone option emails not set, use keyst.setPath("emails") or set the emails option in your configuration.';
	this.name = 'ErrorEmailsPathNotSet';
};
util.inherits(ErrorEmailsPathNotSet, Error);

var getEmailsPath = function(){
	try{
		var path = keystone.getPath('emails');
		if(path){
			return path;
		}
		throw new ErrorEmailsPathNotSet();
	}catch(e){
		throw new ErrorEmailsPathNotSet();
	}
};

process.nextTick(getEmailsPath);

/**
 * Email Class
 * ===========
 *
 * Helper class for sending emails with Mandrill.
 *
 * New instances take a `templatePath` string which must be a folder in the
 * emails path, and must contain either `templateName/email.templateExt` or `templateName.templateExt`
 * which is used as the template for the HTML part of the email.
 *
 * Once created, emails can be rendered or sent.
 *
 * Requires the `emails` path option and the `mandrill api key` option to be
 * set on Keystone.
 *
 * @api public
 */

var Email = function(options) {
	var self = this;
	if(typeof(options)==='string'){ // Use Email.defaults for everything but template name
		options = {
			templateName: options,
		}
	}
	options = options || {};
	self.templateName = options.templateName;
	self.templateExt = options.templateExt || Email.defaults.templateExt;
	self.templateEngine = options.templateEngine || Email.defaults.templateEngine;
	self.templateBasePath = options.templateBasePath||Email.defaults.templateBasePath;
	if(!self.templateName){
		throw new ErrorNoEmailtemplateName();
	}
	return self;
};

/**
 * Renders the email and passes it to the callback. Used by `email.send()` but
 * can also be called directly to generate a preview.
 *
 * @param {Object} locals - object of local variables provided to the template
 * @param {Function} callback(err, email)
 *
 * @api public
 */

Email.prototype.render = function(locals, callback) {

	if ('function' == typeof locals && !callback) {
		callback = locals;
		locals = {};
	}

	locals = ('object' == typeof locals) ? locals : {};
	callback = ('function' == typeof callback) ? callback : function() {};

	var self = this;

	if (keystone.get('email locals')) {
		_.defaults(locals, keystone.get('email locals'));
	}

	_.defaults(locals, {
		pretty: true,
		brand: keystone.get('brand'),
		moment: moment,
		utils: utils,
		subject: '(no subject)',
		theme: {},
		css: templateCSSMethods
	});

	this.compileTemplate(function(err) {

		if (err) {
			return callback(err);
		}

		var html = templateCache[self.templateName](locals);

		// ensure extended characters are replaced
		html = html.replace(/[\u007f-\uffff]/g, function(c) {
			return '&#x'+('0000'+c.charCodeAt(0).toString(16)).slice(-4)+';';
		});

		// process email rules
		var rules = keystone.get('email rules');
		if (rules) {

			if (!Array.isArray(rules)) {
				rules = [rules];
			}

			_.each(rules, function(rule) {
				if (rule.find && rule.replace) {

					var find = rule.find,
						replace = rule.replace;

					if ('string' == typeof find) {
						find = new RegExp(find, 'gi');
					}

					html = html.replace(find, replace);
				}
			});

		}

		callback(null, {
			subject: locals.subject,
			html: html
		});

	});

};

/**
 * Loads the template. Looks for `templateName.templateExt`, followed by `templateName/email.templateExt`
 *
 * @param {Function} callback(err)
 *
 * @api private
 */

Email.prototype.loadTemplate = function(callback) {

	var self = this,
		fsTemplatePath = path.join(Email.getEmailsPath(), self.templateName + '.' + self.templateExt);

	fs.readFile(fsTemplatePath, function(err, contents) {

		if (err) {
			if (err.code == 'ENOENT') {

				fsTemplatePath = path.join(Email.getEmailsPath(), self.templateName, 'email.'+self.templateExt);

				fs.readFile(fsTemplatePath, function(err, contents) {
					callback(err, fsTemplatePath, contents);
				});

			} else {
				return callback(err);
			}
		} else {
			return callback(err, fsTemplatePath, contents);
		}

	});

};

/**
 * Ensures the template for the email has been compiled
 *
 * @param {Function} callback(err)
 *
 * @api private
 */

Email.prototype.compileTemplate = function(callback) {

	if (keystone.get('env') == 'production' && templateCache[this.templateName])
		return callback();

	var self = this;

	this.loadTemplate(function(err, filename, contents) {

		if (err) return callback(err);

		var template = self.templateEngine.compile(contents.toString(), Email.defaults.compilerOptions||{ filename: fs.realpathSync(filename), basedir: self.templateBasePath });

		templateCache[self.templateName] = template;

		callback();

	});

};

/**
 * Prepares the email and sends it
 *
 * Options:
 *
 * - mandrill
 *   Initialised Mandrill API instance
 *
 * - tags
 *   Array of tags to send to Mandrill
 *
 * - to
 *   Object / String or Array of Objects / Strings to send to, e.g.
 *   ['jed@team9.com.au', { email: 'jed.watson@gmail.com' }]
 *   { email: 'jed@team9.com.au' }
 *   'jed@team9.com.au'
 *
 * - fromName
 *   Name to send from
 *
 * - fromEmail
 *   Email address to send from
 *
 * @param {Object} locals (passed to `email.render()`)
 * @param {Object} options
 * @param {Function} callback(err, info)
 *
 * @api private
 */

Email.prototype.send = function(locals, options, callback) {
	var self = this;

	this.render(locals, function(err, email) {

		callback = ('function' == typeof callback) ? callback : function() {};

		if (err) {
			return callback(err);
		}

		if ('object' != typeof options) {
			return callback({
				from: 'Email.send',
				key: 'invalid options',
				message: 'options object is required'
			});
		}

		if ('string' == typeof options.from) {
			options.fromName = options.from;
			options.fromEmail = options.from;
		} else if ((options.from||{}).name) {
			options.fromName = ('object' == typeof options.from.name) ? options.from.name.full : options.from.name;
			options.fromEmail = options.from.email;
		}

		if (!(options.fromName && options.fromEmail)) {
			return callback({
				from: 'Email.send',
				key: 'invalid options',
				message: 'options.fromName and options.fromEmail are required'
			});
		}

		if (!options.mandrill) {
			if (!keystone.get('mandrill api key'))
				return callback({
					from: 'Email.send',
					key: 'missing api key',
					message: 'You must either provide a Mandrill API Instance or set the mandrill api key before sending email.'
				});
			options.mandrill = new mandrillapi.Mandrill(keystone.get('mandrill api key'));
		}

		options.tags = ('array' == typeof options.tags) ? options.tags : [];
		options.tags.push('sent:' + moment().format('YYYY-MM-DD'));
		options.tags.push(self.templateName);

		var recipients = [],
			mergeVars = [];

		options.to = Array.isArray(options.to) ? options.to : [options.to];

		for (var i = 0; i < options.to.length; i++) {

			if ('string' == typeof options.to[i]) {
				options.to[i] = { email: options.to[i] };
			} else if ('object' == typeof options.to[i]) {
				if (!options.to[i].email) {
					return callback({
						from: 'Email.send',
						key: 'invalid recipient',
						message: 'Recipient ' + (i+1) + ' does not have a valid email address.'
					});
				}
			} else {
				return callback({
					from: 'Email.send',
					key: 'invalid recipient',
					message: 'Recipient ' + (i+1) + ' is not a string or an object.'
				});
			}

			var recipient = { email: options.to[i].email };

			if ('string' == typeof options.to[i].name) {
				recipient.name = options.to[i].name;
			} else if ('object' == typeof options.to[i].name) {
				recipient.name = options.to[i].name.full;
			}

			recipients.push(recipient);
			mergeVars.push({ rcpt: recipient.email, vars: [{ name: 'email', content: recipient.email }, { name: 'name', content: recipient.name }] });
		}

		var onSuccess = function(info) {
			callback(null, info);
		}

		var onFail = function(info) {
			callback({
				from: 'Email.send',
				key: 'send error',
				message: 'Mandrill encountered an error and did not send the emails.',
				info: info
			});
		}

		var message = {
			html: email.html,
			subject: email.subject,
			from_name: options.fromName,
			from_email: options.fromEmail,
			tags: options.tags,
			attachments: options.attachments,
			to: recipients,
			merge_vars: mergeVars,
			/*
			track_opens: true,
			track_clicks: true,
			preserve_recipients: false,
			inline_css: true,
			*/
			async: true
		};

		_.defaults(message, options.mandrillOptions);
		_.defaults(message, Email.defaults.mandrill);

		options.mandrill.messages.send({ message: message }, onSuccess, onFail);

	});

};

var templateCSSMethods = {
	shadeColor: function(color, percent) {
    	var num = parseInt(color.slice(1),16), amt = Math.round(2.55 * percent), R = (num >> 16) + amt, G = (num >> 8 & 0x00FF) + amt, B = (num & 0x0000FF) + amt;
    	return "#" + (0x1000000 + (R<255?R<1?0:R:255)*0x10000 + (G<255?G<1?0:G:255)*0x100 + (B<255?B<1?0:B:255)).toString(16).slice(1);
	}
};

Email.getEmailsPath = getEmailsPath;
Email.templateCache = templateCache;
Email.templateCSSMethods = templateCSSMethods;
Email.defaults = DEFAULT_CONFIGURATION;
Email.ErrorNoEmailTemplateName = ErrorNoEmailTemplateName;
Email.ErrorEmailsPathNotSet = ErrorEmailsPathNotSet;

exports = module.exports = Email;
<commit_msg>Fixing immediate email error, needs to be reconsidered<commit_after>var _ = require('underscore'),
	keystone = require('../'),
	fs = require('fs'),
	util = require('util'),
	path = require('path'),
	async = require('async'),
	moment = require('moment'),
	utils = require('keystone-utils'),
	mandrillapi = require('mandrill-api');

var templateCache = {};
var DEFAULT_CONFIGURATION = {
	templateExt: 'jade',
	templateEngine: require('jade'),
	templateBasePath: path.normalize(path.join(__dirname, '..', 'templates', 'helpers', 'emails')),
	mandrill: {
		track_opens: true,
		track_clicks: true,
		preserve_recipients: false,
		inline_css: true
	}
};

var ErrorNoEmailTemplateName = function(){
  Error.apply(this, arguments);
	Error.captureStackTrace(this, arguments.callee);
	this.message = 'No email templateName specified.';
	this.name = 'ErrorNoEmailTemplateName';
};
util.inherits(ErrorNoEmailTemplateName, Error);

var ErrorEmailsPathNotSet = function(){
  Error.apply(this, arguments);
	Error.captureStackTrace(this, arguments.callee);
	this.message = 'Keystone option emails not set, use keyst.setPath("emails") or set the emails option in your configuration.';
	this.name = 'ErrorEmailsPathNotSet';
};
util.inherits(ErrorEmailsPathNotSet, Error);

var getEmailsPath = function(){
	try{
		var path = keystone.getPath('emails');
		if(path){
			return path;
		}
		throw new ErrorEmailsPathNotSet();
	}catch(e){
		throw new ErrorEmailsPathNotSet();
	}
};

// TODO: Calling this immediately vaildates email configuration even when emails aren't
// being used. It needs to happen when the Email class is used (and probably NOT throw a
// hard error).

// process.nextTick(getEmailsPath);

/**
 * Email Class
 * ===========
 *
 * Helper class for sending emails with Mandrill.
 *
 * New instances take a `templatePath` string which must be a folder in the
 * emails path, and must contain either `templateName/email.templateExt` or `templateName.templateExt`
 * which is used as the template for the HTML part of the email.
 *
 * Once created, emails can be rendered or sent.
 *
 * Requires the `emails` path option and the `mandrill api key` option to be
 * set on Keystone.
 *
 * @api public
 */

var Email = function(options) {
	var self = this;
	if(typeof(options)==='string'){ // Use Email.defaults for everything but template name
		options = {
			templateName: options,
		}
	}
	options = options || {};
	self.templateName = options.templateName;
	self.templateExt = options.templateExt || Email.defaults.templateExt;
	self.templateEngine = options.templateEngine || Email.defaults.templateEngine;
	self.templateBasePath = options.templateBasePath || Email.defaults.templateBasePath;
	if(!self.templateName){
		throw new ErrorNoEmailtemplateName();
	}
	return self;
};

/**
 * Renders the email and passes it to the callback. Used by `email.send()` but
 * can also be called directly to generate a preview.
 *
 * @param {Object} locals - object of local variables provided to the template
 * @param {Function} callback(err, email)
 *
 * @api public
 */

Email.prototype.render = function(locals, callback) {

	if ('function' == typeof locals && !callback) {
		callback = locals;
		locals = {};
	}

	locals = ('object' == typeof locals) ? locals : {};
	callback = ('function' == typeof callback) ? callback : function() {};

	var self = this;

	if (keystone.get('email locals')) {
		_.defaults(locals, keystone.get('email locals'));
	}

	_.defaults(locals, {
		pretty: true,
		brand: keystone.get('brand'),
		moment: moment,
		utils: utils,
		subject: '(no subject)',
		theme: {},
		css: templateCSSMethods
	});

	this.compileTemplate(function(err) {

		if (err) {
			return callback(err);
		}

		var html = templateCache[self.templateName](locals);

		// ensure extended characters are replaced
		html = html.replace(/[\u007f-\uffff]/g, function(c) {
			return '&#x'+('0000'+c.charCodeAt(0).toString(16)).slice(-4)+';';
		});

		// process email rules
		var rules = keystone.get('email rules');
		if (rules) {

			if (!Array.isArray(rules)) {
				rules = [rules];
			}

			_.each(rules, function(rule) {
				if (rule.find && rule.replace) {

					var find = rule.find,
						replace = rule.replace;

					if ('string' == typeof find) {
						find = new RegExp(find, 'gi');
					}

					html = html.replace(find, replace);
				}
			});

		}

		callback(null, {
			subject: locals.subject,
			html: html
		});

	});

};

/**
 * Loads the template. Looks for `templateName.templateExt`, followed by `templateName/email.templateExt`
 *
 * @param {Function} callback(err)
 *
 * @api private
 */

Email.prototype.loadTemplate = function(callback) {

	var self = this,
		fsTemplatePath = path.join(Email.getEmailsPath(), self.templateName + '.' + self.templateExt);

	fs.readFile(fsTemplatePath, function(err, contents) {

		if (err) {
			if (err.code == 'ENOENT') {

				fsTemplatePath = path.join(Email.getEmailsPath(), self.templateName, 'email.'+self.templateExt);

				fs.readFile(fsTemplatePath, function(err, contents) {
					callback(err, fsTemplatePath, contents);
				});

			} else {
				return callback(err);
			}
		} else {
			return callback(err, fsTemplatePath, contents);
		}

	});

};

/**
 * Ensures the template for the email has been compiled
 *
 * @param {Function} callback(err)
 *
 * @api private
 */

Email.prototype.compileTemplate = function(callback) {

	if (keystone.get('env') == 'production' && templateCache[this.templateName])
		return callback();

	var self = this;

	this.loadTemplate(function(err, filename, contents) {

		if (err) return callback(err);

		var template = self.templateEngine.compile(contents.toString(), Email.defaults.compilerOptions||{ filename: fs.realpathSync(filename), basedir: self.templateBasePath });

		templateCache[self.templateName] = template;

		callback();

	});

};

/**
 * Prepares the email and sends it
 *
 * Options:
 *
 * - mandrill
 *   Initialised Mandrill API instance
 *
 * - tags
 *   Array of tags to send to Mandrill
 *
 * - to
 *   Object / String or Array of Objects / Strings to send to, e.g.
 *   ['jed@team9.com.au', { email: 'jed.watson@gmail.com' }]
 *   { email: 'jed@team9.com.au' }
 *   'jed@team9.com.au'
 *
 * - fromName
 *   Name to send from
 *
 * - fromEmail
 *   Email address to send from
 *
 * @param {Object} locals (passed to `email.render()`)
 * @param {Object} options
 * @param {Function} callback(err, info)
 *
 * @api private
 */

Email.prototype.send = function(locals, options, callback) {
	var self = this;

	this.render(locals, function(err, email) {

		callback = ('function' == typeof callback) ? callback : function() {};

		if (err) {
			return callback(err);
		}

		if ('object' != typeof options) {
			return callback({
				from: 'Email.send',
				key: 'invalid options',
				message: 'options object is required'
			});
		}

		if ('string' == typeof options.from) {
			options.fromName = options.from;
			options.fromEmail = options.from;
		} else if ((options.from||{}).name) {
			options.fromName = ('object' == typeof options.from.name) ? options.from.name.full : options.from.name;
			options.fromEmail = options.from.email;
		}

		if (!(options.fromName && options.fromEmail)) {
			return callback({
				from: 'Email.send',
				key: 'invalid options',
				message: 'options.fromName and options.fromEmail are required'
			});
		}

		if (!options.mandrill) {
			if (!keystone.get('mandrill api key'))
				return callback({
					from: 'Email.send',
					key: 'missing api key',
					message: 'You must either provide a Mandrill API Instance or set the mandrill api key before sending email.'
				});
			options.mandrill = new mandrillapi.Mandrill(keystone.get('mandrill api key'));
		}

		options.tags = ('array' == typeof options.tags) ? options.tags : [];
		options.tags.push('sent:' + moment().format('YYYY-MM-DD'));
		options.tags.push(self.templateName);

		var recipients = [],
			mergeVars = [];

		options.to = Array.isArray(options.to) ? options.to : [options.to];

		for (var i = 0; i < options.to.length; i++) {

			if ('string' == typeof options.to[i]) {
				options.to[i] = { email: options.to[i] };
			} else if ('object' == typeof options.to[i]) {
				if (!options.to[i].email) {
					return callback({
						from: 'Email.send',
						key: 'invalid recipient',
						message: 'Recipient ' + (i+1) + ' does not have a valid email address.'
					});
				}
			} else {
				return callback({
					from: 'Email.send',
					key: 'invalid recipient',
					message: 'Recipient ' + (i+1) + ' is not a string or an object.'
				});
			}

			var recipient = { email: options.to[i].email };

			if ('string' == typeof options.to[i].name) {
				recipient.name = options.to[i].name;
			} else if ('object' == typeof options.to[i].name) {
				recipient.name = options.to[i].name.full;
			}

			recipients.push(recipient);
			mergeVars.push({ rcpt: recipient.email, vars: [{ name: 'email', content: recipient.email }, { name: 'name', content: recipient.name }] });
		}

		var onSuccess = function(info) {
			callback(null, info);
		}

		var onFail = function(info) {
			callback({
				from: 'Email.send',
				key: 'send error',
				message: 'Mandrill encountered an error and did not send the emails.',
				info: info
			});
		}

		var message = {
			html: email.html,
			subject: email.subject,
			from_name: options.fromName,
			from_email: options.fromEmail,
			tags: options.tags,
			attachments: options.attachments,
			to: recipients,
			merge_vars: mergeVars,
			/*
			track_opens: true,
			track_clicks: true,
			preserve_recipients: false,
			inline_css: true,
			*/
			async: true
		};

		_.defaults(message, options.mandrillOptions);
		_.defaults(message, Email.defaults.mandrill);

		options.mandrill.messages.send({ message: message }, onSuccess, onFail);

	});

};

var templateCSSMethods = {
	shadeColor: function(color, percent) {
    	var num = parseInt(color.slice(1),16), amt = Math.round(2.55 * percent), R = (num >> 16) + amt, G = (num >> 8 & 0x00FF) + amt, B = (num & 0x0000FF) + amt;
    	return "#" + (0x1000000 + (R<255?R<1?0:R:255)*0x10000 + (G<255?G<1?0:G:255)*0x100 + (B<255?B<1?0:B:255)).toString(16).slice(1);
	}
};

Email.getEmailsPath = getEmailsPath;
Email.templateCache = templateCache;
Email.templateCSSMethods = templateCSSMethods;
Email.defaults = DEFAULT_CONFIGURATION;
Email.ErrorNoEmailTemplateName = ErrorNoEmailTemplateName;
Email.ErrorEmailsPathNotSet = ErrorEmailsPathNotSet;

exports = module.exports = Email;
<|endoftext|>


<commit_before>import { toRes } from '../../lib/util';
import Room from '../../models/rooms';

/**
 * Creates the new room
 * @param  {Object} options.body
 * @param  {Object} options.user logged user
 * @param  {Object} res
 */
export const create = ({ body, user }, res) => {
  Room.findOne({ name: body.name })
    .then(room => {
      if (!room) {
        console.log(`Room "${body.name}" not found, creating room with admin "${user.name}(${user._id})`);

        const room = new Room({
          name: body.name,
          admin: user._id,
          users: [user._id]
        });

        return room.save((err, item) => {
          if (err) {
            return toRes(res, 201)(err, item);
          }

          Room.findOne(item).populate('admin users').exec(toRes(res, 201));
        });
      }

      console.log(`Room "${room.name} already exists.`);
      return res.status(200).json(room);
    })
    .catch(toRes(res, 400))
};

/**
 * Shows a given room
 * @param  {Object} options.user   logged user
 * @param  {Object} options.params
 * @param  {Object} res
 */
export const show = ({ user, params}, res) => {
  Room.findById(params.id).populate('admin users').exec(toRes(res, 200));
};

/**
 * Joins a room
 * @param  {Object} options.user
 * @param  {Object} options.params
 * @param  {Object} res
 */
export const join = ({ user, params }, res) => {
  Room.findById(params.id)
    .populate('admin users')
    .then(room => {
      if (!room) {
        return res.status(404).send({ error: 'This room does not exist.' });
      }

      console.log(`"${user.name}" is about to join the room "${room.name}"`);

      // Check if the user is already in the users list
      if (!room.users.find(u => u._id === user._id)) {
        console.log(`"Adding ${user.name}" to the room "${room.name}"`);

        room.users.push(user._id);
        console.log(`"${user.name}" added to the room "${room.name}"`);

        return room.save(toRes(res, 200));
      }

      res.status(200).json(room.toObject());
    })
    .catch(error => {
      console.error('Error when joining room:', error);
      toRes(res, 400)
    });
}

/**
 * List all the rooms the user is in
 * @param  {Object} options.user
 * @param  {Object} res
 */
export const list = ({ user, query }, res) => {
  const filter = {};

  if (query.name) {
    filter.name = query.name;
  }

  Room.find(filter)
    .populate('admin users')
    .where({ 'users._id': user._id }).exec(toRes(res, 200));
};
<commit_msg>Fixed multiple populate<commit_after>import { toRes } from '../../lib/util';
import Room from '../../models/rooms';

/**
 * Creates the new room
 * @param  {Object} options.body
 * @param  {Object} options.user logged user
 * @param  {Object} res
 */
export const create = ({ body, user }, res) => {
  Room.findOne({ name: body.name })
    .then(room => {
      if (!room) {
        console.log(`Room "${body.name}" not found, creating room with admin "${user.name}(${user._id})`);

        const room = new Room({
          name: body.name,
          admin: user._id,
          users: [user._id]
        });

        console.log("Room:", room);

        return room.save((err, item) => {
          if (err) {
            return toRes(res, 201)(err, item);
          }

          room.populate('admin users', toRes(res, 201));
        });
      }

      console.log(`Room "${room.name} already exists.`);
      return res.status(200).json(room);
    })
    .catch(toRes(res, 400))
};

/**
 * Shows a given room
 * @param  {Object} options.user   logged user
 * @param  {Object} options.params
 * @param  {Object} res
 */
export const show = ({ user, params}, res) => {
  Room.findById(params.id).populate('admin users').exec(toRes(res, 200));
};

/**
 * Joins a room
 * @param  {Object} options.user
 * @param  {Object} options.params
 * @param  {Object} res
 */
export const join = ({ user, params }, res) => {
  Room.findById(params.id)
    .then(room => {
      if (!room) {
        return res.status(404).send({ error: 'This room does not exist.' });
      }

      console.log(`"${user.name}" is about to join the room "${room.name}"`);

      // Check if the user is already in the users list
      if (room.users.findIndex(userId => userId.equals(user._id)) < 0) {
        console.log(`"Adding ${user.name}" to the room "${room.name}"`);

        room.users.push(user);
        console.log(`"${user.name}" added to the room "${room.name}"`);

        return room.save((err, item) => {
          if (err) {
            return toRes(res, 200)(err, item);
          }

          room.populate('admin users', toRes(res, 200));
        });
      }

      console.log(`"${user.name}" is already in the room "${room.name}"`);

      res.status(200).json(room.toObject());
    })
    .catch(error => {
      console.error('Error when joining room:', error);
      toRes(res, 400)
    });
}

/**
 * List all the rooms the user is in
 * @param  {Object} options.user
 * @param  {Object} res
 */
export const list = ({ user, query }, res) => {
  const filter = {};

  if (query.name) {
    filter.name = query.name;
  }

  Room.find(filter)
    .populate('admin users')
    .where({ 'users': user._id })
    .exec(toRes(res, 200));
};
<|endoftext|>


<commit_before>/* jslint node:true */

'use strict';

exports = module.exports = {
    init: init,
    getAll: getAll,
    getAllLean: getAllLean,
    get: get,
    add: add,
    put: put,
    del: del,
    exp: exp,
    imp: imp,
    publicLink: publicLink,
    getByShareId: getByShareId,
    extractURLs: extractURLs,
    extractTags: extractTags,

    TYPE_IMAGE: 'image',
    TYPE_UNKNOWN: 'unknown'
};

var MongoClient = require('mongodb').MongoClient,
    ObjectId = require('mongodb').ObjectID,
    async = require('async'),
    fs = require('fs'),
    os = require('os'),
    config = require('./config.js'),
    tags = require('./tags.js'),
    path = require('path'),
    superagent = require('superagent');

var g_db, g_things, g_publicLinks;
var GET_URL = new RegExp('(^|[ \t\r\n])((ftp|http|https|gopher|mailto|news|nntp|telnet|wais|file|prospero|aim|webcal):(([A-Za-z0-9$_.+!*(),;/?:@&~=-])|%[A-Fa-f0-9]{2}){2,}(#([a-zA-Z0-9$_.+!*(),;/?:@&~=%-]*))?([A-Za-z0-9$_+!*();/?:~-]))', 'g');

function init(callback) {
    MongoClient.connect(config.databaseUrl, function (error, db) {
        if (error) return callback(error);

        g_db = db;
        g_db.createCollection('things');
        g_db.createCollection('publicLinks');
        g_things = db.collection('things');
        g_publicLinks = db.collection('publicLinks');

        g_things.createIndex({ content: 'text' }, { default_language: 'none' });

        callback(null);
    });
}

function extractURLs(content) {
    var lines = content.split('\n');
    var urls = [];

    lines.forEach(function (line) {
        var tmp = line.match(GET_URL);
        if (tmp === null) return;

        urls = urls.concat(tmp.map(function (url) {
            return url.trim();
        }));
    });

    return urls.filter(function (item, pos, self) {
        return self.indexOf(item) === pos;
    });
}

function extractTags(content) {
    var tagObjects = [];

    // first replace all urls which might contain # with placeholders
    var urls = extractURLs(content);
    urls.forEach(function (u) {
        content = content.replace(new RegExp(u, 'gmi'), ' --URL_PLACEHOLDER-- ');
    });

    var lines = content.split('\n');
    lines.forEach(function (line) {
        var tmp = line.match(/#(\w+)/g);
        if (tmp === null) return;

        tagObjects = tagObjects.concat(tmp.map(function (tag) {
            return tag.slice(1).toLowerCase();
        }));
    });

    return tagObjects;
}

function extractExternalContent(content, callback) {
    var urls = extractURLs(content);
    var externalContent = [];

    async.each(urls, function (url, callback) {
        superagent.get(url).end(function (error, result) {
            var obj = { url: url, type: exports.TYPE_UNKNOWN };

            if (error) {
                console.log('[WARN] failed to fetch external content %s', url);
            } else {
                if (result.type.indexOf('image/') === 0) {
                    obj = { url: url, type: exports.TYPE_IMAGE };
                }

                console.log('[INFO] external content type %s - %s', obj.type, obj.url);
            }

            externalContent.push(obj);

            callback(null);
        });
    }, function () {
        callback(null, externalContent);
    });
}

function facelift(thing, callback) {
    var data = thing.content;
    var tagObjects = thing.tags;
    var externalContent = thing.externalContent;
    var attachments = thing.attachments || [];

    function wrapper() {

        // Enrich with tag links
        tagObjects.forEach(function (tag) {
            data = data.replace(new RegExp('#' + tag, 'gmi'), '[#' + tag + '](#search?#' + tag + ')');
        });

        // Enrich with image links
        externalContent.forEach(function (obj) {
            if (obj.type === exports.TYPE_IMAGE) {
                data = data.replace(new RegExp(obj.url, 'gmi'), '![' + obj.url + '](' + obj.url + ')');
            }
        });

        // Enrich with attachments
        attachments.forEach(function (a) {
            if (a.type === exports.TYPE_IMAGE) {
                data = data.replace(new RegExp(a.fileName, 'gmi'), '![/api/files/' + a.identifier + '](/api/files/' + a.identifier + ')');
            } else {
                data = data.replace(new RegExp(a.fileName, 'gmi'), '[/api/files/' + a.identifier + '](/api/files/' + a.identifier + ')');
            }
        });

        callback(null, data);
    }

    if (Array.isArray(externalContent)) return wrapper();

    // old entry extract external content first
    extractExternalContent(thing.content, function (error, result) {
        if (error) {
            console.error('Failed to extract external content:', error);

            externalContent = [];

            return wrapper();
        }

        // set for wrapper()
        externalContent = result;

        console.log('[INFO] update %s with new external content.', thing._id, result);

        g_things.update({_id: new ObjectId(thing._id) }, { $set: { externalContent: result } }, function (error) {
            if (error) console.error('Failed to update external content:', error);

            wrapper();
        });
    });
}

function getAll(query, skip, limit, callback) {
    g_things.find(query).skip(skip).limit(limit).sort({ modifiedAt: -1 }).toArray(function (error, result) {
        if (error) return callback(error);
        if (!result) return callback(null, []);

        async.each(result, function (thing, callback) {
            facelift(thing, function (error, data) {
                if (error) console.error('Failed to facelift:', error);

                thing.attachments = thing.attachments || [];
                thing.richContent = data || thing.content;

                callback(null);
            });
        }, function () {
            callback(null, result);
        });
    });
}

function getAllLean(callback) {
    g_things.find({}).toArray(function (error, result) {
        if (error) return callback(error);
        callback(null, result || []);
    });
}

function get(id, callback) {
    g_things.find({ _id: new ObjectId(id) }).toArray(function (error, result) {
        if (error) return callback(error);
        if (result.length === 0) return callback(new Error('not found'));

        var thing = result[0];
        facelift(thing, function (error, data) {
            if (error) console.error('Failed to facelift:', error);

            thing.attachments = thing.attachments || [];
            thing.richContent = data || thing.content;

            callback(null, thing);
        });
    });
}

function add(content, attachments, callback) {

    extractExternalContent(content, function (error, result) {
        if (error) return callback(error);

        var doc = {
            content: content,
            createdAt: new Date(),
            modifiedAt: new Date(),
            tags: extractTags(content),
            externalContent: result,
            attachments: attachments
        };

        async.eachSeries(doc.tags, tags.update, function (error) {
            if (error) return callback(error);

            g_things.insert(doc, function (error, result) {
                if (error) return callback(error);
                if (!result) return callback(new Error('no result returned'));

                // TODO replace with get()
                var thing = result.ops[0];

                facelift(thing, function (error, data) {
                    if (error) console.error('Failed to facelift:', error);

                    thing.attachments = thing.attachments || [];
                    thing.richContent = data || thing.content;

                    callback(null, thing);
                });
            });
        });
    });
}

function put(id, content, attachments, callback) {
    var tagObjects = extractTags(content);

    async.eachSeries(tagObjects, tags.update, function (error) {
        if (error) return callback(error);

        extractExternalContent(content, function (error, result) {
            if (error) console.error('Failed to extract external content:', error);

            var data = {
                content: content,
                tags: tagObjects,
                modifiedAt: new Date(),
                externalContent: result,
                attachments: attachments
            };

            g_things.update({_id: new ObjectId(id) }, { $set: data }, function (error) {
                if (error) return callback(error);

                get(id, callback);
            });
        });
    });
}

function del(id, callback) {
    g_things.deleteOne({ _id: new ObjectId(id) }, function (error) {
        if (error) return callback(error);
        callback(null);
    });
}

function exp(callback) {
    g_things.find({}).toArray(function (error, result) {
        if (error) return callback(error);
        if (!result) return (null, '');

        var fileName = path.join(os.tmpdir(), Date.now() + '.json');
        var out = result.map(function (thing) {
            return {
                createdAt: thing.createdAt,
                modifiedAt: thing.modifiedAt,
                content: thing.content,
                attachments: thing.attachments || []
            };
        });
        fs.writeFileSync(fileName, JSON.stringify({ things : out }, null, 4));

        callback(null, fileName);
    });
}

function imp(data, callback) {
    async.eachSeries(data.things, function (thing, next) {
        var tagObjects = extractTags(thing.content);
        var data = thing.content;

        var doc = {
            content: data,
            createdAt: thing.createdAt,
            modifiedAt: thing.modifiedAt || thing.createdAt,
            tags: tagObjects,
            attachments: thing.attachments || []
        };

        async.eachSeries(tagObjects, tags.update, function (error) {
            if (error) return next(error);

            g_things.insert(doc, function (error, result) {
                if (error) return next(error);
                if (!result) return next(new Error('no result returned'));

                next(null, result._id);
            });
        });
    }, callback);
}

function publicLink(id, callback) {
    var doc = {
        thingId: id,
        createdAt: new Date()
    };

    g_publicLinks.insert(doc, function (error, result) {
        if (error) return callback(error);
        if (!result) return callback(new Error('no result returned'));

        callback(null, result.insertedIds[0]);
    });
}

function getByShareId(shareId, callback) {
    g_publicLinks.find({ _id: new ObjectId(shareId) }).toArray(function (error, result) {
        if (error) return callback(error);
        if (result.length === 0) return callback(new Error('not found'));

        get(result[0].thingId, function (error, result) {
            if (error) return callback(error);

            callback(null, result);
        });
    });
}
<commit_msg>Use get() for the adding result<commit_after>/* jslint node:true */

'use strict';

exports = module.exports = {
    init: init,
    getAll: getAll,
    getAllLean: getAllLean,
    get: get,
    add: add,
    put: put,
    del: del,
    exp: exp,
    imp: imp,
    publicLink: publicLink,
    getByShareId: getByShareId,
    extractURLs: extractURLs,
    extractTags: extractTags,

    TYPE_IMAGE: 'image',
    TYPE_UNKNOWN: 'unknown'
};

var MongoClient = require('mongodb').MongoClient,
    ObjectId = require('mongodb').ObjectID,
    async = require('async'),
    fs = require('fs'),
    os = require('os'),
    config = require('./config.js'),
    tags = require('./tags.js'),
    path = require('path'),
    superagent = require('superagent');

var g_db, g_things, g_publicLinks;
var GET_URL = new RegExp('(^|[ \t\r\n])((ftp|http|https|gopher|mailto|news|nntp|telnet|wais|file|prospero|aim|webcal):(([A-Za-z0-9$_.+!*(),;/?:@&~=-])|%[A-Fa-f0-9]{2}){2,}(#([a-zA-Z0-9$_.+!*(),;/?:@&~=%-]*))?([A-Za-z0-9$_+!*();/?:~-]))', 'g');

function init(callback) {
    MongoClient.connect(config.databaseUrl, function (error, db) {
        if (error) return callback(error);

        g_db = db;
        g_db.createCollection('things');
        g_db.createCollection('publicLinks');
        g_things = db.collection('things');
        g_publicLinks = db.collection('publicLinks');

        g_things.createIndex({ content: 'text' }, { default_language: 'none' });

        callback(null);
    });
}

function extractURLs(content) {
    var lines = content.split('\n');
    var urls = [];

    lines.forEach(function (line) {
        var tmp = line.match(GET_URL);
        if (tmp === null) return;

        urls = urls.concat(tmp.map(function (url) {
            return url.trim();
        }));
    });

    return urls.filter(function (item, pos, self) {
        return self.indexOf(item) === pos;
    });
}

function extractTags(content) {
    var tagObjects = [];

    // first replace all urls which might contain # with placeholders
    var urls = extractURLs(content);
    urls.forEach(function (u) {
        content = content.replace(new RegExp(u, 'gmi'), ' --URL_PLACEHOLDER-- ');
    });

    var lines = content.split('\n');
    lines.forEach(function (line) {
        var tmp = line.match(/#(\w+)/g);
        if (tmp === null) return;

        tagObjects = tagObjects.concat(tmp.map(function (tag) {
            return tag.slice(1).toLowerCase();
        }));
    });

    return tagObjects;
}

function extractExternalContent(content, callback) {
    var urls = extractURLs(content);
    var externalContent = [];

    async.each(urls, function (url, callback) {
        superagent.get(url).end(function (error, result) {
            var obj = { url: url, type: exports.TYPE_UNKNOWN };

            if (error) {
                console.log('[WARN] failed to fetch external content %s', url);
            } else {
                if (result.type.indexOf('image/') === 0) {
                    obj = { url: url, type: exports.TYPE_IMAGE };
                }

                console.log('[INFO] external content type %s - %s', obj.type, obj.url);
            }

            externalContent.push(obj);

            callback(null);
        });
    }, function () {
        callback(null, externalContent);
    });
}

function facelift(thing, callback) {
    var data = thing.content;
    var tagObjects = thing.tags;
    var externalContent = thing.externalContent;
    var attachments = thing.attachments || [];

    function wrapper() {

        // Enrich with tag links
        tagObjects.forEach(function (tag) {
            data = data.replace(new RegExp('#' + tag, 'gmi'), '[#' + tag + '](#search?#' + tag + ')');
        });

        // Enrich with image links
        externalContent.forEach(function (obj) {
            if (obj.type === exports.TYPE_IMAGE) {
                data = data.replace(new RegExp(obj.url, 'gmi'), '![' + obj.url + '](' + obj.url + ')');
            }
        });

        // Enrich with attachments
        attachments.forEach(function (a) {
            if (a.type === exports.TYPE_IMAGE) {
                data = data.replace(new RegExp(a.fileName, 'gmi'), '![/api/files/' + a.identifier + '](/api/files/' + a.identifier + ')');
            } else {
                data = data.replace(new RegExp(a.fileName, 'gmi'), '[/api/files/' + a.identifier + '](/api/files/' + a.identifier + ')');
            }
        });

        callback(null, data);
    }

    if (Array.isArray(externalContent)) return wrapper();

    // old entry extract external content first
    extractExternalContent(thing.content, function (error, result) {
        if (error) {
            console.error('Failed to extract external content:', error);

            externalContent = [];

            return wrapper();
        }

        // set for wrapper()
        externalContent = result;

        console.log('[INFO] update %s with new external content.', thing._id, result);

        g_things.update({_id: new ObjectId(thing._id) }, { $set: { externalContent: result } }, function (error) {
            if (error) console.error('Failed to update external content:', error);

            wrapper();
        });
    });
}

function getAll(query, skip, limit, callback) {
    g_things.find(query).skip(skip).limit(limit).sort({ modifiedAt: -1 }).toArray(function (error, result) {
        if (error) return callback(error);
        if (!result) return callback(null, []);

        async.each(result, function (thing, callback) {
            facelift(thing, function (error, data) {
                if (error) console.error('Failed to facelift:', error);

                thing.attachments = thing.attachments || [];
                thing.richContent = data || thing.content;

                callback(null);
            });
        }, function () {
            callback(null, result);
        });
    });
}

function getAllLean(callback) {
    g_things.find({}).toArray(function (error, result) {
        if (error) return callback(error);
        callback(null, result || []);
    });
}

function get(id, callback) {
    g_things.find({ _id: new ObjectId(id) }).toArray(function (error, result) {
        if (error) return callback(error);
        if (result.length === 0) return callback(new Error('not found'));

        var thing = result[0];
        facelift(thing, function (error, data) {
            if (error) console.error('Failed to facelift:', error);

            thing.attachments = thing.attachments || [];
            thing.richContent = data || thing.content;

            callback(null, thing);
        });
    });
}

function add(content, attachments, callback) {

    extractExternalContent(content, function (error, result) {
        if (error) return callback(error);

        var doc = {
            content: content,
            createdAt: new Date(),
            modifiedAt: new Date(),
            tags: extractTags(content),
            externalContent: result,
            attachments: attachments
        };

        async.eachSeries(doc.tags, tags.update, function (error) {
            if (error) return callback(error);

            g_things.insert(doc, function (error, result) {
                if (error) return callback(error);
                if (!result) return callback(new Error('no result returned'));

                get(result.ops[0]._id, callback);
            });
        });
    });
}

function put(id, content, attachments, callback) {
    var tagObjects = extractTags(content);

    async.eachSeries(tagObjects, tags.update, function (error) {
        if (error) return callback(error);

        extractExternalContent(content, function (error, result) {
            if (error) console.error('Failed to extract external content:', error);

            var data = {
                content: content,
                tags: tagObjects,
                modifiedAt: new Date(),
                externalContent: result,
                attachments: attachments
            };

            g_things.update({_id: new ObjectId(id) }, { $set: data }, function (error) {
                if (error) return callback(error);

                get(id, callback);
            });
        });
    });
}

function del(id, callback) {
    g_things.deleteOne({ _id: new ObjectId(id) }, function (error) {
        if (error) return callback(error);
        callback(null);
    });
}

function exp(callback) {
    g_things.find({}).toArray(function (error, result) {
        if (error) return callback(error);
        if (!result) return (null, '');

        var fileName = path.join(os.tmpdir(), Date.now() + '.json');
        var out = result.map(function (thing) {
            return {
                createdAt: thing.createdAt,
                modifiedAt: thing.modifiedAt,
                content: thing.content,
                attachments: thing.attachments || []
            };
        });
        fs.writeFileSync(fileName, JSON.stringify({ things : out }, null, 4));

        callback(null, fileName);
    });
}

function imp(data, callback) {
    async.eachSeries(data.things, function (thing, next) {
        var tagObjects = extractTags(thing.content);
        var data = thing.content;

        var doc = {
            content: data,
            createdAt: thing.createdAt,
            modifiedAt: thing.modifiedAt || thing.createdAt,
            tags: tagObjects,
            attachments: thing.attachments || []
        };

        async.eachSeries(tagObjects, tags.update, function (error) {
            if (error) return next(error);

            g_things.insert(doc, function (error, result) {
                if (error) return next(error);
                if (!result) return next(new Error('no result returned'));

                next(null, result._id);
            });
        });
    }, callback);
}

function publicLink(id, callback) {
    var doc = {
        thingId: id,
        createdAt: new Date()
    };

    g_publicLinks.insert(doc, function (error, result) {
        if (error) return callback(error);
        if (!result) return callback(new Error('no result returned'));

        callback(null, result.insertedIds[0]);
    });
}

function getByShareId(shareId, callback) {
    g_publicLinks.find({ _id: new ObjectId(shareId) }).toArray(function (error, result) {
        if (error) return callback(error);
        if (result.length === 0) return callback(new Error('not found'));

        get(result[0].thingId, function (error, result) {
            if (error) return callback(error);

            callback(null, result);
        });
    });
}
<|endoftext|>


<commit_before>function parseSchedule(data, done) {
	var rootRef = new Firebase("https://sizzling-heat-3782.firebaseio.com/");
	var classesRef =  rootRef.child("Classes");
	var header = $(data).find('.staticheaders');
	var name = header.html();
	name = $.trim(name).substring(10,header.html().length-48)
	var userRef = rootRef.child("Users");
	var users;
	var userFound = false;
	var userID = 1;
	userRef.once("value", function(snapshot){
		users = snapshot.val();
		if (users) {
			$.each(users, function(key, userObject)
			{
				if(userObject.userName == name)
				{
					userFound = true;
					userID = key;
				}
			});
		}

		if(userFound == false)
		{
			userID = userRef.push().name();
			userRef.child(userID).set({userName: name});
		}

		//gets bolded class name, e.x.: Microcomputers I - CE 320 - 01
		$(data).find('.captiontext').each(function()
		{
			var parsedClassName = $(this).html();
			var classes;
			var classFound = false;
			var classExists = false;
			if(!(parsedClassName == "Scheduled Meeting Times"))
			{

				classesRef.once("value", function(snapshot){
					classes = snapshot.val();

					if (classes) {
						$.each(classes, function(key, classObject){
							if(parsedClassName == classObject.ClassName)
							{
								userRef.child(userID + "/Classes").once("value", function(snapshot){
									classes2 = snapshot.val();

									if (classes2) {
										$.each(classes2, function(key2, userClassObject)
										{
											if(userClassObject.ClassName == parsedClassName)
											{
												classExists = true;
											}
										});

									}
									if(!classExists)
									{
										userRef.child(userID + "/Classes").push({ClassName : parsedClassName, classKey : key});
									}
								});
								classFound = true;
							}
						});
					}

					if(classFound == false)
					{
						var classId = classesRef.push().name();
						classesRef.child(classId).set({ClassName : parsedClassName});
						userRef.child(userID + "/Classes").push({ClassName : parsedClassName, classKey : classId});
					}

					done && done();
					return userRef.child(userID).val();
				});
			}
		});

	});

}
<commit_msg>trying to fix return val from parsing<commit_after>function parseSchedule(data, done) {
	var rootRef = new Firebase("https://sizzling-heat-3782.firebaseio.com/");
	var classesRef =  rootRef.child("Classes");
	var header = $(data).find('.staticheaders');
	var name = header.html();
	name = $.trim(name).substring(10,header.html().length-48)
	var userRef = rootRef.child("Users");
	var users;
	var userFound = false;
	var userID = 1;
	var returnVal;
	userRef.once("value", function(snapshot){
		users = snapshot.val();
		if (users) {
			$.each(users, function(key, userObject)
			{
				if(userObject.userName == name)
				{
					userFound = true;
					userID = key;
				}
			});
		}

		if(userFound == false)
		{
			userID = userRef.push().name();
			userRef.child(userID).set({userName: name});
		}

		//gets bolded class name, e.x.: Microcomputers I - CE 320 - 01
		$(data).find('.captiontext').each(function()
		{
			var parsedClassName = $(this).html();
			var classes;
			var classFound = false;
			var classExists = false;
			if(!(parsedClassName == "Scheduled Meeting Times"))
			{

				classesRef.once("value", function(snapshot){
					classes = snapshot.val();

					if (classes) {
						$.each(classes, function(key, classObject){
							if(parsedClassName == classObject.ClassName)
							{
								userRef.child(userID + "/Classes").once("value", function(snapshot){
									classes2 = snapshot.val();

									if (classes2) {
										$.each(classes2, function(key2, userClassObject)
										{
											if(userClassObject.ClassName == parsedClassName)
											{
												classExists = true;
											}
										});

									}
									if(!classExists)
									{
										userRef.child(userID + "/Classes").push({ClassName : parsedClassName, classKey : key});
									}
								});
								classFound = true;
							}
						});
					}

					if(classFound == false)
					{
						var classId = classesRef.push().name();
						classesRef.child(classId).set({ClassName : parsedClassName});
						userRef.child(userID + "/Classes").push({ClassName : parsedClassName, classKey : classId});
					}

					done && done();
					var tempRef = userRef.child(userID);
					tempRef.once("value", function(snapshot){
						returnVal =  tempRef.val();
					});
				});
			}
		});

	});
	return returnVal;
}
<|endoftext|>


<commit_before>/*
===============================================================================

    Element defines additional game variables and methods to perform
    mathematical calculations, simplify inheritance and work with HTML5.

===============================================================================
*/

/*
================
extend
    Extends `Child` from `Parent`.
    Fixes constructor and adds parent class link as `super`.
================
*/
function extend( Child, Parent ) {
    var F = function () {};
    F.prototype = Parent.prototype;
    Child.prototype = new F();
    Child.prototype.constructor = Child;
    Child.super = Parent.prototype;
}

/*
================
mixin
    Copies new properties from `src` to `dst`.
    Properties of the `Object` will be ignored.
================
*/
function mixin( dst, src ) {
    // filters `Object` variables and methods
    var filter = {};
    for ( var x in src ){
        if ( (typeof filter[x] === "undefined") || (filter[x] !== src[x]) ) {
            dst[x] = src[x];
        }
    }
}

/*
-------------------------------------------------------------------------------
    CACHE
-------------------------------------------------------------------------------
*/
function Cache() {
    if ( !(this instanceof Cache) ) return new Cache();

    this._values = {};
}

/*
=================
get
    Gets Element by key.
=================
*/
Cache.prototype.get = function ( key ) {
    return this._values[ key ];
};

/*
=================
set
    Sets element value or adds new element.
=================
*/
Cache.prototype.set = function ( key, value, group ) {
    this._values[ key ] = value;
    this._values[ key ]._group = group;
    return this._values[ key ];
};

/*
=================
add
    Adds only new element.
=================
*/
Cache.prototype.add = function ( key, value, group ) {
    if ( this._values[ key ] === undefined ) {
        this._values[ key ] = value;
        this._values[ key ]._group = group;
    }
    return this._values[ key ];
};

/*
=================
remove
    Removes element.
=================
*/
Cache.prototype.remove = function ( key ) {
    delete this._values[ key ];
};

// For group adding use mixin() method

/*
=================
removeKeys
    Removes set of variables.
=================
*/
Cache.prototype.removeKeys = function ( keys ) {
    for ( var i in keys ) {
        delete this._values[ keys[ i ] ];
    }
};

/*
=================
removeGroup
    Removes set of variables.
=================
*/
Cache.prototype.removeGroup = function ( group ) {
    for ( var k in this._values ) {
        if ( this._values[ k ]._group === group ) {
            delete this._values[ keys[ i ] ];
        }
    }
};

/*
=================
contains
    Returns true if key is present in _values, otherwise - false.
=================
*/
Cache.prototype.contains = function ( key ) {
    return key in this._values;
};

/*
-------------------------------------------------------------------------------
    STRING
-------------------------------------------------------------------------------
*/
/*
=================
hashCode
    Javascript implementation of Java's String.hashCode() method.
=================
*/
String.prototype.hashCode = function() {
    if ( this.length === 0 ) return hash;

    var hash = 0;
    for ( i = 0; i < this.length; i++ ) {
        var char = this.charCodeAt( i );
        hash = ( ( hash << 5 ) - hash ) + char;
        hash = hash & hash; // Convert to 32bit integer
    }
    return hash;
};
Object.defineProperty( String.prototype, 'hashCode', { writable: false } );

/*
-------------------------------------------------------------------------------
    MATH
-------------------------------------------------------------------------------
*/
Math.PI_2 = Math.PI / 2;
Object.defineProperty( Math, 'PI_2', { writable: false } );

Math.PI2  = Math.PI * 2;
Object.defineProperty( Math, 'PI2', { writable: false } );

/*
=================
logab
    Evaluates LOGa(b) as LN(b)/LN(a)
=================
*/
Math.logab = function ( a, b ) {
    if ( a === 2 ) {
        return Math.log( b ) / Math.LN2;
    } else if ( a === 10 ) {
        return Math.log( b ) / Math.LN10;
    } else {
        return Math.log( b ) / Math.log( a );
    }
};
Object.defineProperty( Math, 'logab', { writable: false } );
<commit_msg>Fix Cache methods counter.<commit_after>/*
===============================================================================

    Element defines additional game variables and methods to perform
    mathematical calculations, simplify inheritance and work with HTML5.

===============================================================================
*/

/*
================
extend
    Extends `Child` from `Parent`.
    Fixes constructor and adds parent class link as `super`.
================
*/
function extend( Child, Parent ) {
    var F = function () {};
    F.prototype = Parent.prototype;
    Child.prototype = new F();
    Child.prototype.constructor = Child;
    Child.super = Parent.prototype;
}

/*
================
mixin
    Copies new properties from `src` to `dst`.
    Properties of the `Object` will be ignored.
================
*/
function mixin( dst, src ) {
    // filters `Object` variables and methods
    var filter = {};
    for ( var k in src ){
        if ( ( typeof filter[ k ] === "undefined" ) || ( filter[ k ] !== src[ k ] ) ) {
            dst[ k ] = src[ k ];
        }
    }
}

/*
-------------------------------------------------------------------------------
    CACHE
-------------------------------------------------------------------------------
*/
function Cache() {
    if ( !(this instanceof Cache) ) return new Cache();

    this._values = {};
}

/*
=================
get
    Gets Element by key.
=================
*/
Cache.prototype.get = function ( key ) {
    return this._values[ key ];
};

/*
=================
set
    Sets element value or adds new element.
=================
*/
Cache.prototype.set = function ( key, value, group ) {
    this._values[ key ] = value;
    this._values[ key ]._group = group;
    return this._values[ key ];
};

/*
=================
add
    Adds only new element.
=================
*/
Cache.prototype.add = function ( key, value, group ) {
    if ( this._values[ key ] === undefined ) {
        this._values[ key ] = value;
        this._values[ key ]._group = group;
    }
    return this._values[ key ];
};

/*
=================
remove
    Removes element.
=================
*/
Cache.prototype.remove = function ( key ) {
    delete this._values[ key ];
};

// For group adding use mixin() method

/*
=================
removeKeys
    Removes set of variables.
=================
*/
Cache.prototype.removeKeys = function ( keys ) {
    for ( var k in keys ) {
        delete this._values[ keys[ k ] ];
    }
};

/*
=================
removeGroup
    Removes set of variables.
=================
*/
Cache.prototype.removeGroup = function ( group ) {
    for ( var k in this._values ) {
        if ( this._values[ k ]._group === group ) {
            delete this._values[ keys[ k ] ];
        }
    }
};

/*
=================
contains
    Returns true if key is present in _values, otherwise - false.
=================
*/
Cache.prototype.contains = function ( key ) {
    return key in this._values;
};

/*
-------------------------------------------------------------------------------
    STRING
-------------------------------------------------------------------------------
*/
/*
=================
hashCode
    Javascript implementation of Java's String.hashCode() method.
=================
*/
String.prototype.hashCode = function() {
    if ( this.length === 0 ) return hash;

    var hash = 0;
    for ( var i = 0; i < this.length; i++ ) {
        var char = this.charCodeAt( i );
        hash = ( ( hash << 5 ) - hash ) + char;
        hash = hash & hash; // Convert to 32bit integer
    }
    return hash;
};
Object.defineProperty( String.prototype, 'hashCode', { writable: false } );

/*
-------------------------------------------------------------------------------
    MATH
-------------------------------------------------------------------------------
*/
Math.PI_2 = Math.PI / 2;
Object.defineProperty( Math, 'PI_2', { writable: false } );

Math.PI2  = Math.PI * 2;
Object.defineProperty( Math, 'PI2', { writable: false } );

/*
=================
logab
    Evaluates LOGa(b) as LN(b)/LN(a)
=================
*/
Math.logab = function ( a, b ) {
    if ( a === 2 ) {
        return Math.log( b ) / Math.LN2;
    } else if ( a === 10 ) {
        return Math.log( b ) / Math.LN10;
    } else {
        return Math.log( b ) / Math.log( a );
    }
};
Object.defineProperty( Math, 'logab', { writable: false } );
<|endoftext|>


<commit_before>angular.module('ngNamedRoute').provider('namedRouteService', function ($locationProvider) {
    'use strict';

    this.$get = /*@ngInject*/ function ($route, $location, $browser) {
        //map name to route
        var routemap = {};

        Object.keys($route.routes).forEach(function (path) {
            var route = $route.routes[path];
            if (route.name) {
                if (routemap.hasOwnProperty(route.name)) {
                    throw new Error("Route name [" + route.name + "] defined more than once.");
                }
                routemap[route.name] = {
                    path: path,
                    route: route
                };
            }
        });

        function reverse(name, args, query_params) {
            var idx = -1, url;

            if (!routemap.hasOwnProperty(name)) {
                throw new Error("Route name [" + name + "] not known.");
            }

            url = routemap[name].path.replace(/(:\w+[\*\?]{0,1})/g, function (match, p) {
                idx++;

                p = p.substring(1);

                var placeholder = p[p.length - 1] === '?' ? '' : '?';
                if (p[p.length - 1] === '*' || p[p.length - 1] === '?') {
                    p = p.substring(0, p.length - 1);
                }

                //arguments is an array: resolve positional parameter
                if (angular.isArray(args)) {
                    return idx < args.length ? args[idx] : placeholder;
                }

                //argument is an object: resolve property
                if (angular.isObject(args)) {
                    if (args.hasOwnProperty(p)) {
                        return args[p];
                    }
                    return placeholder;
                }

                //it's string or number, return as is, unless more than one is required
                if (!idx) {
                    return args === undefined ? placeholder : args;
                }

                return '?';
            });

            if (query_params) {
                url += '?' + Object.keys(query_params).map(function (key) {
                    var val = query_params[key];
                    if (angular.isArray(val)) {
                        return val.map(function (val) {
                            return key + '=' + encodeURIComponent(val);
                        }).join('&');
                    }
                    return key + '=' + encodeURIComponent(val);
                }).join('&');
            }

            if ($browser.baseHref() === '/') {
                // No need to append '/'
                return url;
            } else {
                // Prepend the base href
                return $browser.baseHref() + url;
            }
        }

        return {
            reverse: reverse,
            open: function (name, args) {
                $location.path(reverse(name, args));
            },
            hashPrefix: function () { return $locationProvider.hashPrefix(); }
        };
    };
});
<commit_msg>Implement provider configuration function for alwaysPrefixBase().<commit_after>angular.module('ngNamedRoute').provider('namedRouteService', function ($locationProvider) {
    'use strict';

    /** Internal configuration variable. */
    var shouldAlwaysPrefixBase = false;

    /**
     * Sets whether the service should always prefix the <base href />.
     */
    this.alwaysPrefixBase = function (value) {
        if (value === undefined) {
            return shouldAlwaysPrefixBase;
        }

        shouldAlwaysPrefixBase = value;

        return this;
    };

    this.$get = /*@ngInject*/ function ($route, $location, $browser) {
        //map name to route
        var routemap = {};

        Object.keys($route.routes).forEach(function (path) {
            var route = $route.routes[path];
            if (route.name) {
                if (routemap.hasOwnProperty(route.name)) {
                    throw new Error("Route name [" + route.name + "] defined more than once.");
                }
                routemap[route.name] = {
                    path: path,
                    route: route
                };
            }
        });

        function reverse(name, args, query_params) {
            var idx = -1, url;

            if (!routemap.hasOwnProperty(name)) {
                throw new Error("Route name [" + name + "] not known.");
            }

            url = routemap[name].path.replace(/(:\w+[\*\?]{0,1})/g, function (match, p) {
                idx++;

                p = p.substring(1);

                var placeholder = p[p.length - 1] === '?' ? '' : '?';
                if (p[p.length - 1] === '*' || p[p.length - 1] === '?') {
                    p = p.substring(0, p.length - 1);
                }

                //arguments is an array: resolve positional parameter
                if (angular.isArray(args)) {
                    return idx < args.length ? args[idx] : placeholder;
                }

                //argument is an object: resolve property
                if (angular.isObject(args)) {
                    if (args.hasOwnProperty(p)) {
                        return args[p];
                    }
                    return placeholder;
                }

                //it's string or number, return as is, unless more than one is required
                if (!idx) {
                    return args === undefined ? placeholder : args;
                }

                return '?';
            });

            if (query_params) {
                url += '?' + Object.keys(query_params).map(function (key) {
                    var val = query_params[key];
                    if (angular.isArray(val)) {
                        return val.map(function (val) {
                            return key + '=' + encodeURIComponent(val);
                        }).join('&');
                    }
                    return key + '=' + encodeURIComponent(val);
                }).join('&');
            }

            if (shouldAlwaysPrefixBase) {
                if ($browser.baseHref() === '/') {
                    // No need to append '/'
                    return url;
                }
                // Prepend the base href
                return $browser.baseHref() + url;
            }

            return url;
        }

        return {
            reverse: reverse,
            open: function (name, args) {
                $location.path(reverse(name, args));
            },
            hashPrefix: function () { return $locationProvider.hashPrefix(); }
        };
    };
});
<|endoftext|>


<commit_before>/**
 * @license
 * The MIT License (MIT)
 * Copyright 2015 Government of Canada
 *
 * @author
 * Ian Boyes
 *
 * @exports IsolateAdd
 */

import React from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { Modal } from "react-bootstrap";

import { addIsolate, hideVirusModal } from "../../actions";
import { Button } from "../../../base";
import IsolateForm from "./IsolateForm";

const getInitialState = (props) => ({
    sourceType: props.restrictSourceTypes ? "unknown" : "",
    sourceName: ""
});

class AddIsolate extends React.Component {

    constructor (props) {
        super(props);
        this.state = getInitialState(this.props);
    }

    static propTypes = {
        virusId: PropTypes.string,
        allowedSourceTypes: PropTypes.array,
        restrictSourceTypes: PropTypes.bool,
        show: PropTypes.bool,
        onHide: PropTypes.func,
        onSave: PropTypes.func
    };

    handleChange = (update) => {
        this.setState(update);
    };

    handleSubmit = () => {
        this.props.onSave(this.props.virusId, this.state.sourceType, this.state.sourceName);
    };

    render () {
        return (
            <Modal show={this.props.show} onEntered={this.handleModalEntered} onHide={this.props.onHide}>
                <Modal.Header onHide={this.props.onHide} closeButton>
                    Add Isolate
                </Modal.Header>
                <Modal.Body>
                    <IsolateForm
                        ref={(node) => this.formNode = node}
                        sourceType={this.state.sourceType}
                        sourceName={this.state.sourceName}
                        allowedSourceTypes={this.props.allowedSourceTypes}
                        restrictSourceTypes={this.props.restrictSourceTypes}
                        onChange={this.handleChange}
                        onSubmit={this.handleSubmit}
                    />
                </Modal.Body>
                <Modal.Footer>
                    <Button bsStyle="primary" icon="floppy" onClick={this.save}>
                        Save
                    </Button>
                </Modal.Footer>
            </Modal>
        );
    }
}

const mapStateToProps = state => ({
    show: state.viruses.addIsolate,
    allowedSourceTypes: state.settings.data.allowed_source_types,
    restrictSourceTypes: state.settings.data.restrict_source_types
});

const mapDispatchToProps = dispatch => ({

    onHide: () => {
        dispatch(hideVirusModal());
    },

    onSave: (virusId, sourceType, sourceName) => {
        dispatch(addIsolate(virusId, sourceType, sourceName));
    }

});

const Container = connect(mapStateToProps, mapDispatchToProps)(AddIsolate);

export default Container;
<commit_msg>Fix isolate add<commit_after>/**
 * @license
 * The MIT License (MIT)
 * Copyright 2015 Government of Canada
 *
 * @author
 * Ian Boyes
 *
 * @exports IsolateAdd
 */

import React from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { Modal } from "react-bootstrap";

import { addIsolate, hideVirusModal } from "../../actions";
import { Button } from "../../../base";
import IsolateForm from "./IsolateForm";

const getInitialState = (props) => ({
    sourceType: props.restrictSourceTypes ? "unknown" : "",
    sourceName: ""
});

class AddIsolate extends React.Component {

    constructor (props) {
        super(props);
        this.state = getInitialState(this.props);
    }

    static propTypes = {
        virusId: PropTypes.string,
        allowedSourceTypes: PropTypes.array,
        restrictSourceTypes: PropTypes.bool,
        show: PropTypes.bool,
        onHide: PropTypes.func,
        onSave: PropTypes.func
    };

    handleChange = (update) => {
        this.setState(update);
    };

    handleSubmit = () => {
        this.props.onSave(this.props.virusId, this.state.sourceType, this.state.sourceName);
    };

    render () {
        return (
            <Modal show={this.props.show} onEntered={this.handleModalEntered} onHide={this.props.onHide}>
                <Modal.Header onHide={this.props.onHide} closeButton>
                    Add Isolate
                </Modal.Header>
                <Modal.Body>
                    <IsolateForm
                        ref={(node) => this.formNode = node}
                        sourceType={this.state.sourceType}
                        sourceName={this.state.sourceName}
                        allowedSourceTypes={this.props.allowedSourceTypes}
                        restrictSourceTypes={this.props.restrictSourceTypes}
                        onChange={this.handleChange}
                    />
                </Modal.Body>
                <Modal.Footer>
                    <Button bsStyle="primary" icon="floppy" onClick={this.handleSubmit}>
                        Save
                    </Button>
                </Modal.Footer>
            </Modal>
        );
    }
}

const mapStateToProps = state => ({
    show: state.viruses.addIsolate,
    allowedSourceTypes: state.settings.data.allowed_source_types,
    restrictSourceTypes: state.settings.data.restrict_source_types
});

const mapDispatchToProps = dispatch => ({

    onHide: () => {
        dispatch(hideVirusModal());
    },

    onSave: (virusId, sourceType, sourceName) => {
        dispatch(addIsolate(virusId, sourceType, sourceName));
    }

});

const Container = connect(mapStateToProps, mapDispatchToProps)(AddIsolate);

export default Container;
<|endoftext|>


<commit_before>var hasOwn = Object.prototype.hasOwnProperty;
var entryMap = Object.create(null);
var utils = require("./utils.js");

function Entry(id) {
  // Same as module.id for this module.
  this.id = id;
  // The number of times this.runModuleSetters has been called.
  this.runCount = 0;
  // Map from parent module identifiers to parent module objects.
  this.parents = Object.create(null);
  // Setters for assigning to local variables in parent modules.
  this.setters = Object.create(null);
  // Getters for local variables exported from this module.
  this.getters = Object.create(null);
}

var Ep = Entry.prototype;

Entry.get = function (id) {
  return entryMap[id] || null;
};

Entry.getOrCreate = function (id) {
  return entryMap[id] = entryMap[id] || new Entry(id);
};

Ep.addSetters = function (parent, setters) {
  var entry = this;

  // Register the parent module so we can call runParentSetters later.
  entry.parents[parent.id] = parent;

  Object.keys(setters).forEach(function (name) {
    var setter = setters[name];
    if (typeof setter === "function" &&
        // Ignore any requests for the exports.__esModule property."
        name !== "__esModule") {
      (entry.setters[name] =
       entry.setters[name] || []
      ).push(setter);
    }
  });
};

Ep.addGetters = function (getters) {
  var entry = this;
  Object.keys(getters).forEach(function (name) {
    var getter = getters[name];
    if (typeof getter === "function" &&
        // Ignore any requests for the exports.__esModule property."
        name !== "__esModule") {
      // Should this throw if hasOwn.call(this.getters, name)?
      entry.getters[name] = getter;
    }
  });
};

function runModuleSetters(module) {
  var entry = entryMap[module.id];
  if (entry) {
    entry.runModuleSetters(module);
  }
}

function runModuleGetters(module) {
  var entry = entryMap[module.id];
  return entry ? entry.runModuleGetters(module) : 0;
}

Ep.runModuleGetters = function (module) {
  var entry = this;
  var changeCount = 0;

  Object.keys(entry.getters).forEach(function (name) {
    if (entry.runGetter(module, name)) {
      ++changeCount;
    }
  });

  return changeCount;
};

// Returns true iff the getter updated module.exports with a new value.
Ep.runGetter = function (module, name) {
  if (! hasOwn.call(this.getters, name)) {
    return false;
  }

  var getter = this.getters[name];
  try {
    var value = getter.call(module);
  } catch (e) {}
  var exports = module.exports;

  if (! hasOwn.call(exports, name) ||
      exports[name] !== value) {
    // We update module.exports[name] with the current value so that
    // CommonJS require calls remain consistent with module.import.
    exports[name] = value;
    return true;
  }

  return false;
};

Ep.runModuleSetters = function (module) {
  var entry = this;
  var parents = this.parents;
  var snapshots = Object.create(null);

  Object.keys(parents).forEach(function (id) {
    var parent = parents[id];
    var exports = parent.exports;
    if (utils.isPlainObject(exports)) {
      // If parent.exports is an object, make a shallow clone of it so
      // that we can see if it changes as a result of calling setters.
      snapshots[id] = utils.assign({}, exports);
    } else {
      // If parent.exports is not an object, the "snapshot" is just the
      // value of parent.exports.
      snapshots[id] = exports;
    }
  });

  // Make sure module.exports is up to date before we call
  // module.getExportByName(name).
  entry.runModuleGetters(module);

  Object.keys(entry.setters).forEach(function (name) {
    var value = module.getExportByName(name);

    entry.setters[name].forEach(function (setter) {
      if (name === "*") {
        Object.keys(value).forEach(function (name) {
          if (name !== "__esModule") {
            callSetter(module, setter, name, value[name]);
          }
        });
      } else {
        callSetter(module, setter, name, value);
      }
    });
  });

  ++entry.runCount;

  // If any of the setters updated the module.exports of a parent module,
  // or updated local variables that are exported by that parent module,
  // then we must re-run any setters registered by that parent module.
  Object.keys(parents).forEach(function (id) {
    var parent = parents[id];

    if (runModuleGetters(parent) > 0) {
      return runModuleSetters(parent);
    }

    var exports = parent.exports;
    var snapshot = snapshots[parent.id];
    if (utils.shallowObjEqual(exports, snapshot)) {
      return;
    }

    runModuleSetters(parent);
  });
};

function callSetter(module, setter, name, value) {
  setter.last = setter.last || Object.create(null);
  if (! hasOwn.call(setter.last, name) ||
      value !== setter.last[name]) {
    return setter.call(
      module,
      setter.last[name] = value,
      name
    );
  }
}

exports.Entry = Entry;
<commit_msg>Store setter.parent instead of entry.parents to optimize snapshotting.<commit_after>var hasOwn = Object.prototype.hasOwnProperty;
var entryMap = Object.create(null);
var utils = require("./utils.js");

function Entry(id) {
  // Same as module.id for this module.
  this.id = id;
  // The number of times this.runModuleSetters has been called.
  this.runCount = 0;
  // Setters for assigning to local variables in parent modules.
  this.setters = Object.create(null);
  // Getters for local variables exported from this module.
  this.getters = Object.create(null);
}

var Ep = Entry.prototype;

Entry.get = function (id) {
  return entryMap[id] || null;
};

Entry.getOrCreate = function (id) {
  return entryMap[id] = entryMap[id] || new Entry(id);
};

Ep.addSetters = function (parent, setters) {
  var entry = this;

  Object.keys(setters).forEach(function (name) {
    var setter = setters[name];
    if (typeof setter === "function" &&
        // Ignore any requests for the exports.__esModule property."
        name !== "__esModule") {
      setter.parent = parent;
      (entry.setters[name] =
       entry.setters[name] || []
      ).push(setter);
    }
  });
};

Ep.addGetters = function (getters) {
  var entry = this;
  Object.keys(getters).forEach(function (name) {
    var getter = getters[name];
    if (typeof getter === "function" &&
        // Ignore any requests for the exports.__esModule property."
        name !== "__esModule") {
      // Should this throw if hasOwn.call(this.getters, name)?
      entry.getters[name] = getter;
    }
  });
};

function runModuleSetters(module) {
  var entry = entryMap[module.id];
  if (entry) {
    entry.runModuleSetters(module);
  }
}

function runModuleGetters(module) {
  var entry = entryMap[module.id];
  return entry ? entry.runModuleGetters(module) : 0;
}

Ep.runModuleGetters = function (module) {
  var entry = this;
  var changeCount = 0;

  Object.keys(entry.getters).forEach(function (name) {
    if (entry.runGetter(module, name)) {
      ++changeCount;
    }
  });

  return changeCount;
};

// Returns true iff the getter updated module.exports with a new value.
Ep.runGetter = function (module, name) {
  if (! hasOwn.call(this.getters, name)) {
    return false;
  }

  var getter = this.getters[name];
  try {
    var value = getter.call(module);
  } catch (e) {}
  var exports = module.exports;

  if (! hasOwn.call(exports, name) ||
      exports[name] !== value) {
    // We update module.exports[name] with the current value so that
    // CommonJS require calls remain consistent with module.import.
    exports[name] = value;
    return true;
  }

  return false;
};

// Called whenever module.exports might have changed, to trigger any
// setters associated with the newly exported values.
Ep.runModuleSetters = function (module) {
  var entry = this;
  var names = Object.keys(entry.setters);

  // Make sure module.exports is up to date before we call
  // module.getExportByName(name).
  entry.runModuleGetters(module);

  // Invoke the given callback once for every (setter, value, name) triple
  // that needs to be called. Note that forEachSetter does not call any
  // setters itself, only the given callback.
  function forEachSetter(callback, context) {
    names.forEach(function (name) {
      entry.setters[name].forEach(function (setter) {
        var value = module.getExportByName(name);
        if (name === "*") {
          Object.keys(value).forEach(function (name) {
            call(setter, value[name], name);
          });
        } else {
          call(setter, value, name);
        }
      });
    });

    function call(setter, value, name) {
      if (name === "__esModule") {
        // Ignore setters asking for module.exports.__esModule.
        return;
      }

      setter.last = setter.last || Object.create(null);

      if (! hasOwn.call(setter.last, name) ||
          setter.last[name] !== value) {
        // Only invoke the callback if we have not called this setter
        // (with a value of this name) before, or the current value is
        // different from the last value we passed to this setter.
        return callback.apply(context, arguments);
      }
    }
  }

  // Lazily-initialized objects mapping parent module identifiers to
  // relevant parent module objects and snapshots of their exports.
  var relevantParents;
  var parentSnapshots;

  // Take snapshots of setter.parent.exports for any setters that we are
  // planning to call, so that we can later determine if calling the
  // setters modified any of those exports objects.
  forEachSetter(function (setter) {
    var parent = setter.parent;
    parentSnapshots = parentSnapshots || Object.create(null);
    if (! hasOwn.call(parentSnapshots, parent.id)) {
      relevantParents = relevantParents || Object.create(null);
      relevantParents[parent.id] = parent;
      if (utils.isPlainObject(parent.exports)) {
        // If parent.exports is an object, make a shallow clone of it so
        // that we can see if it changes as a result of calling setters.
        parentSnapshots[parent.id] = utils.assign({}, parent.exports);
      } else {
        // If parent.exports is not an object, the "snapshot" is just the
        // value of parent.exports.
        parentSnapshots[parent.id] = parent.exports;
      }
    }
  });

  // Now call all the setters that we decided we need to call.
  forEachSetter(function (setter, value, name) {
    setter.call(module, setter.last[name] = value, name);
  });

  ++entry.runCount;

  if (! relevantParents) {
    // If we never called takeSnapshot, then we can avoid checking
    // relevantParents and parentSnapshots below.
    return;
  }

  // If any of the setters updated the module.exports of a parent module,
  // or updated local variables that are exported by that parent module,
  // then we must re-run any setters registered by that parent module.
  Object.keys(relevantParents).forEach(function (id) {
    var parent = relevantParents[id];

    if (runModuleGetters(parent) > 0) {
      return runModuleSetters(parent);
    }

    var exports = parent.exports;
    var snapshot = parentSnapshots[parent.id];
    if (utils.shallowObjEqual(exports, snapshot)) {
      // If parent.exports have not changed since we took the snapshot,
      // then we do not need to run the parent's setters.
      return;
    }

    runModuleSetters(parent);
  });
};

exports.Entry = Entry;
<|endoftext|>


<commit_before>/**
 * Created by GYX on 15/7/3.
 */

var MailControl = require("../common/mail");

var mailFs = require('../common/mailFs');

var Mail = require("../proxy").Mail;

exports.getConfig = function (callback) {

        mailFs.readMailConfig(callback);

};

exports.setConfig =function(config,callback) {

    var mailControl = new MailControl(config);
    mailControl.startSMTPConnection();

    //测试SMTP
    var mailOptions = {
        from: config.mailAddress, // sender address
        to: '450024927@qq.com', // list of receivers
        subject: 'Hello ', // Subject line
        text: 'Hello world ', // plaintext body
        html: '<b>Hello world </b>' // html body
    };
    var onerror = function (error, info) {
        if (error) {
            callback(104, "无法连接到smtp服务器");
            mailControl.stopSMTPConnection();
        } else {
            //测试IMAP
            mailControl.stopSMTPConnection();
            mailControl.imapTest(function (err, msg) {
                if (err != 0) {
                    callback(err, msg);
                }
                else {
                    mailFs.writeMailConfig(config, function (err) {
                        if (err) callback(-1, "internal error");

                        callback(0, 'success');

                        Mail.clear();
                        mailControl.openBox("INBOX", ["ALL"], function (mail) {

                            Mail.newAndSave(mail);
                        },null);
                    });
                }
            });
        }
    };

    mailControl.sendMail(mailOptions,onerror);
};

<commit_msg>设置邮箱之后获取邮件<commit_after>/**
 * Created by GYX on 15/7/3.
 */

var MailControl = require("../common/mail");

var mailFs = require('../common/mailFs');

var Mail = require("../proxy").Mail;

exports.getConfig = function (callback) {

        mailFs.readMailConfig(callback);

};

exports.setConfig =function(config,callback) {

    var mailControl = new MailControl(config);
    mailControl.startSMTPConnection();

    //测试SMTP
    var mailOptions = {
        from: config.mailAddress, // sender address
        to: '450024927@qq.com', // list of receivers
        subject: 'Hello ', // Subject line
        text: 'Hello world ', // plaintext body
        html: '<b>Hello world </b>' // html body
    };
    var onerror = function (error, info) {
        if (error) {
            callback(104, "无法连接到smtp服务器");
            mailControl.stopSMTPConnection();
        } else {
            //测试IMAP
            mailControl.stopSMTPConnection();
            mailControl.imapTest(function (err, msg) {
                if (err != 0) {
                    callback(err, msg);
                }
                else {
                    mailFs.writeMailConfig(config, function (err) {
                        if (err) callback(-1, "internal error");

                        callback(0, 'success');

                        Mail.clear();
                        mailControl.openBox("INBOX", ["ALL"], function (mail) {
                            Mail.newAndSave(mail);
                        },function(err){
                            console.log(err);
                        });
                    });
                }
            });
        }
    };

    mailControl.sendMail(mailOptions,onerror);
};

<|endoftext|>


<commit_before>/* eslint unicorn/filename-case: "off", func-names: "off", camelcase: "off", no-unused-vars: "off" */

module.exports = function (iface) {
    const {mqttPub, mqttSub, mqttStatus, log, Service, Characteristic} = iface;

    /*
     // Required Characteristics
     this.addCharacteristic(Characteristic.BatteryLevel);
     this.addCharacteristic(Characteristic.ChargingState);
     this.addCharacteristic(Characteristic.StatusLowBattery);

     // Optional Characteristics
     this.addOptionalCharacteristic(Characteristic.Name);

     // The value property of StatusLowBattery must be one of the following:
     Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL = 0;
     Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW = 1;

     // The value property of ChargingState must be one of the following:
     Characteristic.ChargingState.NOT_CHARGING = 0;
     Characteristic.ChargingState.CHARGING = 1;
     Characteristic.ChargingState.NOT_CHARGEABLE = 2;
     */

    return function createService_BatteryService(acc, settings) {
        acc.addService(Service.BatteryService);
        /*
            .getCharacteristic(Characteristic.BatteryLevel)
            .on('get', callback => {
                log.debug('< hap get', settings.name, 'BatteryLevel');
                const level = mqttStatus[settings.topic.statusBatteryLevel];
                log.debug('> hap re_get', settings.name, 'BatteryLevel', level);
                callback(null, level);
            });
            */

        mqttSub(settings.topic.statusBatteryLevel, val => {
            if (settings.config && (typeof settings.payload.maxBatteryLevel !== 'undefined')) {
                const max = settings.payload.maxBatteryLevel;
                const min = settings.payload.minBatteryLevel || 0;
                const range = max - min;
                val = ((val - min) / range) * 100;
            }
            log.debug('> hap update', settings.name, 'BatteryLevel', val);
            acc.getService(Service.BatteryService)
                .updateCharacteristic(Characteristic.BatteryLevel, val);
        });

        mqttSub(settings.topic.statusChargingState, val => {
            log.debug('> hap update', settings.name, 'ChargingState', val);
            acc.getService(Service.BatteryService)
                .updateCharacteristic(Characteristic.ChargingState, val);
        });

        mqttSub(settings.topic.statusLowBattery, val => {
            val = (val === settings.payload.onLowBattery) ? 1 : 0;
            log.debug('> hap update', settings.name, 'StatusLowBattery', val);
            acc.getService(Service.BatteryService)
                .updateCharacteristic(Characteristic.StatusLowBattery, val);
        });
    };
};
<commit_msg>dont subscribe empty topics<commit_after>/* eslint unicorn/filename-case: "off", func-names: "off", camelcase: "off", no-unused-vars: "off" */

module.exports = function (iface) {
    const {mqttPub, mqttSub, mqttStatus, log, Service, Characteristic} = iface;

    /*
     // Required Characteristics
     this.addCharacteristic(Characteristic.BatteryLevel);
     this.addCharacteristic(Characteristic.ChargingState);
     this.addCharacteristic(Characteristic.StatusLowBattery);

     // Optional Characteristics
     this.addOptionalCharacteristic(Characteristic.Name);

     // The value property of StatusLowBattery must be one of the following:
     Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL = 0;
     Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW = 1;

     // The value property of ChargingState must be one of the following:
     Characteristic.ChargingState.NOT_CHARGING = 0;
     Characteristic.ChargingState.CHARGING = 1;
     Characteristic.ChargingState.NOT_CHARGEABLE = 2;
     */

    return function createService_BatteryService(acc, settings) {
        acc.addService(Service.BatteryService);
        /*
            .getCharacteristic(Characteristic.BatteryLevel)
            .on('get', callback => {
                log.debug('< hap get', settings.name, 'BatteryLevel');
                const level = mqttStatus[settings.topic.statusBatteryLevel];
                log.debug('> hap re_get', settings.name, 'BatteryLevel', level);
                callback(null, level);
            });
            */

        if (settings.topic.statusBatteryLevel) {
            mqttSub(settings.topic.statusBatteryLevel, val => {
                if (settings.config && (typeof settings.payload.maxBatteryLevel !== 'undefined')) {
                    const max = settings.payload.maxBatteryLevel;
                    const min = settings.payload.minBatteryLevel || 0;
                    const range = max - min;
                    val = ((val - min) / range) * 100;
                }
                log.debug('> hap update', settings.name, 'BatteryLevel', val);
                acc.getService(Service.BatteryService)
                    .updateCharacteristic(Characteristic.BatteryLevel, val);
            });
        }

        if (settings.topic.statusChargingState) {
            mqttSub(settings.topic.statusChargingState, val => {
                log.debug('> hap update', settings.name, 'ChargingState', val);
                acc.getService(Service.BatteryService)
                    .updateCharacteristic(Characteristic.ChargingState, val);
            });
        }

        if (settings.topic.statusLowBattery) {
            mqttSub(settings.topic.statusLowBattery, val => {
                val = (val === settings.payload.onLowBattery) ? 1 : 0;
                log.debug('> hap update', settings.name, 'StatusLowBattery', val);
                acc.getService(Service.BatteryService)
                    .updateCharacteristic(Characteristic.StatusLowBattery, val);
            });
        }
    };
};
<|endoftext|>