<commit_before>var Q = require('q'),
    QFS = require('q-fs'),
    INHERIT = require('inherit'),
    CP = require('child_process'),
    PATH = require('path'),
    URL = require('url'),
    UTIL = require('util'),

    Node = require('./node').Node,

    SCM_VALIDITY_TIMEOUT = 60000; // 60 secs

var LibraryNode = exports.LibraryNode = INHERIT(Node, /** @lends LibraryNode.prototype */ {

    /**
     * LibraryNode instance constructor.
     *
     * @class LibraryNode
     * @constructs
     * @param {Object} o  Node options.
     * @param {String} o.root    Project root path.
     * @param {String} o.target  Library path.
     */
    __constructor: function(o) {
        this.__base(o);
        this.root = o.root;
        this.target = o.target;
    },

    /**
     * Get absolute path to library.
     *
     * @return {String}
     */
    getPath: function() {
        return PATH.resolve(this.root, this.target);
    }

}, {

    createId: function(o) {
        return o.target;
    }

});

exports.SymlinkLibraryNode = INHERIT(LibraryNode, /** @lends SymlinkLibraryNode.prototype */ {

    /**
     * SymlinkLibraryNode instance constructor.
     *
     * @class SymlinkLibraryNode
     * @constructs
     * @param {Object} o  Node options.
     * @param {String} o.root      Project root path.
     * @param {String} o.target    Library path.
     * @param {String} o.relative  Symlink path.
     */
    __constructor: function(o) {
        this.__base(o);
        this.relative = o.relative;
    },

    /**
     * Check validity of node.
     *
     * @return {Boolean}
     */
    isValid: function() {
        return false;
    },

    /**
     * Make node.
     *
     * @return {Promise * Undefined}
     */
    make: function() {

        var _this = this;
        return QFS.statLink(this.getPath())
            .fail(function() {
                return false;
            })
            .then(function(stat) {

                if (!stat) return;

                if (!stat.isSymbolicLink()) {
                    return Q.reject(UTIL.format("SymlinkLibraryNode: Path '%s' is exists and is not a symbolic link",
                        _this.getPath()));
                }

                return QFS.remove(_this.getPath());

            })
            .then(function() {
                return QFS.symbolicLink(_this.getPath(), _this.relative);
            });

    }

});

var ScmLibraryNode = exports.ScmLibraryNode = INHERIT(LibraryNode, /** @lends ScmLibraryNode.prototype */ {

    /**
     * ScmLibraryNode instance constructor.
     *
     * @class ScmLibraryNode
     * @constructs
     * @param {Object} o  Node options.
     * @param {String} o.root      Project root path.
     * @param {String} o.target    Library path.
     * @param {String} o.url       Repository URL.
     * @param {String[]} [o.paths=['']]  Paths to checkout.
     */
    __constructor: function(o) {
        this.__base(o);
        this.url = o.url;
        this.paths = [''];
        this.timeout = typeof o.timeout !== 'undefined'? Number(o.timeout) : SCM_VALIDITY_TIMEOUT;
    },

    /**
     * Check validity of node.
     *
     * @return {Boolean}
     */
    isValid: function() {
        return this.lastRunTime && this.timeout && (Date.now() - this.lastRunTime <= this.timeout);
    },

    /**
     * Stub for getInitialCheckoutCmd(), throws.
     *
     * @param {String} url  Repository url.
     * @param {String} target  Repository checkout path.
     * @throws {Error}
     */
    getInitialCheckoutCmd: function(url, target) {
        throw new Error('getInitialCheckoutCmd() not implemented!');
    },

    /**
     * Stub for getUpdateCmd(), throws.
     *
     * @param {String} url  Repository url.
     * @param {String} target  Repository checkout path.
     * @throws {Error}
     */
    getUpdateCmd: function(url, target) {
        throw new Error('getInitialCheckoutCmd() not implemented!');
    },

    /**
     * Checkput or update single repository path.
     *
     * @param {String} path  Repository path to checkout / update.
     * @return {Promise * Undefined}
     */
    updatePath: function(path) {

        var _this = this,
            target = PATH.resolve(this.root, this.target, path),
            repo = joinUrlPath(this.url, path);

        return QFS.exists(target)
            .then(function(exists) {

                var cmd = exists?
                        _this.getUpdateCmd(repo, target) :
                        _this.getInitialCheckoutCmd(repo, target),
                    d = Q.defer();

                _this.log(cmd);

                CP.exec(cmd, function(err, stdout, stderr) {
                    stdout && _this.log(stdout);
                    stderr && _this.log(stderr);

                    if (err) return d.reject(err);

                    _this.lastRunTime = Date.now();
                    d.resolve();
                });

                return d.promise;

            });

    },

    /**
     * Make node.
     *
     * @return {Promise * Undefined}
     */
    make: function() {

        return Q.all(this.paths.map(function(path) {
            return this.updatePath(path);
        }, this));

    }

});

exports.GitLibraryNode = INHERIT(ScmLibraryNode, /** @lends GitLibraryNode.prototype */ {

    /**
     * GitLibraryNode instance constructor.
     *
     * @class GitLibraryNode
     * @constructs
     * @param {Object} o  Node options.
     * @param {String} o.root      Project root path.
     * @param {String} o.target    Library path.
     * @param {String} o.url       Repository URL.
     * @param {String[]} [o.paths=['']]  Paths to checkout.
     * @param {String} [o.treeish='master']  Treeish to checkout.
     */
    __constructor: function(o) {
        this.__base(o);
        this.treeish = o.treeish || 'master';
    },

    getInitialCheckoutCmd: function(url, target) {
        return UTIL.format('git clone --progress %s %s && cd %s && git checkout %s', url, target, target, this.treeish);
    },

    getUpdateCmd: function(url, target) {
        return UTIL.format('cd %s && git checkout HEAD~ && git branch -D %s ; git fetch origin && git checkout --track -b %s origin/%s', target, this.treeish, this.treeish, this.treeish);
    }

});

exports.SvnLibraryNode = INHERIT(LibraryNode, /** @lends SvnLibraryNode.prototype */ {

    /**
     * SvnLibraryNode instance constructor.
     *
     * @class SvnLibraryNode
     * @constructs
     * @param {Object} o  Node options.
     * @param {String} o.root      Project root path.
     * @param {String} o.target    Library path.
     * @param {String} o.url       Repository URL.
     * @param {String[]} [o.paths=['']]  Paths to checkout.
     * @param {String} [o.revision='HEAD']  Revision to checkout.
     */
    __constructor: function(o) {
        this.__base(o);
        this.paths = Array.isArray(o.paths)? o.paths : [o.paths || ''];
        this.revision = o.revision || 'HEAD';
    },

    getInitialCheckoutCmd: function(url, target) {
        return UTIL.format('svn co -q -r %s %s %s', this.revision, url, target);
    },

    getUpdateCmd: function(url, target) {
        return UTIL.format('svn up -q -r %s %s', this.revision, target);
    }

});

function joinUrlPath(url, part) {
    var p = URL.parse(url);
    p.pathname = PATH.join(p.pathname, part);
    return URL.format(p);
}
<commit_msg>SvnLibraryNode should inherit ScmLibraryNode<commit_after>var Q = require('q'),
    QFS = require('q-fs'),
    INHERIT = require('inherit'),
    CP = require('child_process'),
    PATH = require('path'),
    URL = require('url'),
    UTIL = require('util'),

    Node = require('./node').Node,

    SCM_VALIDITY_TIMEOUT = 60000; // 60 secs

var LibraryNode = exports.LibraryNode = INHERIT(Node, /** @lends LibraryNode.prototype */ {

    /**
     * LibraryNode instance constructor.
     *
     * @class LibraryNode
     * @constructs
     * @param {Object} o  Node options.
     * @param {String} o.root    Project root path.
     * @param {String} o.target  Library path.
     */
    __constructor: function(o) {
        this.__base(o);
        this.root = o.root;
        this.target = o.target;
    },

    /**
     * Get absolute path to library.
     *
     * @return {String}
     */
    getPath: function() {
        return PATH.resolve(this.root, this.target);
    }

}, {

    createId: function(o) {
        return o.target;
    }

});

exports.SymlinkLibraryNode = INHERIT(LibraryNode, /** @lends SymlinkLibraryNode.prototype */ {

    /**
     * SymlinkLibraryNode instance constructor.
     *
     * @class SymlinkLibraryNode
     * @constructs
     * @param {Object} o  Node options.
     * @param {String} o.root      Project root path.
     * @param {String} o.target    Library path.
     * @param {String} o.relative  Symlink path.
     */
    __constructor: function(o) {
        this.__base(o);
        this.relative = o.relative;
    },

    /**
     * Check validity of node.
     *
     * @return {Boolean}
     */
    isValid: function() {
        return false;
    },

    /**
     * Make node.
     *
     * @return {Promise * Undefined}
     */
    make: function() {

        var _this = this;
        return QFS.statLink(this.getPath())
            .fail(function() {
                return false;
            })
            .then(function(stat) {

                if (!stat) return;

                if (!stat.isSymbolicLink()) {
                    return Q.reject(UTIL.format("SymlinkLibraryNode: Path '%s' is exists and is not a symbolic link",
                        _this.getPath()));
                }

                return QFS.remove(_this.getPath());

            })
            .then(function() {
                return QFS.symbolicLink(_this.getPath(), _this.relative);
            });

    }

});

var ScmLibraryNode = exports.ScmLibraryNode = INHERIT(LibraryNode, /** @lends ScmLibraryNode.prototype */ {

    /**
     * ScmLibraryNode instance constructor.
     *
     * @class ScmLibraryNode
     * @constructs
     * @param {Object} o  Node options.
     * @param {String} o.root      Project root path.
     * @param {String} o.target    Library path.
     * @param {String} o.url       Repository URL.
     * @param {String[]} [o.paths=['']]  Paths to checkout.
     */
    __constructor: function(o) {
        this.__base(o);
        this.url = o.url;
        this.paths = [''];
        this.timeout = typeof o.timeout !== 'undefined'? Number(o.timeout) : SCM_VALIDITY_TIMEOUT;
    },

    /**
     * Check validity of node.
     *
     * @return {Boolean}
     */
    isValid: function() {
        return this.lastRunTime && this.timeout && (Date.now() - this.lastRunTime <= this.timeout);
    },

    /**
     * Stub for getInitialCheckoutCmd(), throws.
     *
     * @param {String} url  Repository url.
     * @param {String} target  Repository checkout path.
     * @throws {Error}
     */
    getInitialCheckoutCmd: function(url, target) {
        throw new Error('getInitialCheckoutCmd() not implemented!');
    },

    /**
     * Stub for getUpdateCmd(), throws.
     *
     * @param {String} url  Repository url.
     * @param {String} target  Repository checkout path.
     * @throws {Error}
     */
    getUpdateCmd: function(url, target) {
        throw new Error('getInitialCheckoutCmd() not implemented!');
    },

    /**
     * Checkput or update single repository path.
     *
     * @param {String} path  Repository path to checkout / update.
     * @return {Promise * Undefined}
     */
    updatePath: function(path) {

        var _this = this,
            target = PATH.resolve(this.root, this.target, path),
            repo = joinUrlPath(this.url, path);

        return QFS.exists(target)
            .then(function(exists) {

                var cmd = exists?
                        _this.getUpdateCmd(repo, target) :
                        _this.getInitialCheckoutCmd(repo, target),
                    d = Q.defer();

                _this.log(cmd);

                CP.exec(cmd, function(err, stdout, stderr) {
                    stdout && _this.log(stdout);
                    stderr && _this.log(stderr);

                    if (err) return d.reject(err);

                    _this.lastRunTime = Date.now();
                    d.resolve();
                });

                return d.promise;

            });

    },

    /**
     * Make node.
     *
     * @return {Promise * Undefined}
     */
    make: function() {

        return Q.all(this.paths.map(function(path) {
            return this.updatePath(path);
        }, this));

    }

});

exports.GitLibraryNode = INHERIT(ScmLibraryNode, /** @lends GitLibraryNode.prototype */ {

    /**
     * GitLibraryNode instance constructor.
     *
     * @class GitLibraryNode
     * @constructs
     * @param {Object} o  Node options.
     * @param {String} o.root      Project root path.
     * @param {String} o.target    Library path.
     * @param {String} o.url       Repository URL.
     * @param {String[]} [o.paths=['']]  Paths to checkout.
     * @param {String} [o.treeish='master']  Treeish to checkout.
     */
    __constructor: function(o) {
        this.__base(o);
        this.treeish = o.treeish || 'master';
    },

    getInitialCheckoutCmd: function(url, target) {
        return UTIL.format('git clone --progress %s %s && cd %s && git checkout %s', url, target, target, this.treeish);
    },

    getUpdateCmd: function(url, target) {
        return UTIL.format('cd %s && git checkout HEAD~ && git branch -D %s ; git fetch origin && git checkout --track -b %s origin/%s', target, this.treeish, this.treeish, this.treeish);
    }

});

exports.SvnLibraryNode = INHERIT(ScmLibraryNode, /** @lends SvnLibraryNode.prototype */ {

    /**
     * SvnLibraryNode instance constructor.
     *
     * @class SvnLibraryNode
     * @constructs
     * @param {Object} o  Node options.
     * @param {String} o.root      Project root path.
     * @param {String} o.target    Library path.
     * @param {String} o.url       Repository URL.
     * @param {String[]} [o.paths=['']]  Paths to checkout.
     * @param {String} [o.revision='HEAD']  Revision to checkout.
     */
    __constructor: function(o) {
        this.__base(o);
        this.paths = Array.isArray(o.paths)? o.paths : [o.paths || ''];
        this.revision = o.revision || 'HEAD';
    },

    getInitialCheckoutCmd: function(url, target) {
        return UTIL.format('svn co -q -r %s %s %s', this.revision, url, target);
    },

    getUpdateCmd: function(url, target) {
        return UTIL.format('svn up -q -r %s %s', this.revision, target);
    }

});

function joinUrlPath(url, part) {
    var p = URL.parse(url);
    p.pathname = PATH.join(p.pathname, part);
    return URL.format(p);
}
<|endoftext|>


<commit_before>var Conversation = function(speciesList) {
	this.lastAnswer = null;
	this.lastAction = Date.now();
	this.firstmessage = true;
	this.inFindingProcess = false;

	this.speciesCommonNames = speciesList.map((obj)=>obj.triname);
	this.speciesSientificNames = speciesList.map((obj)=>obj.sciname);

	this.location = null;
	this.speciesName = null;

	this.isActive = function(){
			let diff = this.lastAction - Date.now();
			let fiveMinInMs = 1000 * 60 * 5;
			return diff <= fiveMinInMs;

	};
	this.processMessage = function(message) {
		console.log("Input> " + message);
    this.lastAction = Date.now();
		var splitedMessage = message.split(/[ ,]+/);

		if(this.firstmessage || match(splitedMessage,["hey", "moin", "hallo", "hi", "servus"])) {
			this.firstmessage = false;
			var startText = 'Hey du, ich bin BioDiv und kann weiterhelfen, wenn du seltene Muscheln / Säugetiere oder Fische in deiner Umgebung gesichtet hast. ';

			var answerOptions = ["Hilfe", "Fund melden"];

			return { answer: startText, answerOptions: answerOptions };
		}
		let yes = ["ja", "ok", "jo", "jup"];
		let no = ["nein", "nö", "ne", "auf gar keinen fall", "halt die fresse"];

    if(match(splitedMessage, yes.concat(no))) {
			var userAnswer = message;
			var answerOptions = [];

			this.lastAnswer = null;
			if(match(splitedMessage, yes)) {
				var jaText = "Ich halte Dich auf dem Laufenden. 👍";
				return { answer: jaText, answerOptions: answerOptions };
			} else {
				var neinText = "Ok, frag' einfach, wenn du wissen willst, wie der Status ist. 😁 Ich bin bis auf weiteres stumm. 🙈🙊🙉";
				return { answer: neinText, answerOptions: answerOptions };
			}

		}

		if(match(splitedMessage, ["Hilfe", "Fund Melden"])) {
			var answerOptions = [];

			var helpText = 'ℹ Alles klar du, dann lass uns loslegen und deinen Fund zusammen aufnehmen! Was für eine Spezies hast du denn gesehen?';

      this.inFindingProcess = true;

			return { answer: helpText, answerOptions: answerOptions };
		}

		if(this.inFindingProcess){

    	console.log(splitedMessage);
    	console.log(this.speciesCommonNames);
    	console.log(this.speciesSientificNames);
    	if(match(splitedMessage,this.speciesCommonNames) || match(splitedMessage,this.speciesSientificNames)){

        return {
        	answer: "Sehr schön, hab ich verstanden du hast " + splitedMessage + " bei dir gesehen. " +
					"\n Es wäre super wenn du mir noch deinen Standort zeigen könntest?",
					locationRequest: true
        };

			}

    	else if(this.speciesName == null){

        console.log("Choose species text ", this.speciesCommonNames)
        return {
          answer: "Leider habe ich dich nicht so recht verstanden, hier einige Vorschläge was für Spezies ich so im Angebot hätte",
          answerOptions: this.speciesCommonNames
        }

			}

		}

		return {
      answer: "Ich konnte dich leider nicht verstehen... 😰",
      answerOptions: ["Hilfe"]
    }

	};

	return this;
};

function match(splitedMessage, keyWords) {

	for(var word in splitedMessage) {
		for(var keyWord in keyWords) {
			var lowerCaseWord = splitedMessage[word].toLowerCase();
			var lowerCaseKeyword = keyWords[keyWord].toLowerCase();

			if(lowerCaseWord == lowerCaseKeyword) {
				return true;
			}
		}
	}

	return false;
}

module.exports = Conversation;
<commit_msg>fix bug with match<commit_after>var Conversation = function(speciesList) {
	this.lastAnswer = null;
	this.lastAction = Date.now();
	this.firstmessage = true;
	this.inFindingProcess = false;

	this.speciesCommonNames = speciesList.map((obj)=>obj.triname);
	this.speciesSientificNames = speciesList.map((obj)=>obj.sciname);

	this.location = null;
	this.speciesName = null;

	this.isActive = function(){
			let diff = this.lastAction - Date.now();
			let fiveMinInMs = 1000 * 60 * 5;
			return diff <= fiveMinInMs;

	};
	this.processMessage = function(message) {
		console.log("Input> " + message);
    this.lastAction = Date.now();
		var splitedMessage = message.split(/[ ,]+/);

		if(this.firstmessage || match(splitedMessage,["hey", "moin", "hallo", "hi", "servus"])) {
			this.firstmessage = false;
			var startText = 'Hey du, ich bin BioDiv und kann weiterhelfen, wenn du seltene Muscheln / Säugetiere oder Fische in deiner Umgebung gesichtet hast. ';

			var answerOptions = ["Hilfe", "Fund melden"];

			return { answer: startText, answerOptions: answerOptions };
		}
		let yes = ["ja", "ok", "jo", "jup"];
		let no = ["nein", "nö", "ne", "auf gar keinen fall", "halt die fresse"];

    if(match(splitedMessage, yes.concat(no))) {
			var userAnswer = message;
			var answerOptions = [];

			this.lastAnswer = null;
			if(match(splitedMessage, yes)) {
				var jaText = "Ich halte Dich auf dem Laufenden. 👍";
				return { answer: jaText, answerOptions: answerOptions };
			} else {
				var neinText = "Ok, frag' einfach, wenn du wissen willst, wie der Status ist. 😁 Ich bin bis auf weiteres stumm. 🙈🙊🙉";
				return { answer: neinText, answerOptions: answerOptions };
			}

		}

		if(match(splitedMessage, ["Hilfe", "Fund Melden"])) {
			var answerOptions = [];

			var helpText = 'ℹ Alles klar du, dann lass uns loslegen und deinen Fund zusammen aufnehmen! Was für eine Spezies hast du denn gesehen?';

      this.inFindingProcess = true;

			return { answer: helpText, answerOptions: answerOptions };
		}

		if(this.inFindingProcess){

    	console.log(splitedMessage);
    	console.log(this.speciesCommonNames);
    	console.log(this.speciesSientificNames);
    	if(match([message],this.speciesCommonNames) || match([message],this.speciesSientificNames)){

        return {
        	answer: "Sehr schön, hab ich verstanden du hast " + splitedMessage + " bei dir gesehen. " +
					"\n Es wäre super wenn du mir noch deinen Standort zeigen könntest?",
					locationRequest: true
        };

			}

    	else if(this.speciesName == null){

        console.log("Choose species text ", this.speciesCommonNames)
        return {
          answer: "Leider habe ich dich nicht so recht verstanden, hier einige Vorschläge was für Spezies ich so im Angebot hätte",
          answerOptions: this.speciesCommonNames
        }

			}

		}

		return {
      answer: "Ich konnte dich leider nicht verstehen... 😰",
      answerOptions: ["Hilfe"]
    }

	};

	return this;
};

function match(splitedMessage, keyWords) {

	for(var word in splitedMessage) {
		for(var keyWord in keyWords) {
			var lowerCaseWord = splitedMessage[word].toLowerCase();
			var lowerCaseKeyword = keyWords[keyWord].toLowerCase();

			if(lowerCaseWord == lowerCaseKeyword) {
				return true;
			}
		}
	}

	return false;
}

module.exports = Conversation;
<|endoftext|>


<commit_before>/*
 * L.Browser handles different browser and feature detections for internal Leaflet use.
 */

(function () {

	var ie = !!window.ActiveXObject,
	    ie6 = ie && !window.XMLHttpRequest,
	    ie7 = ie && !document.querySelector,
		ielt9 = ie && !document.addEventListener,

	    // terrible browser detection to work around Safari / iOS / Android browser bugs
	    ua = navigator.userAgent.toLowerCase(),
	    webkit = ua.indexOf('webkit') !== -1,
	    chrome = ua.indexOf('chrome') !== -1,
	    android = ua.indexOf('android') !== -1,
	    android23 = ua.search('android [23]') !== -1,

	    mobile = typeof orientation !== undefined + '',
	    msTouch = window.navigator && window.navigator.msPointerEnabled &&
	              window.navigator.msMaxTouchPoints,
	    retina = ('devicePixelRatio' in window && window.devicePixelRatio > 1) ||
	             ('matchMedia' in window && window.matchMedia('(min-resolution:144dpi)') &&
	              window.matchMedia('(min-resolution:144dpi)').matches),

	    doc = document.documentElement,
	    ie3d = ie && ('transition' in doc.style),
	    webkit3d = ('WebKitCSSMatrix' in window) && ('m11' in new window.WebKitCSSMatrix()),
	    gecko3d = 'MozPerspective' in doc.style,
	    opera3d = 'OTransition' in doc.style,
	    any3d = !window.L_DISABLE_3D && (ie3d || webkit3d || gecko3d || opera3d);

	var touch = !window.L_NO_TOUCH && (function () {

		var startName = 'ontouchstart';

		// IE10+ (We simulate these into touch* events in L.DomEvent and L.DomEvent.MsTouch) or WebKit, etc.
		if (msTouch || (startName in doc)) {
			return true;
		}

		// Firefox/Gecko
		var div = document.createElement('div'),
		    supported = false;

		if (!div.setAttribute) {
			return false;
		}
		div.setAttribute(startName, 'return;');

		if (typeof div[startName] === 'function') {
			supported = true;
		}

		div.removeAttribute(startName);
		div = null;

		return supported;
	}());

	L.Browser = {
		ie: ie,
		ie6: ie6,
		ie7: ie7,
		ielt9: ielt9,
		webkit: webkit,

		android: android,
		android23: android23,

		chrome: chrome,

		ie3d: ie3d,
		webkit3d: webkit3d,
		gecko3d: gecko3d,
		opera3d: opera3d,
		any3d: any3d,

		mobile: mobile,
		mobileWebkit: mobile && webkit,
		mobileWebkit3d: mobile && webkit3d,
		mobileOpera: mobile && window.opera,

		touch: touch,
		msTouch: msTouch,

		retina: retina
	};

}());
<commit_msg>Disable 3D CSS transforms on PhantomJS<commit_after>/*
 * L.Browser handles different browser and feature detections for internal Leaflet use.
 */

(function () {

	var ie = !!window.ActiveXObject,
	    ie6 = ie && !window.XMLHttpRequest,
	    ie7 = ie && !document.querySelector,
		ielt9 = ie && !document.addEventListener,

	    // terrible browser detection to work around Safari / iOS / Android browser bugs
	    ua = navigator.userAgent.toLowerCase(),
	    webkit = ua.indexOf('webkit') !== -1,
	    chrome = ua.indexOf('chrome') !== -1,
	    phantomjs = ua.indexOf('phantom') !== -1,
	    android = ua.indexOf('android') !== -1,
	    android23 = ua.search('android [23]') !== -1,

	    mobile = typeof orientation !== undefined + '',
	    msTouch = window.navigator && window.navigator.msPointerEnabled &&
	              window.navigator.msMaxTouchPoints,
	    retina = ('devicePixelRatio' in window && window.devicePixelRatio > 1) ||
	             ('matchMedia' in window && window.matchMedia('(min-resolution:144dpi)') &&
	              window.matchMedia('(min-resolution:144dpi)').matches),

	    doc = document.documentElement,
	    ie3d = ie && ('transition' in doc.style),
	    webkit3d = ('WebKitCSSMatrix' in window) && ('m11' in new window.WebKitCSSMatrix()),
	    gecko3d = 'MozPerspective' in doc.style,
	    opera3d = 'OTransition' in doc.style,
	    any3d = !window.L_DISABLE_3D && (ie3d || webkit3d || gecko3d || opera3d) && !phantomjs;

	var touch = !window.L_NO_TOUCH && (function () {

		var startName = 'ontouchstart';

		// IE10+ (We simulate these into touch* events in L.DomEvent and L.DomEvent.MsTouch) or WebKit, etc.
		if (msTouch || (startName in doc)) {
			return true;
		}

		// Firefox/Gecko
		var div = document.createElement('div'),
		    supported = false;

		if (!div.setAttribute) {
			return false;
		}
		div.setAttribute(startName, 'return;');

		if (typeof div[startName] === 'function') {
			supported = true;
		}

		div.removeAttribute(startName);
		div = null;

		return supported;
	}());

	L.Browser = {
		ie: ie,
		ie6: ie6,
		ie7: ie7,
		ielt9: ielt9,
		webkit: webkit,

		android: android,
		android23: android23,

		chrome: chrome,

		ie3d: ie3d,
		webkit3d: webkit3d,
		gecko3d: gecko3d,
		opera3d: opera3d,
		any3d: any3d,

		mobile: mobile,
		mobileWebkit: mobile && webkit,
		mobileWebkit3d: mobile && webkit3d,
		mobileOpera: mobile && window.opera,

		touch: touch,
		msTouch: msTouch,

		retina: retina
	};

}());
<|endoftext|>


<commit_before>/*jshint laxcomma:true, smarttabs: true, node:true */
'use strict';
/**
 * @module tastypie/lib/paginator
 * @author Eric Satterwhite
 * @requires util
 * @requires module:class
 * @requires module:class/options
 * @requires module:class/parent
 * @requires mout/lang/kindOf
 * @since 0.1.0
 * @requires xml2js
 * @requires util
 * @requires url
 * @requires events
 * @requires debug
 * @requires mout/lang/isNumber
 * @requires mout/lang/clone
 * @requires tastypie/lib/class
 * @requires tastypie/lib/class/options
 * @requires tastypie/lib/exceptions
 **/

var url        = require( 'url' )                  // url
	, Boom       = require('boom')
	, events     = require( 'events' )             // events
	, isNumber   = require( 'mout/lang/isNumber' ) // isNumber
	, clone      = require( 'mout/lang/clone' )    // clone
	, Class      = require( './class' )            // Class
	, Options    = require( './class/options' )    // Options
	, Parent     = require( './class/parent' )     // Parent function
	, Paginator
	;

/**
 * Used to generate pages of array data. Also responsible for creating Meta data packets for api responses
 * @constructor
 * @alias module:tastypie/lib/paginator
 * @param {Object} options
 * @param {Object[]} [options.object=[]] The data to page
 * @param {?Number} [options.limit=null] The maximum number of object to include in a page
 * @param {Number} [options.offset=0] The number of object to skip
 * @param {Request} options.req A hapi.js request object
 * @param {Reply} options.res A hapi.js reply object
 * @example var Paginator = require('tastypie/lib/paginator')
paginator = new Paginator({
	limit: bundle.req.query.limit || 25
, req: bundle.req
, res: bundle.res
, collectionName: 'data'
, objects: []
});

to_be_serialize = paginator.page();
 */
module.exports =
Paginator = new Class({
		inherits:events.EventEmitter
	, mixin:[ Parent, Options ]
	, options:{
		objects:[]
	  , limit:25
	  , max:1000
	  , offset:0
	  , req:null
	  , res:null
	  , collectionName: 'objects'
	}
	, constructor: function( options ){
		this.setOptions( options );
	}

	/**
	 * Generates a page of a data set
	 * @method module:tastypie/lib/paginator#page
	 * @return {Object} page An array sliced from the original data set using offset & limit parameters
	 **/
	, page: function page(){
			var limit = this.limit();
			var offset = this.offset();
			var count = this.count();
			var ret = {
				meta:{
					count:count
				, limit: limit
				, offset: offset
				}
			};

			if( limit  && limit < this.options.objects.length ){
				ret.meta.previous = this.previous( limit, offset, count );
				ret.meta.next = this.next( limit, offset, count );
			}

			ret[ this.options.collectionName ] = this.slice( limit, offset );
			// dereference the request and respons
			this.setOptions({ req:null, res:null });
			return ret;
	}

	/**
	 * Returns  the uri for the next page if their is one
	 * @method module:tastypie/lib/paginator#next
	 * @param {Number} limit the number of items in the page
	 * @param {Number} offset where in the data set to derive the page from
	 * @param {Number} count the length of the current data set
	 * @return {String} url the URI that can be used to retrieve the next page
	 **/
	, next: function next( limit, offset, count ){
		var value = limit + offset;

		if( value > count - 1 ){
			return null;
		}

		return this.uri(limit, value);
	}

	/**
	 * determines the offset for the current data set using options, or pased in request
	 * @method module:tastypie/lib/paginator#offset
	 * @return {Number} offset THe resulting offset parameter
	 **/
	, offset: function offset( ){
			var oset = this.options.offset;
			var query = this.options.req.query || {};

			if( query.offset != null ){
				oset = parseInt( query.offset, 10 );
			}

			if( !isNumber( oset ) || oset<0 ){
				var e = new Boom.badRequest("bad offset param: " + oset );
				e.req = this.options.req;
				e.res = this.options.res;
				return this.emit('error', e);
			}

			return oset;
	}

	/**
	 * Returns  the uri for the previous page if their is one
	 * @method module:tastypie/lib/paginator#previous
	 * @param {Number} limit the number of items in the page
	 * @param {Number} offset where in the data set to derive the page from
	 * @return {String} the URI that can be used to retrieve the previous page
	 **/
	, previous: function previous( limit, offset ){

		var value = offset - limit;
		if( value < 0 ){
			return null;
		}

		return this.uri( limit, value );
	}

	/**
	 * returns the number of objects in the current data set
	 * @method module:tastypie/lib/paginator#count
	 * @return {Number}
	 **/
	, count: function count(){
		return this.options.count;
	}

	/**
	 * retuns a slice from the current data set to represent a page
	 * @method module:tastypie/lib/paginator#slice
	 * @param {Number} limit The maximum number of items to include in the slice
	 * @param {Number} offset The starting position in the data set at which to start the slice
	 * @return {Array}
	 **/
	,slice: function slice( limit, offset ){
		if( limit <=0 ){
			return this.options.objects.slice( offset, this.options.objects.length );
		}

		return this.options.objects.slice( offset, ( offset ) + limit );
	}

	/**
	 * returns the number of items that should be included in the data set.
	 * Checks req.query for limit or a configured limit option
	 * @method module:tastypie/lib/paginator#limit
	 * @return {Number}
	 **/
	, limit: function limit(){
		var query = (this.options.req || {}).query || {}
		  , max   = this.options.max || -1
		  , limit = this.options.limit
		  , lmt
		  ;

		lmt = query.limit ? parseInt( query.limit, 10) : query.limit;
		lmt = isNumber( lmt ) ? lmt ? lmt : max : limit ? limit : 25;
		lmt = Math.min( lmt, max );
		if(!isNumber( lmt ) ){
			this.emit(
				'error'
				, new Boom.badRequest('limit must be a number')
				, this.options.req
				, this.options.res
			);
		}
		return lmt;
	}

	/**
	 * generates a URI that will return page of data
	 * @method module:tastypie/lib/paginator#uri
	 * @param {Number} limit The maximum number of items to include in the slice
	 * @param {Number} offset The starting position in the data set at which to start the slice
	 * @return {String} a formatted uri
	 **/
	, uri: function uri( limit, offset ){
		var values = clone(this.options.req.query || {});

		values.limit = limit;
		values.offset = offset;
		return url.format({
			 pathname:this.options.req.path
			 ,query: values
		});
	}
});

/**
 * Assumes paging is done at the data store level. Slice method returns the objects array untouched
 * @class module:tastypie/lib/paginator.Remote
 * @extends module:tastypie/lib/paginator
 * @param {Object} options
 * @param {Object[]} [options.object=[]] The data to page
 * @param {?Number} [options.limit=null] The maximum number of object to include in a page
 * @param {Number} [options.offset=0] The number of object to skip
 * @param {Request} options.req A hapi.js request object
 * @param {Reply} options.res A hapi.js reply object
 * @example var Paginator = require('tastypie/lib/paginator')
paginator = new Paginator.Remote({
	limit: bundle.req.query.limit || 25
, req: bundle.req
, res: bundle.res
, collectionName: 'data'
, objects: []
});

to_be_serialize = paginator.page();
 */
module.exports.Remote = new Class({
	inherits: Paginator
	,sort: function( ){
		return this.options.objects;
	}
	, slice: function( ){
		return this.options.objects;
	}
	/**
	 * Generates a page of a data set
	 * @method module:tastypie/lib/paginator.REMOTE#page
	 * @return {Object} page An array sliced from the original data set using offset & limit parameters
	 **/
	, page: function page(){
			var limit = this.limit()
			  , offset = this.offset()
			  , count = this.count()
			  , ret = {
					meta:{
						count:count
					  , limit: limit
					  , offset: offset
					}
			};

			if( limit  && limit < count ){
				ret.meta.previous = this.previous( limit, offset, count );
				ret.meta.next = this.next( limit, offset, count );
			}

			ret[ this.options.collectionName ] = this.slice( limit, offset );
			// dereference the request and respons
			this.setOptions({ req:null, res:null });
			return ret;
	}
});

<commit_msg>remove the new kew work from boom errors<commit_after>/*jshint laxcomma:true, smarttabs: true, node:true */
'use strict';
/**
 * @module tastypie/lib/paginator
 * @author Eric Satterwhite
 * @requires util
 * @requires module:class
 * @requires module:class/options
 * @requires module:class/parent
 * @requires mout/lang/kindOf
 * @since 0.1.0
 * @requires xml2js
 * @requires util
 * @requires url
 * @requires events
 * @requires debug
 * @requires mout/lang/isNumber
 * @requires mout/lang/clone
 * @requires tastypie/lib/class
 * @requires tastypie/lib/class/options
 * @requires tastypie/lib/exceptions
 **/

var url        = require( 'url' )                  // url
	, Boom       = require('boom')
	, events     = require( 'events' )             // events
	, isNumber   = require( 'mout/lang/isNumber' ) // isNumber
	, clone      = require( 'mout/lang/clone' )    // clone
	, Class      = require( './class' )            // Class
	, Options    = require( './class/options' )    // Options
	, Parent     = require( './class/parent' )     // Parent function
	, Paginator
	;

/**
 * Used to generate pages of array data. Also responsible for creating Meta data packets for api responses
 * @constructor
 * @alias module:tastypie/lib/paginator
 * @param {Object} options
 * @param {Object[]} [options.object=[]] The data to page
 * @param {?Number} [options.limit=null] The maximum number of object to include in a page
 * @param {Number} [options.offset=0] The number of object to skip
 * @param {Request} options.req A hapi.js request object
 * @param {Reply} options.res A hapi.js reply object
 * @example var Paginator = require('tastypie/lib/paginator')
paginator = new Paginator({
	limit: bundle.req.query.limit || 25
, req: bundle.req
, res: bundle.res
, collectionName: 'data'
, objects: []
});

to_be_serialize = paginator.page();
 */
module.exports =
Paginator = new Class({
		inherits:events.EventEmitter
	, mixin:[ Parent, Options ]
	, options:{
		objects:[]
	  , limit:25
	  , max:1000
	  , offset:0
	  , req:null
	  , res:null
	  , collectionName: 'objects'
	}
	, constructor: function( options ){
		this.setOptions( options );
	}

	/**
	 * Generates a page of a data set
	 * @method module:tastypie/lib/paginator#page
	 * @return {Object} page An array sliced from the original data set using offset & limit parameters
	 **/
	, page: function page(){
			var limit = this.limit();
			var offset = this.offset();
			var count = this.count();
			var ret = {
				meta:{
					count:count
				, limit: limit
				, offset: offset
				}
			};

			if( limit  && limit < this.options.objects.length ){
				ret.meta.previous = this.previous( limit, offset, count );
				ret.meta.next = this.next( limit, offset, count );
			}

			ret[ this.options.collectionName ] = this.slice( limit, offset );
			// dereference the request and respons
			this.setOptions({ req:null, res:null });
			return ret;
	}

	/**
	 * Returns  the uri for the next page if their is one
	 * @method module:tastypie/lib/paginator#next
	 * @param {Number} limit the number of items in the page
	 * @param {Number} offset where in the data set to derive the page from
	 * @param {Number} count the length of the current data set
	 * @return {String} url the URI that can be used to retrieve the next page
	 **/
	, next: function next( limit, offset, count ){
		var value = limit + offset;

		if( value > count - 1 ){
			return null;
		}

		return this.uri(limit, value);
	}

	/**
	 * determines the offset for the current data set using options, or pased in request
	 * @method module:tastypie/lib/paginator#offset
	 * @return {Number} offset THe resulting offset parameter
	 **/
	, offset: function offset( ){
			var oset = this.options.offset;
			var query = this.options.req.query || {};

			if( query.offset != null ){
				oset = parseInt( query.offset, 10 );
			}

			if( !isNumber( oset ) || oset<0 ){
				var e = Boom.badRequest("bad offset param: " + oset );
				e.req = this.options.req;
				e.res = this.options.res;
				return this.emit('error', e);
			}

			return oset;
	}

	/**
	 * Returns  the uri for the previous page if their is one
	 * @method module:tastypie/lib/paginator#previous
	 * @param {Number} limit the number of items in the page
	 * @param {Number} offset where in the data set to derive the page from
	 * @return {String} the URI that can be used to retrieve the previous page
	 **/
	, previous: function previous( limit, offset ){

		var value = offset - limit;
		if( value < 0 ){
			return null;
		}

		return this.uri( limit, value );
	}

	/**
	 * returns the number of objects in the current data set
	 * @method module:tastypie/lib/paginator#count
	 * @return {Number}
	 **/
	, count: function count(){
		return this.options.count;
	}

	/**
	 * retuns a slice from the current data set to represent a page
	 * @method module:tastypie/lib/paginator#slice
	 * @param {Number} limit The maximum number of items to include in the slice
	 * @param {Number} offset The starting position in the data set at which to start the slice
	 * @return {Array}
	 **/
	,slice: function slice( limit, offset ){
		if( limit <=0 ){
			return this.options.objects.slice( offset, this.options.objects.length );
		}

		return this.options.objects.slice( offset, ( offset ) + limit );
	}

	/**
	 * returns the number of items that should be included in the data set.
	 * Checks req.query for limit or a configured limit option
	 * @method module:tastypie/lib/paginator#limit
	 * @return {Number}
	 **/
	, limit: function limit(){
		var query = (this.options.req || {}).query || {}
		  , max   = this.options.max || -1
		  , limit = this.options.limit
		  , lmt
		  ;

		lmt = query.limit ? parseInt( query.limit, 10) : query.limit;
		lmt = isNumber( lmt ) ? lmt ? lmt : max : limit ? limit : 25;
		lmt = Math.min( lmt, max );
		if(!isNumber( lmt ) ){
			this.emit(
				'error'
				, Boom.badRequest('limit must be a number')
				, this.options.req
				, this.options.res
			);
		}
		return lmt;
	}

	/**
	 * generates a URI that will return page of data
	 * @method module:tastypie/lib/paginator#uri
	 * @param {Number} limit The maximum number of items to include in the slice
	 * @param {Number} offset The starting position in the data set at which to start the slice
	 * @return {String} a formatted uri
	 **/
	, uri: function uri( limit, offset ){
		var values = clone(this.options.req.query || {});

		values.limit = limit;
		values.offset = offset;
		return url.format({
			 pathname:this.options.req.path
			 ,query: values
		});
	}
});

/**
 * Assumes paging is done at the data store level. Slice method returns the objects array untouched
 * @class module:tastypie/lib/paginator.Remote
 * @extends module:tastypie/lib/paginator
 * @param {Object} options
 * @param {Object[]} [options.object=[]] The data to page
 * @param {?Number} [options.limit=null] The maximum number of object to include in a page
 * @param {Number} [options.offset=0] The number of object to skip
 * @param {Request} options.req A hapi.js request object
 * @param {Reply} options.res A hapi.js reply object
 * @example var Paginator = require('tastypie/lib/paginator')
paginator = new Paginator.Remote({
	limit: bundle.req.query.limit || 25
, req: bundle.req
, res: bundle.res
, collectionName: 'data'
, objects: []
});

to_be_serialize = paginator.page();
 */
module.exports.Remote = new Class({
	inherits: Paginator
	,sort: function( ){
		return this.options.objects;
	}
	, slice: function( ){
		return this.options.objects;
	}
	/**
	 * Generates a page of a data set
	 * @method module:tastypie/lib/paginator.REMOTE#page
	 * @return {Object} page An array sliced from the original data set using offset & limit parameters
	 **/
	, page: function page(){
			var limit = this.limit()
			  , offset = this.offset()
			  , count = this.count()
			  , ret = {
					meta:{
						count:count
					  , limit: limit
					  , offset: offset
					}
			};

			if( limit  && limit < count ){
				ret.meta.previous = this.previous( limit, offset, count );
				ret.meta.next = this.next( limit, offset, count );
			}

			ret[ this.options.collectionName ] = this.slice( limit, offset );
			// dereference the request and respons
			this.setOptions({ req:null, res:null });
			return ret;
	}
});

<|endoftext|>


<commit_before>Settings = new Mongo.Collection('settings');

Settings.attachSchema(
  new SimpleSchema({
    disableRegistration: {
      type: Boolean,
    },
    'mailServer.username': {
      type: String,
      optional: true,
    },
    'mailServer.password': {
      type: String,
      optional: true,
    },
    'mailServer.host': {
      type: String,
      optional: true,
    },
    'mailServer.port': {
      type: String,
      optional: true,
    },
    'mailServer.enableTLS': {
      type: Boolean,
      optional: true,
    },
    'mailServer.from': {
      type: String,
      optional: true,
    },
    productName: {
      type: String,
      optional: true,
    },
    displayAuthenticationMethod: {
      type: Boolean,
      optional: true,
    },
    defaultAuthenticationMethod: {
      type: String,
      optional: false,
    },
    hideLogo: {
      type: Boolean,
      optional: true,
    },
    createdAt: {
      type: Date,
      denyUpdate: true,
      // eslint-disable-next-line consistent-return
      autoValue() {
        if (this.isInsert) {
          return new Date();
        } else if (this.isUpsert) {
          return { $setOnInsert: new Date() };
        } else {
          this.unset();
        }
      },
    },
    modifiedAt: {
      type: Date,
      // eslint-disable-next-line consistent-return
      autoValue() {
        if (this.isInsert || this.isUpsert || this.isUpdate) {
          return new Date();
        } else {
          this.unset();
        }
      },
    },
  }),
);
Settings.helpers({
  mailUrl() {
    if (!this.mailServer.host) {
      return null;
    }
    const protocol = this.mailServer.enableTLS ? 'smtps://' : 'smtp://';
    if (!this.mailServer.username && !this.mailServer.password) {
      return `${protocol}${this.mailServer.host}:${this.mailServer.port}/`;
    }
    return `${protocol}${this.mailServer.username}:${encodeURIComponent(
      this.mailServer.password,
    )}@${this.mailServer.host}:${this.mailServer.port}/`;
  },
});
Settings.allow({
  update(userId) {
    const user = Users.findOne(userId);
    return user && user.isAdmin;
  },
});

if (Meteor.isServer) {
  Meteor.startup(() => {
    Settings._collection._ensureIndex({ modifiedAt: -1 });
    const setting = Settings.findOne({});
    if (!setting) {
      const now = new Date();
      const domain = process.env.ROOT_URL.match(
        /\/\/(?:www\.)?(.*)?(?:\/)?/,
      )[1];
      const from = `Boards Support <support@${domain}>`;
      const defaultSetting = {
        disableRegistration: false,
        mailServer: {
          username: '',
          password: '',
          host: '',
          port: '',
          enableTLS: false,
          from,
        },
        createdAt: now,
        modifiedAt: now,
        displayAuthenticationMethod: true,
        defaultAuthenticationMethod: 'password',
      };
      Settings.insert(defaultSetting);
    }
    const newSetting = Settings.findOne();
    if (!process.env.MAIL_URL && newSetting.mailUrl())
      process.env.MAIL_URL = newSetting.mailUrl();
    Accounts.emailTemplates.from = process.env.MAIL_FROM
      ? process.env.MAIL_FROM
      : newSetting.mailServer.from;
  });
  Settings.after.update((userId, doc, fieldNames) => {
    // assign new values to mail-from & MAIL_URL in environment
    if (_.contains(fieldNames, 'mailServer') && doc.mailServer.host) {
      const protocol = doc.mailServer.enableTLS ? 'smtps://' : 'smtp://';
      if (!doc.mailServer.username && !doc.mailServer.password) {
        process.env.MAIL_URL = `${protocol}${doc.mailServer.host}:${doc.mailServer.port}/`;
      } else {
        process.env.MAIL_URL = `${protocol}${
          doc.mailServer.username
        }:${encodeURIComponent(doc.mailServer.password)}@${
          doc.mailServer.host
        }:${doc.mailServer.port}/`;
      }
      Accounts.emailTemplates.from = doc.mailServer.from;
    }
  });

  function getRandomNum(min, max) {
    const range = max - min;
    const rand = Math.random();
    return min + Math.round(rand * range);
  }

  function getEnvVar(name) {
    const value = process.env[name];
    if (value) {
      return value;
    }
    throw new Meteor.Error([
      'var-not-exist',
      `The environment variable ${name} does not exist`,
    ]);
  }

  function sendInvitationEmail(_id) {
    const icode = InvitationCodes.findOne(_id);
    const author = Users.findOne(Meteor.userId());
    try {
      const params = {
        email: icode.email,
        inviter: Users.findOne(icode.authorId).username,
        user: icode.email.split('@')[0],
        icode: icode.code,
        url: FlowRouter.url('sign-up'),
      };
      const lang = author.getLanguage();

      Email.send({
        to: icode.email,
        from: Accounts.emailTemplates.from,
        subject: TAPi18n.__('email-invite-register-subject', params, lang),
        text: TAPi18n.__('email-invite-register-text', params, lang),
      });
    } catch (e) {
      InvitationCodes.remove(_id);
      throw new Meteor.Error('email-fail', e.message);
    }
  }

  function isLdapEnabled() {
    return process.env.LDAP_ENABLE === 'true';
  }

  function isOauth2Enabled() {
    return process.env.OAUTH2_ENABLED === 'true';
  }

  function isCasEnabled() {
    return process.env.CAS_ENABLED === 'true';
  }

  function isApiEnabled() {
    return process.env.WITH_API === 'true';
  }

  Meteor.methods({
    sendInvitation(emails, boards) {
      check(emails, [String]);
      check(boards, [String]);

      const user = Users.findOne(Meteor.userId());
      if (!user.isAdmin) {
        throw new Meteor.Error('not-allowed');
      }
      emails.forEach(email => {
        if (email && SimpleSchema.RegEx.Email.test(email)) {
          // Checks if the email is already link to an account.
          const userExist = Users.findOne({ email });
          if (userExist) {
            throw new Meteor.Error(
              'user-exist',
              `The user with the email ${email} has already an account.`,
            );
          }
          // Checks if the email is already link to an invitation.
          const invitation = InvitationCodes.findOne({ email });
          if (invitation) {
            InvitationCodes.update(invitation, {
              $set: { boardsToBeInvited: boards },
            });
            sendInvitationEmail(invitation._id);
          } else {
            const code = getRandomNum(100000, 999999);
            InvitationCodes.insert(
              {
                code,
                email,
                boardsToBeInvited: boards,
                createdAt: new Date(),
                authorId: Meteor.userId(),
              },
              function(err, _id) {
                if (!err && _id) {
                  sendInvitationEmail(_id);
                } else {
                  throw new Meteor.Error(
                    'invitation-generated-fail',
                    err.message,
                  );
                }
              },
            );
          }
        }
      });
    },

    sendSMTPTestEmail() {
      if (!Meteor.userId()) {
        throw new Meteor.Error('invalid-user');
      }
      const user = Meteor.user();
      if (!user.emails && !user.emails[0] && user.emails[0].address) {
        throw new Meteor.Error('email-invalid');
      }
      this.unblock();
      const lang = user.getLanguage();
      try {
        Email.send({
          to: user.emails[0].address,
          from: Accounts.emailTemplates.from,
          subject: TAPi18n.__('email-smtp-test-subject', { lng: lang }),
          text: TAPi18n.__('email-smtp-test-text', { lng: lang }),
        });
      } catch ({ message }) {
        throw new Meteor.Error(
          'email-fail',
          `${TAPi18n.__('email-fail-text', { lng: lang })}: ${message}`,
          message,
        );
      }
      return {
        message: 'email-sent',
        email: user.emails[0].address,
      };
    },

    getCustomUI() {
      const setting = Settings.findOne({});
      if (!setting.productName) {
        return {
          productName: '',
        };
      } else {
        return {
          productName: `${setting.productName}`,
        };
      }
    },

    getMatomoConf() {
      return {
        address: getEnvVar('MATOMO_ADDRESS'),
        siteId: getEnvVar('MATOMO_SITE_ID'),
        doNotTrack: process.env.MATOMO_DO_NOT_TRACK || false,
        withUserName: process.env.MATOMO_WITH_USERNAME || false,
      };
    },

    _isLdapEnabled() {
      return isLdapEnabled();
    },

    _isOauth2Enabled() {
      return isOauth2Enabled();
    },

    _isCasEnabled() {
      return isCasEnabled();
    },

    _isApiEnabled() {
      return isApiEnabled();
    },

    // Gets all connection methods to use it in the Template
    getAuthenticationsEnabled() {
      return {
        ldap: isLdapEnabled(),
        oauth2: isOauth2Enabled(),
        cas: isCasEnabled(),
      };
    },

    getDefaultAuthenticationMethod() {
      return process.env.DEFAULT_AUTHENTICATION_METHOD;
    },

    isPasswordLoginDisabled() {
      return process.env.PASSWORD_LOGIN_ENABLED === 'false';
    },
  });
}

export default Settings;
<commit_msg>Fix email verification in `sendSMTPTestEmail`<commit_after>Settings = new Mongo.Collection('settings');

Settings.attachSchema(
  new SimpleSchema({
    disableRegistration: {
      type: Boolean,
    },
    'mailServer.username': {
      type: String,
      optional: true,
    },
    'mailServer.password': {
      type: String,
      optional: true,
    },
    'mailServer.host': {
      type: String,
      optional: true,
    },
    'mailServer.port': {
      type: String,
      optional: true,
    },
    'mailServer.enableTLS': {
      type: Boolean,
      optional: true,
    },
    'mailServer.from': {
      type: String,
      optional: true,
    },
    productName: {
      type: String,
      optional: true,
    },
    displayAuthenticationMethod: {
      type: Boolean,
      optional: true,
    },
    defaultAuthenticationMethod: {
      type: String,
      optional: false,
    },
    hideLogo: {
      type: Boolean,
      optional: true,
    },
    createdAt: {
      type: Date,
      denyUpdate: true,
      // eslint-disable-next-line consistent-return
      autoValue() {
        if (this.isInsert) {
          return new Date();
        } else if (this.isUpsert) {
          return { $setOnInsert: new Date() };
        } else {
          this.unset();
        }
      },
    },
    modifiedAt: {
      type: Date,
      // eslint-disable-next-line consistent-return
      autoValue() {
        if (this.isInsert || this.isUpsert || this.isUpdate) {
          return new Date();
        } else {
          this.unset();
        }
      },
    },
  }),
);
Settings.helpers({
  mailUrl() {
    if (!this.mailServer.host) {
      return null;
    }
    const protocol = this.mailServer.enableTLS ? 'smtps://' : 'smtp://';
    if (!this.mailServer.username && !this.mailServer.password) {
      return `${protocol}${this.mailServer.host}:${this.mailServer.port}/`;
    }
    return `${protocol}${this.mailServer.username}:${encodeURIComponent(
      this.mailServer.password,
    )}@${this.mailServer.host}:${this.mailServer.port}/`;
  },
});
Settings.allow({
  update(userId) {
    const user = Users.findOne(userId);
    return user && user.isAdmin;
  },
});

if (Meteor.isServer) {
  Meteor.startup(() => {
    Settings._collection._ensureIndex({ modifiedAt: -1 });
    const setting = Settings.findOne({});
    if (!setting) {
      const now = new Date();
      const domain = process.env.ROOT_URL.match(
        /\/\/(?:www\.)?(.*)?(?:\/)?/,
      )[1];
      const from = `Boards Support <support@${domain}>`;
      const defaultSetting = {
        disableRegistration: false,
        mailServer: {
          username: '',
          password: '',
          host: '',
          port: '',
          enableTLS: false,
          from,
        },
        createdAt: now,
        modifiedAt: now,
        displayAuthenticationMethod: true,
        defaultAuthenticationMethod: 'password',
      };
      Settings.insert(defaultSetting);
    }
    const newSetting = Settings.findOne();
    if (!process.env.MAIL_URL && newSetting.mailUrl())
      process.env.MAIL_URL = newSetting.mailUrl();
    Accounts.emailTemplates.from = process.env.MAIL_FROM
      ? process.env.MAIL_FROM
      : newSetting.mailServer.from;
  });
  Settings.after.update((userId, doc, fieldNames) => {
    // assign new values to mail-from & MAIL_URL in environment
    if (_.contains(fieldNames, 'mailServer') && doc.mailServer.host) {
      const protocol = doc.mailServer.enableTLS ? 'smtps://' : 'smtp://';
      if (!doc.mailServer.username && !doc.mailServer.password) {
        process.env.MAIL_URL = `${protocol}${doc.mailServer.host}:${doc.mailServer.port}/`;
      } else {
        process.env.MAIL_URL = `${protocol}${
          doc.mailServer.username
        }:${encodeURIComponent(doc.mailServer.password)}@${
          doc.mailServer.host
        }:${doc.mailServer.port}/`;
      }
      Accounts.emailTemplates.from = doc.mailServer.from;
    }
  });

  function getRandomNum(min, max) {
    const range = max - min;
    const rand = Math.random();
    return min + Math.round(rand * range);
  }

  function getEnvVar(name) {
    const value = process.env[name];
    if (value) {
      return value;
    }
    throw new Meteor.Error([
      'var-not-exist',
      `The environment variable ${name} does not exist`,
    ]);
  }

  function sendInvitationEmail(_id) {
    const icode = InvitationCodes.findOne(_id);
    const author = Users.findOne(Meteor.userId());
    try {
      const params = {
        email: icode.email,
        inviter: Users.findOne(icode.authorId).username,
        user: icode.email.split('@')[0],
        icode: icode.code,
        url: FlowRouter.url('sign-up'),
      };
      const lang = author.getLanguage();

      Email.send({
        to: icode.email,
        from: Accounts.emailTemplates.from,
        subject: TAPi18n.__('email-invite-register-subject', params, lang),
        text: TAPi18n.__('email-invite-register-text', params, lang),
      });
    } catch (e) {
      InvitationCodes.remove(_id);
      throw new Meteor.Error('email-fail', e.message);
    }
  }

  function isLdapEnabled() {
    return process.env.LDAP_ENABLE === 'true';
  }

  function isOauth2Enabled() {
    return process.env.OAUTH2_ENABLED === 'true';
  }

  function isCasEnabled() {
    return process.env.CAS_ENABLED === 'true';
  }

  function isApiEnabled() {
    return process.env.WITH_API === 'true';
  }

  Meteor.methods({
    sendInvitation(emails, boards) {
      check(emails, [String]);
      check(boards, [String]);

      const user = Users.findOne(Meteor.userId());
      if (!user.isAdmin) {
        throw new Meteor.Error('not-allowed');
      }
      emails.forEach(email => {
        if (email && SimpleSchema.RegEx.Email.test(email)) {
          // Checks if the email is already link to an account.
          const userExist = Users.findOne({ email });
          if (userExist) {
            throw new Meteor.Error(
              'user-exist',
              `The user with the email ${email} has already an account.`,
            );
          }
          // Checks if the email is already link to an invitation.
          const invitation = InvitationCodes.findOne({ email });
          if (invitation) {
            InvitationCodes.update(invitation, {
              $set: { boardsToBeInvited: boards },
            });
            sendInvitationEmail(invitation._id);
          } else {
            const code = getRandomNum(100000, 999999);
            InvitationCodes.insert(
              {
                code,
                email,
                boardsToBeInvited: boards,
                createdAt: new Date(),
                authorId: Meteor.userId(),
              },
              function(err, _id) {
                if (!err && _id) {
                  sendInvitationEmail(_id);
                } else {
                  throw new Meteor.Error(
                    'invitation-generated-fail',
                    err.message,
                  );
                }
              },
            );
          }
        }
      });
    },

    sendSMTPTestEmail() {
      if (!Meteor.userId()) {
        throw new Meteor.Error('invalid-user');
      }
      const user = Meteor.user();
      if (!user.emails || !user.emails[0] || user.emails[0].address) {
        throw new Meteor.Error('email-invalid');
      }
      this.unblock();
      const lang = user.getLanguage();
      try {
        Email.send({
          to: user.emails[0].address,
          from: Accounts.emailTemplates.from,
          subject: TAPi18n.__('email-smtp-test-subject', { lng: lang }),
          text: TAPi18n.__('email-smtp-test-text', { lng: lang }),
        });
      } catch ({ message }) {
        throw new Meteor.Error(
          'email-fail',
          `${TAPi18n.__('email-fail-text', { lng: lang })}: ${message}`,
          message,
        );
      }
      return {
        message: 'email-sent',
        email: user.emails[0].address,
      };
    },

    getCustomUI() {
      const setting = Settings.findOne({});
      if (!setting.productName) {
        return {
          productName: '',
        };
      } else {
        return {
          productName: `${setting.productName}`,
        };
      }
    },

    getMatomoConf() {
      return {
        address: getEnvVar('MATOMO_ADDRESS'),
        siteId: getEnvVar('MATOMO_SITE_ID'),
        doNotTrack: process.env.MATOMO_DO_NOT_TRACK || false,
        withUserName: process.env.MATOMO_WITH_USERNAME || false,
      };
    },

    _isLdapEnabled() {
      return isLdapEnabled();
    },

    _isOauth2Enabled() {
      return isOauth2Enabled();
    },

    _isCasEnabled() {
      return isCasEnabled();
    },

    _isApiEnabled() {
      return isApiEnabled();
    },

    // Gets all connection methods to use it in the Template
    getAuthenticationsEnabled() {
      return {
        ldap: isLdapEnabled(),
        oauth2: isOauth2Enabled(),
        cas: isCasEnabled(),
      };
    },

    getDefaultAuthenticationMethod() {
      return process.env.DEFAULT_AUTHENTICATION_METHOD;
    },

    isPasswordLoginDisabled() {
      return process.env.PASSWORD_LOGIN_ENABLED === 'false';
    },
  });
}

export default Settings;
<|endoftext|>


<commit_before>/* global HTMLElement */
var ANode = require('./a-node');
var registerElement = require('./a-register-element').registerElement;
var components = require('./component').components;

/**
 * @member {object} componentAttrCache - Cache of pre parsed component attributes
 */
module.exports = registerElement('a-mixin', {
  prototype: Object.create(
    ANode.prototype,
    {
      createdCallback: {
        value: function () {
          this.componentAttrCache = {};
        }
      },

      attributeChangedCallback: {
        value: function (attr, oldVal, newVal) {
          this.cacheAttribute(attr, newVal);
        }
      },

      attachedCallback: {
        value: function () {
          this.cacheAttributes();
          this.load();
        },
        writable: window.debug
      },

      setAttribute: {
        value: function (attr, value) {
          this.cacheAttribute(attr, value);
          HTMLElement.prototype.setAttribute.call(this, attr, value);
        },
        writable: window.debug
      },

      cacheAttribute: {
        value: function (attr, value) {
          var component = components[attr];
          if (!component) { return; }
          value = value === undefined ? HTMLElement.prototype.getAttribute.call(this, attr) : value;
          this.componentAttrCache[attr] = component.parseAttrValueForCache(value);
        }
      },

      getAttribute: {
        value: function (attr) {
          return this.componentAttrCache[attr] || HTMLElement.prototype.getAttribute.call(this, attr);
        },
        writable: window.debug
      },

      /**
       * Update cache of parsed component attributes
       */
      cacheAttributes: {
        value: function () {
          var attributes = this.attributes;
          var attrName;
          var i;
          for (i = 0; i < attributes.length; ++i) {
            attrName = attributes[i].name;
            this.cacheAttribute(attrName);
          }
        }
      }
    }
  )
});
<commit_msg>make a-mixin indents consistent (#1607)<commit_after>/* global HTMLElement */
var ANode = require('./a-node');
var registerElement = require('./a-register-element').registerElement;
var components = require('./component').components;

/**
 * @member {object} componentAttrCache - Cache of pre parsed component attributes
 */
module.exports = registerElement('a-mixin', {
  prototype: Object.create(ANode.prototype, {
    createdCallback: {
      value: function () {
        this.componentAttrCache = {};
      }
    },

    attributeChangedCallback: {
      value: function (attr, oldVal, newVal) {
        this.cacheAttribute(attr, newVal);
      }
    },

    attachedCallback: {
      value: function () {
        this.cacheAttributes();
        this.load();
      },
      writable: window.debug
    },

    setAttribute: {
      value: function (attr, value) {
        this.cacheAttribute(attr, value);
        HTMLElement.prototype.setAttribute.call(this, attr, value);
      },
      writable: window.debug
    },

    cacheAttribute: {
      value: function (attr, value) {
        var component = components[attr];
        if (!component) { return; }
        value = value === undefined ? HTMLElement.prototype.getAttribute.call(this, attr) : value;
        this.componentAttrCache[attr] = component.parseAttrValueForCache(value);
      }
    },

    getAttribute: {
      value: function (attr) {
        return this.componentAttrCache[attr] || HTMLElement.prototype.getAttribute.call(this, attr);
      },
      writable: window.debug
    },

    /**
     * Update cache of parsed component attributes
     */
    cacheAttributes: {
      value: function () {
        var attributes = this.attributes;
        var attrName;
        var i;
        for (i = 0; i < attributes.length; ++i) {
          attrName = attributes[i].name;
          this.cacheAttribute(attrName);
        }
      }
    }
  })
});
<|endoftext|>


<commit_before>/**
 * Gen 2 moves
 */
function clampIntRange(num, min, max) {
	num = Math.floor(num);
	if (num < min) num = min;
	if (typeof max !== 'undefined' && num > max) num = max;
	return num;
}
exports.BattleMovedex = {
	bellydrum: {
		inherit: true,
		onHit: function(target) {
			if (target.boosts.atk >= 6) {
				return false;
			}
			if (target.hp <= target.maxhp/2) {
				this.boost({atk: 2});
				return false;
			}
			this.directDamage(target.maxhp/2);
			target.setBoost({atk: 6});
			this.add('-setboost', target, 'atk', '6', '[from] move: Belly Drum');
		}
	},
	encore: {
		inherit: true,
		isBounceable: false,
		volatileStatus: 'encore',
		effect: {
			durationCallback: function() {
				return this.random(2,6);
			},
			onStart: function(target) {
				var noEncore = {encore:1, mimic:1, mirrormove:1, sketch:1, transform:1};
				var moveIndex = target.moves.indexOf(target.lastMove);
				if (!target.lastMove || noEncore[target.lastMove] || (target.moveset[moveIndex] && target.moveset[moveIndex].pp <= 0)) {
					// it failed
					this.add('-fail',target);
					delete target.volatiles['encore'];
					return;
				}
				this.effectData.move = target.lastMove;
				this.add('-start', target, 'Encore');
				if (!this.willMove(target)) {
					this.effectData.duration++;
				}
			},
			onOverrideDecision: function(pokemon) {
				return this.effectData.move;
			},
			onResidualOrder: 13,
			onResidual: function(target) {
				if (target.moves.indexOf(target.lastMove) >= 0 && target.moveset[target.moves.indexOf(target.lastMove)].pp <= 0) {
					// early termination if you run out of PP
					delete target.volatiles.encore;
					this.add('-end', target, 'Encore');
				}
			},
			onEnd: function(target) {
				this.add('-end', target, 'Encore');
			},
			onModifyPokemon: function(pokemon) {
				if (!this.effectData.move || !pokemon.hasMove(this.effectData.move)) {
					return;
				}
				for (var i=0; i<pokemon.moveset.length; i++) {
					if (pokemon.moveset[i].id !== this.effectData.move) {
						pokemon.moveset[i].disabled = true;
					}
				}
			}
		}
	},
	explosion: {
		inherit: true,
		basePower: 500
	},
	growth: {
		inherit: true,
		onModifyMove: null,
		boosts: {
			spa: 1
		}
	},
	leechseed: {
		inherit: true,
		onHit: function (target, source, move) {
			if (!source || source.fainted || source.hp <= 0) {
				// Well this shouldn't happen
				this.debug('Nothing to leech into');
				return;
			}
			if (target.newlySwitched && target.speed <= source.speed) {
				var toLeech = clampIntRange(target.maxhp/8, 1);
				var damage = this.damage(toLeech, target, source, 'move: Leech Seed');
				if (damage) {
					this.heal(damage, source, target);
				}
			}
		},
		effect: {
			onStart: function(target) {
				this.add('-start', target, 'move: Leech Seed');
			},
			onAfterMoveSelf: function(pokemon) {
				var target = pokemon.side.foe.active[pokemon.volatiles['leechseed'].sourcePosition];
				if (!target || target.fainted || target.hp <= 0) {
					this.debug('Nothing to leech into');
					return;
				}
				var toLeech = clampIntRange(pokemon.maxhp/8, 1);
				var damage = this.damage(toLeech, pokemon, target);
				if (damage) {
					this.heal(damage, target, pokemon);
				}
			}
		}
	},
	rest: {
		inherit: true,
		onHit: function(target) {
			if (target.hp >= target.maxhp) return false;
			if (!target.setStatus('slp') && target.status !== 'slp') return false;
			target.statusData.time = 3;
			target.statusData.startTime = 3;
			this.heal(target.maxhp);
			this.add('-status', target, 'slp', '[from] move: Rest');
		},
		secondary: false
	},
	selfdestruct: {
		inherit: true,
		basePower: 400
	},
	sleeptalk: {
		inherit: true,
			onHit: function(pokemon) {
				var moves = [];
				for (var i=0; i<pokemon.moveset.length; i++) {
					var move = pokemon.moveset[i].id;
					var NoSleepTalk = {
						bide:1, dig:1, fly:1, metronome:1, mirrormove:1,
						skullbash:1, skyattack:1, sleeptalk:1, solarbeam:1, razorwind:1
					};
					if (move && !NoSleepTalk[move]) {
						moves.push(move);
					}
				}
				var move = '';
				if (moves.length) move = moves[this.random(moves.length)];
				if (!move) return false;
				move.isSleepTalk = true;
				this.useMove(move, pokemon);
			}
	},
	spikes: {
		inherit: true,
		effect: {
			// this is a side condition
			onStart: function(side) {
				if (!this.effectData.layers || this.effectData.layers === 0) {
					this.add('-sidestart', side, 'Spikes');
					this.effectData.layers = 1;
				} else {
					return false;
				}
			},
			onSwitchIn: function(pokemon) {
				var side = pokemon.side;
				if (!pokemon.runImmunity('Ground')) return;
				var damageAmounts = [0,3];
				var damage = this.damage(damageAmounts[this.effectData.layers]*pokemon.maxhp/24);
			}
		}
	},
	spite: {
		inherit: true,
		onHit: function(target) {
			var reduction = this.random(2, 6);
			if (target.deductPP(target.lastMove, reduction)) {
				this.add("-activate", target, 'move: Spite', target.lastMove, reduction);
				return;
			}
			return false;
		},
	},
	substitute: {
		inherit: true,
		effect: {
			onStart: function(target) {
				this.add('-start', target, 'Substitute');
				this.effectData.hp = Math.floor(target.maxhp/4);
				delete target.volatiles['partiallytrapped'];
			},
			onTryPrimaryHitPriority: -1,
			onTryPrimaryHit: function(target, source, move) {
				if (target === source) {
					this.debug('sub bypass: self hit');
					return;
				}
				if (move.category === 'Status') {
					var SubBlocked = {
						leechseed:1, lockon:1, mindreader:1, nightmare:1, painsplit:1
					};
					if (move.status || move.boosts || move.volatileStatus === 'confusion' || SubBlocked[move.id]) {
						return false;
					}
					return;
				}
				var damage = this.getDamage(source, target, move);
				if (!damage) {
					return null;
				}
				damage = this.runEvent('SubDamage', target, source, move, damage);
				if (!damage) {
					return damage;
				}
				if (damage > target.volatiles['substitute'].hp) {
					damage = target.volatiles['substitute'].hp;
				}
				target.volatiles['substitute'].hp -= damage;
				source.lastDamage = damage;
				if (target.volatiles['substitute'].hp <= 0) {
					target.removeVolatile('substitute');
				} else {
					this.add('-activate', target, 'Substitute', '[damage]');
				}
				if (move.recoil) {
					this.damage(Math.round(damage * move.recoil[0] / move.recoil[1]), source, target, 'recoil');
				}
				if (move.drain) {
					this.heal(Math.ceil(damage * move.drain[0] / move.drain[1]), source, target, 'drain');
				}
				this.runEvent('AfterSubDamage', target, source, move, damage);
				return 0; // hit
			},
			onEnd: function(target) {
				this.add('-end', target, 'Substitute');
			}
		}
	},
	rage: {
		// todo
		// Rage boosts in Gens 2-4 is for the duration of Rage only
		// Disable does not build
		inherit: true
	},
	magikarpsrevenge: null
};<commit_msg>Gen 2: Put phazing moves correct priority<commit_after>/**
 * Gen 2 moves
 */
function clampIntRange(num, min, max) {
	num = Math.floor(num);
	if (num < min) num = min;
	if (typeof max !== 'undefined' && num > max) num = max;
	return num;
}
exports.BattleMovedex = {
	bellydrum: {
		inherit: true,
		onHit: function(target) {
			if (target.boosts.atk >= 6) {
				return false;
			}
			if (target.hp <= target.maxhp/2) {
				this.boost({atk: 2});
				return false;
			}
			this.directDamage(target.maxhp/2);
			target.setBoost({atk: 6});
			this.add('-setboost', target, 'atk', '6', '[from] move: Belly Drum');
		}
	},
	encore: {
		inherit: true,
		isBounceable: false,
		volatileStatus: 'encore',
		effect: {
			durationCallback: function() {
				return this.random(2,6);
			},
			onStart: function(target) {
				var noEncore = {encore:1, mimic:1, mirrormove:1, sketch:1, transform:1};
				var moveIndex = target.moves.indexOf(target.lastMove);
				if (!target.lastMove || noEncore[target.lastMove] || (target.moveset[moveIndex] && target.moveset[moveIndex].pp <= 0)) {
					// it failed
					this.add('-fail',target);
					delete target.volatiles['encore'];
					return;
				}
				this.effectData.move = target.lastMove;
				this.add('-start', target, 'Encore');
				if (!this.willMove(target)) {
					this.effectData.duration++;
				}
			},
			onOverrideDecision: function(pokemon) {
				return this.effectData.move;
			},
			onResidualOrder: 13,
			onResidual: function(target) {
				if (target.moves.indexOf(target.lastMove) >= 0 && target.moveset[target.moves.indexOf(target.lastMove)].pp <= 0) {
					// early termination if you run out of PP
					delete target.volatiles.encore;
					this.add('-end', target, 'Encore');
				}
			},
			onEnd: function(target) {
				this.add('-end', target, 'Encore');
			},
			onModifyPokemon: function(pokemon) {
				if (!this.effectData.move || !pokemon.hasMove(this.effectData.move)) {
					return;
				}
				for (var i=0; i<pokemon.moveset.length; i++) {
					if (pokemon.moveset[i].id !== this.effectData.move) {
						pokemon.moveset[i].disabled = true;
					}
				}
			}
		}
	},
	explosion: {
		inherit: true,
		basePower: 500
	},
	growth: {
		inherit: true,
		onModifyMove: null,
		boosts: {
			spa: 1
		}
	},
	leechseed: {
		inherit: true,
		onHit: function (target, source, move) {
			if (!source || source.fainted || source.hp <= 0) {
				// Well this shouldn't happen
				this.debug('Nothing to leech into');
				return;
			}
			if (target.newlySwitched && target.speed <= source.speed) {
				var toLeech = clampIntRange(target.maxhp/8, 1);
				var damage = this.damage(toLeech, target, source, 'move: Leech Seed');
				if (damage) {
					this.heal(damage, source, target);
				}
			}
		},
		effect: {
			onStart: function(target) {
				this.add('-start', target, 'move: Leech Seed');
			},
			onAfterMoveSelf: function(pokemon) {
				var target = pokemon.side.foe.active[pokemon.volatiles['leechseed'].sourcePosition];
				if (!target || target.fainted || target.hp <= 0) {
					this.debug('Nothing to leech into');
					return;
				}
				var toLeech = clampIntRange(pokemon.maxhp/8, 1);
				var damage = this.damage(toLeech, pokemon, target);
				if (damage) {
					this.heal(damage, target, pokemon);
				}
			}
		}
	},
	rest: {
		inherit: true,
		onHit: function(target) {
			if (target.hp >= target.maxhp) return false;
			if (!target.setStatus('slp') && target.status !== 'slp') return false;
			target.statusData.time = 3;
			target.statusData.startTime = 3;
			this.heal(target.maxhp);
			this.add('-status', target, 'slp', '[from] move: Rest');
		},
		secondary: false
	},
	selfdestruct: {
		inherit: true,
		basePower: 400
	},
	sleeptalk: {
		inherit: true,
			onHit: function(pokemon) {
				var moves = [];
				for (var i=0; i<pokemon.moveset.length; i++) {
					var move = pokemon.moveset[i].id;
					var NoSleepTalk = {
						bide:1, dig:1, fly:1, metronome:1, mirrormove:1,
						skullbash:1, skyattack:1, sleeptalk:1, solarbeam:1, razorwind:1
					};
					if (move && !NoSleepTalk[move]) {
						moves.push(move);
					}
				}
				var move = '';
				if (moves.length) move = moves[this.random(moves.length)];
				if (!move) return false;
				move.isSleepTalk = true;
				this.useMove(move, pokemon);
			}
	},
	spikes: {
		inherit: true,
		effect: {
			// this is a side condition
			onStart: function(side) {
				if (!this.effectData.layers || this.effectData.layers === 0) {
					this.add('-sidestart', side, 'Spikes');
					this.effectData.layers = 1;
				} else {
					return false;
				}
			},
			onSwitchIn: function(pokemon) {
				var side = pokemon.side;
				if (!pokemon.runImmunity('Ground')) return;
				var damageAmounts = [0,3];
				var damage = this.damage(damageAmounts[this.effectData.layers]*pokemon.maxhp/24);
			}
		}
	},
	spite: {
		inherit: true,
		onHit: function(target) {
			var reduction = this.random(2, 6);
			if (target.deductPP(target.lastMove, reduction)) {
				this.add("-activate", target, 'move: Spite', target.lastMove, reduction);
				return;
			}
			return false;
		},
	},
	substitute: {
		inherit: true,
		effect: {
			onStart: function(target) {
				this.add('-start', target, 'Substitute');
				this.effectData.hp = Math.floor(target.maxhp/4);
				delete target.volatiles['partiallytrapped'];
			},
			onTryPrimaryHitPriority: -1,
			onTryPrimaryHit: function(target, source, move) {
				if (target === source) {
					this.debug('sub bypass: self hit');
					return;
				}
				if (move.category === 'Status') {
					var SubBlocked = {
						leechseed:1, lockon:1, mindreader:1, nightmare:1, painsplit:1
					};
					if (move.status || move.boosts || move.volatileStatus === 'confusion' || SubBlocked[move.id]) {
						return false;
					}
					return;
				}
				var damage = this.getDamage(source, target, move);
				if (!damage) {
					return null;
				}
				damage = this.runEvent('SubDamage', target, source, move, damage);
				if (!damage) {
					return damage;
				}
				if (damage > target.volatiles['substitute'].hp) {
					damage = target.volatiles['substitute'].hp;
				}
				target.volatiles['substitute'].hp -= damage;
				source.lastDamage = damage;
				if (target.volatiles['substitute'].hp <= 0) {
					target.removeVolatile('substitute');
				} else {
					this.add('-activate', target, 'Substitute', '[damage]');
				}
				if (move.recoil) {
					this.damage(Math.round(damage * move.recoil[0] / move.recoil[1]), source, target, 'recoil');
				}
				if (move.drain) {
					this.heal(Math.ceil(damage * move.drain[0] / move.drain[1]), source, target, 'drain');
				}
				this.runEvent('AfterSubDamage', target, source, move, damage);
				return 0; // hit
			},
			onEnd: function(target) {
				this.add('-end', target, 'Substitute');
			}
		}
	},
	rage: {
		// todo
		// Rage boosts in Gens 2-4 is for the duration of Rage only
		// Disable does not build
		inherit: true
	},
	roar: {
		inherit: true,
		priority: -1
	},
	magikarpsrevenge: null,
	whirlwind: {
		inherit: true,
		priority: -1
	},
};<|endoftext|>


<commit_before>import {assign,find,has,includes} from "lodash";
import {parse as baseParse} from "./m+xml.pegjs";
import * as Temple from "../";
import {rollup} from "rollup";
import inject from "@mrgalaxy/rollup-plugin-inject";
import path from "path";

const smfurl = "sourceMappingURL=";
const datauri = "data:application/json;charset=utf-8;base64,";
const rel_regex = /^\.{0,2}\//;

var toBase64;
if (typeof window !== "undefined" && typeof window.btoa === "function") {
	toBase64 = window.btoa;
} else toBase64 = function(str) {
	return new Buffer(str, "utf-8").toString("base64");
};

function parseFiles(files, { filename }) {
	if (typeof files === "string") {
		if (filename) files = { [filename]: files };
		else files = [ files ];
	}

	if (Array.isArray(files)) files = files.reduce(function(memo, src, name) {
		if (typeof name === "number") name = `template${name}.html`;
		memo[name] = src;
		return memo;
	}, {});

	return files;
}

export function parse(src, options={}) {
	try {
		return baseParse(src, options);
	} catch(e) {
		e.filename = name;
		e.source = src;
		throw e;
	}
}

function srcToString(smf) {
	return this.code + "\n\n//# " + smfurl +
		(typeof smf === "string" ? smf :
			datauri + toBase64(this.map.toString()));
}

export function compile(files, options={}, cb) {
	files = parseFiles(files, options);
	let exts = [].concat(options.extensions || ".html").filter(Boolean);
	let basedir = options.basedir || (options.filename ? path.dirname(options.filename) : ".");
	let hasCb = typeof cb === "function";
	let templates = [];

	return rollup({
		onwarn: () => {},
		entry: "_entry.js",
		plugins: [
			{
				resolveId: function(id, file) {
					if (id === "_entry.js" ||
						id === "_template.js") return id;

					let full = path.resolve(basedir, path.dirname(file), id);
					let entry = find(Object.keys(files), (name) => {
						return path.resolve(basedir, name) === full;
					});
					if (entry) return entry;

					// only relative paths are followed
					if (rel_regex.test(id) && includes(exts, path.extname(id))) {
						return full;
					}
				},
				load: function(id) {
					if (id === "_entry.js") {
						return Object.keys(files).map(name => {
							return `import ${JSON.stringify(name)}`;
						}).join("\n") + "\nexport default Template;\n";
					}

					if (id === "_template.js") {
						return "export default {};\n";
					}

					if (has(files, id)) {
						return files[id];
					}
				},
				transform: function(src, id) {
					if (!includes(exts, path.extname(id))) return;
					templates.push(id);

					let file = parse(src, assign({ filename: id }, options));
					let out = file.compile(options).toStringWithSourceMap();
					out.map = out.map.toJSON();
					return out;
				}
			},
			inject({
				Temple: "templejs",
				Template: "_template.js",
				idom: [ "templejs", "idom" ],
				decorators: [ "templejs", "decorators" ]
			})
		].concat(options.plugins).filter(Boolean)
	}).then(function(bundle) {
		let out = bundle.generate({
			format: options.format,
			sourceMap: true,
			exports: "default",
			useStrict: false,
			moduleId: options.moduleId,
			moduleName: options.moduleName,
			globals: {
				templejs: "Temple"
			}
		});

		out.templates = templates;
		out.toString = srcToString;

		return out;
	}).then((res) => {
		if (hasCb) cb(null, res);
		return res;
	}, (e) => {
		if (hasCb) cb(e);
		throw e;
	});
}

export function exec(tpl, options) {
	return compile(tpl, assign({
		format: "cjs"
	}, options)).then(function(r) {
		const module = { exports: {} };
		const exports = module.exports;
		const _require = (id) => {
			if (id === "templejs") return Temple;
			return require(id);
		};

		return (new Function("module", "exports", "require", r.code))(module, exports, _require);
	});
}

// export function compileHTML(html, options) {
// 	options = options || {};
// 	var node = new AST.HTML(null, html);
// 	return getSource(node.compile(options), html, options);
// }
//
// export function renderHTML(html, options) {
// 	/* jshint -W054 */
// 	var r = compileHTML(html, options);
// 	// console.log(r);
// 	return (new Function("Temple", r))(require("./"));
// }
<commit_msg>fix: simplify exec method<commit_after>import {assign,find,has,includes} from "lodash";
import {parse as baseParse} from "./m+xml.pegjs";
import * as Temple from "../";
import {rollup} from "rollup";
import inject from "@mrgalaxy/rollup-plugin-inject";
import path from "path";

const smfurl = "sourceMappingURL=";
const datauri = "data:application/json;charset=utf-8;base64,";
const rel_regex = /^\.{0,2}\//;

var toBase64;
if (typeof window !== "undefined" && typeof window.btoa === "function") {
	toBase64 = window.btoa;
} else toBase64 = function(str) {
	return new Buffer(str, "utf-8").toString("base64");
};

function parseFiles(files, { filename }) {
	if (typeof files === "string") {
		if (filename) files = { [filename]: files };
		else files = [ files ];
	}

	if (Array.isArray(files)) files = files.reduce(function(memo, src, name) {
		if (typeof name === "number") name = `template${name}.html`;
		memo[name] = src;
		return memo;
	}, {});

	return files;
}

export function parse(src, options={}) {
	try {
		return baseParse(src, options);
	} catch(e) {
		e.filename = name;
		e.source = src;
		throw e;
	}
}

function srcToString(smf) {
	return this.code + "\n\n//# " + smfurl +
		(typeof smf === "string" ? smf :
			datauri + toBase64(this.map.toString()));
}

export function compile(files, options={}, cb) {
	files = parseFiles(files, options);
	let exts = [].concat(options.extensions || ".html").filter(Boolean);
	let basedir = options.basedir || (options.filename ? path.dirname(options.filename) : ".");
	let hasCb = typeof cb === "function";
	let templates = [];

	return rollup({
		onwarn: () => {},
		entry: "_entry.js",
		plugins: [
			{
				resolveId: function(id, file) {
					if (id === "_entry.js" ||
						id === "_template.js") return id;

					let full = path.resolve(basedir, path.dirname(file), id);
					let entry = find(Object.keys(files), (name) => {
						return path.resolve(basedir, name) === full;
					});
					if (entry) return entry;

					// only relative paths are followed
					if (rel_regex.test(id) && includes(exts, path.extname(id))) {
						return full;
					}
				},
				load: function(id) {
					if (id === "_entry.js") {
						return Object.keys(files).map(name => {
							return `import ${JSON.stringify(name)}`;
						}).join("\n") + "\nexport default Template;\n";
					}

					if (id === "_template.js") {
						return "export default {};\n";
					}

					if (has(files, id)) {
						return files[id];
					}
				},
				transform: function(src, id) {
					if (!includes(exts, path.extname(id))) return;
					templates.push(id);

					let file = parse(src, assign({ filename: id }, options));
					let out = file.compile(options).toStringWithSourceMap();
					out.map = out.map.toJSON();
					return out;
				}
			},
			inject({
				Temple: "templejs",
				Template: "_template.js",
				idom: [ "templejs", "idom" ],
				decorators: [ "templejs", "decorators" ]
			})
		].concat(options.plugins).filter(Boolean)
	}).then(function(bundle) {
		let out = bundle.generate({
			format: options.format,
			sourceMap: true,
			exports: "default",
			useStrict: false,
			moduleId: options.moduleId,
			moduleName: options.moduleName,
			globals: {
				templejs: "Temple"
			}
		});

		out.templates = templates;
		out.toString = srcToString;

		return out;
	}).then((res) => {
		if (hasCb) cb(null, res);
		return res;
	}, (e) => {
		if (hasCb) cb(e);
		throw e;
	});
}

export function exec(tpl, options) {
	return compile(tpl, assign({
		format: "iife",
		moduleName: "Template"
	}, options)).then(function(r) {
		return (new Function("Temple", r.code))(Temple);
	});
}

// export function compileHTML(html, options) {
// 	options = options || {};
// 	var node = new AST.HTML(null, html);
// 	return getSource(node.compile(options), html, options);
// }
//
// export function renderHTML(html, options) {
// 	/* jshint -W054 */
// 	var r = compileHTML(html, options);
// 	// console.log(r);
// 	return (new Function("Temple", r))(require("./"));
// }
<|endoftext|>


<commit_before>var _ = require('lodash')

module.exports = function(dropName, argv, ydm) {
  var factory = ydm.drops[dropName]
  var Drop = null;
  var drop = null;

  function build() {
    if (drop) return;
    Drop = factory(argv, ydm)
    drop = new Drop()
  }

  this.canPerform = function(action) {
    var res = {}
    if (factory) {
      build()
      if (drop[action]) res.ok = true;
      else {
        res.ok = false
        res.reason = "Drop does not define "+action;
      }
    } else {
      res.ok = false
      res.reason = "Drop '"+dropName+"' has no factory. Ydm does not define a remote repository [yet]."
    }
    return res;
  }

  this.perform = function(action, cb) {
    var check = this.canPerform(action);
    if (check.ok) {
      drop[action](cb)
    } else {
      cb(null, {
        error: check.reason,
        drop: dropName,
        action: action
      });
    }
  }
}
<commit_msg>index drops before attempting performance<commit_after>var _ = require('lodash')

module.exports = function(dropName, argv, ydm) {
  ydm.indexDrops()
  var factory = ydm.drops[dropName]
  var Drop = null;
  var drop = null;

  function build() {
    if (drop) return;
    Drop = factory(argv, ydm)
    drop = new Drop()
  }

  this.canPerform = function(action) {
    var res = {}
    if (factory) {
      build()
      if (drop[action]) res.ok = true;
      else {
        res.ok = false
        res.reason = "Drop does not define "+action;
      }
    } else {
      res.ok = false
      res.reason = "Drop '"+dropName+"' has no factory. Ydm does not define a remote repository [yet]."
    }
    return res;
  }

  this.perform = function(action, cb) {
    var check = this.canPerform(action);
    if (check.ok) {
      drop[action](cb)
    } else {
      cb(null, {
        error: check.reason,
        drop: dropName,
        action: action
      });
    }
  }
}
<|endoftext|>


<commit_before>// Copyright 2013 The Obvious Corporation.

/**
 * @fileoverview Helpers made available via require('phantomjs') once package is
 * installed.
 */

var fs = require('fs')
var path = require('path')
var which = require('which')

/**
 * Where the phantom binary can be found.
 * @type {string}
 */
try {
  exports.path = path.resolve(__dirname, require('./location').location)
} catch(e) {
  // Must be running inside install script.
  exports.path = null
}

/**
 * The version of phantomjs installed by this package.
 * @type {number}
 */
exports.version = '1.9.7'

/**
 * Returns a clean path that helps avoid `which` finding bin files installed
 * by NPM for this repo.
 * @param {string} path
 * @return {string}
 */
exports.cleanPath = function (path) {
  return path
      .replace(/:[^:]*node_modules[^:]*/g, '')
      .replace(/(^|:)\.\/bin(\:|$)/g, ':')
      .replace(/^:+/, '')
      .replace(/:+$/, '')
}

// Make sure the binary is executable.  For some reason doing this inside
// install does not work correctly, likely due to some NPM step.
if (exports.path) {
  try {
    // avoid touching the binary if it's already got the correct permissions
    var st = fs.statSync(exports.path);
    var mode = st.mode | 0555;
    if (mode !== st.mode) {
      fs.chmodSync(exports.path, mode);
    }
  } catch (e) {
    // Just ignore error if we don't have permission.
    // We did our best. Likely because phantomjs was already installed.
  }
}
<commit_msg>phantomjs 2.0.0<commit_after>// Copyright 2013 The Obvious Corporation.

/**
 * @fileoverview Helpers made available via require('phantomjs') once package is
 * installed.
 */

var fs = require('fs')
var path = require('path')
var which = require('which')

/**
 * Where the phantom binary can be found.
 * @type {string}
 */
try {
  exports.path = path.resolve(__dirname, require('./location').location)
} catch(e) {
  // Must be running inside install script.
  exports.path = null
}

/**
 * The version of phantomjs installed by this package.
 * @type {number}
 */
exports.version = '2.0.0'

/**
 * Returns a clean path that helps avoid `which` finding bin files installed
 * by NPM for this repo.
 * @param {string} path
 * @return {string}
 */
exports.cleanPath = function (path) {
  return path
      .replace(/:[^:]*node_modules[^:]*/g, '')
      .replace(/(^|:)\.\/bin(\:|$)/g, ':')
      .replace(/^:+/, '')
      .replace(/:+$/, '')
}

// Make sure the binary is executable.  For some reason doing this inside
// install does not work correctly, likely due to some NPM step.
if (exports.path) {
  try {
    // avoid touching the binary if it's already got the correct permissions
    var st = fs.statSync(exports.path);
    var mode = st.mode | 0555;
    if (mode !== st.mode) {
      fs.chmodSync(exports.path, mode);
    }
  } catch (e) {
    // Just ignore error if we don't have permission.
    // We did our best. Likely because phantomjs was already installed.
  }
}
<|endoftext|>