<commit_before>(function () {

  'use strict';

  var assign = require('object-assign');
  var vary = require('vary');

  var defaults = {
    origin: '*',
    methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
    preflightContinue: false,
    optionsSuccessStatus: 204
  };

  function isString(s) {
    return typeof s === 'string' || s instanceof String;
  }

  function isOriginAllowed(origin, allowedOrigin) {
    if (Array.isArray(allowedOrigin)) {
      for (var i = 0; i < allowedOrigin.length; ++i) {
        if (isOriginAllowed(origin, allowedOrigin[i])) {
          return true;
        }
      }
      return false;
    } else if (isString(allowedOrigin)) {
      return origin === allowedOrigin;
    } else if (allowedOrigin instanceof RegExp) {
      return allowedOrigin.test(origin);
    } else {
      return !!allowedOrigin;
    }
  }

  function configureOrigin(options, req) {
    var requestOrigin = req.headers.origin,
      headers = [],
      isAllowed;

    if (!options.origin || options.origin === '*') {
      // allow any origin
      headers.push([{
        key: 'Access-Control-Allow-Origin',
        value: '*'
      }]);
    } else if (isString(options.origin)) {
      // fixed origin
      headers.push([{
        key: 'Access-Control-Allow-Origin',
        value: options.origin
      }]);
      headers.push([{
        key: 'Vary',
        value: 'Origin'
      }]);
    } else {
      isAllowed = isOriginAllowed(requestOrigin, options.origin);
      // reflect origin
      headers.push([{
        key: 'Access-Control-Allow-Origin',
        value: isAllowed ? requestOrigin : false
      }]);
      headers.push([{
        key: 'Vary',
        value: 'Origin'
      }]);
    }

    return headers;
  }

  function configureMethods(options) {
    var methods = options.methods;
    if (methods.join) {
      methods = options.methods.join(','); // .methods is an array, so turn it into a string
    }
    return {
      key: 'Access-Control-Allow-Methods',
      value: methods
    };
  }

  function configureCredentials(options) {
    if (options.credentials === true) {
      return {
        key: 'Access-Control-Allow-Credentials',
        value: 'true'
      };
    }
    return null;
  }

  function configureAllowedHeaders(options, req) {
    var allowedHeaders = options.allowedHeaders || options.headers;
    var headers = [];

    if (!allowedHeaders) {
      allowedHeaders = req.headers['access-control-request-headers']; // .headers wasn't specified, so reflect the request headers
      headers.push([{
        key: 'Vary',
        value: 'Access-Control-Request-Headers'
      }]);
    } else if (allowedHeaders.join) {
      allowedHeaders = allowedHeaders.join(','); // .headers is an array, so turn it into a string
    }
    if (allowedHeaders && allowedHeaders.length) {
      headers.push([{
        key: 'Access-Control-Allow-Headers',
        value: allowedHeaders
      }]);
    }

    return headers;
  }

  function configureExposedHeaders(options) {
    var headers = options.exposedHeaders;
    if (!headers) {
      return null;
    } else if (headers.join) {
      headers = headers.join(','); // .headers is an array, so turn it into a string
    }
    if (headers && headers.length) {
      return {
        key: 'Access-Control-Expose-Headers',
        value: headers
      };
    }
    return null;
  }

  function configureMaxAge(options) {
    var maxAge = options.maxAge && options.maxAge.toString();
    if (maxAge && maxAge.length) {
      return {
        key: 'Access-Control-Max-Age',
        value: maxAge
      };
    }
    return null;
  }

  function applyHeaders(headers, res) {
    for (var i = 0, n = headers.length; i < n; i++) {
      var header = headers[i];
      if (header) {
        if (Array.isArray(header)) {
          applyHeaders(header, res);
        } else if (header.key === 'Vary' && header.value) {
          vary(res, header.value);
        } else if (header.value) {
          res.setHeader(header.key, header.value);
        }
      }
    }
  }

  function cors(options, req, res, next) {
    var headers = [],
      method = req.method && req.method.toUpperCase && req.method.toUpperCase();

    if (method === 'OPTIONS') {
      // preflight
      headers.push(configureOrigin(options, req));
      headers.push(configureCredentials(options, req));
      headers.push(configureMethods(options, req));
      headers.push(configureAllowedHeaders(options, req));
      headers.push(configureMaxAge(options, req));
      headers.push(configureExposedHeaders(options, req));
      applyHeaders(headers, res);

      if (options.preflightContinue ) {
        next();
      } else {
        // Safari (and potentially other browsers) need content-length 0,
        //   for 204 or they just hang waiting for a body
        res.statusCode = options.optionsSuccessStatus || defaults.optionsSuccessStatus;
        res.setHeader('Content-Length', '0');
        res.end();
      }
    } else {
      // actual response
      headers.push(configureOrigin(options, req));
      headers.push(configureCredentials(options, req));
      headers.push(configureExposedHeaders(options, req));
      applyHeaders(headers, res);
      next();
    }
  }

  function middlewareWrapper(o) {
    // if options are static (either via defaults or custom options passed in), wrap in a function
    var optionsCallback = null;
    if (typeof o === 'function') {
      optionsCallback = o;
    } else {
      optionsCallback = function (req, cb) {
        cb(null, o);
      };
    }

    return function corsMiddleware(req, res, next) {
      optionsCallback(req, function (err, options) {
        if (err) {
          next(err);
        } else {
          var corsOptions = assign({}, defaults, options);
          var originCallback = null;
          if (corsOptions.origin && typeof corsOptions.origin === 'function') {
            originCallback = corsOptions.origin;
          } else if (corsOptions.origin) {
            originCallback = function (origin, cb) {
              cb(null, corsOptions.origin);
            };
          }

          if (originCallback) {
            originCallback(req.headers.origin, function (err2, origin) {
              if (err2 || !origin) {
                next(err2);
              } else {
                corsOptions.origin = origin;
                cors(corsOptions, req, res, next);
              }
            });
          } else {
            next();
          }
        }
      });
    };
  }

  // can pass either an options hash, an options delegate, or nothing
  module.exports = middlewareWrapper;

}());
<commit_msg>lint: remove unreachable code branch<commit_after>(function () {

  'use strict';

  var assign = require('object-assign');
  var vary = require('vary');

  var defaults = {
    origin: '*',
    methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
    preflightContinue: false,
    optionsSuccessStatus: 204
  };

  function isString(s) {
    return typeof s === 'string' || s instanceof String;
  }

  function isOriginAllowed(origin, allowedOrigin) {
    if (Array.isArray(allowedOrigin)) {
      for (var i = 0; i < allowedOrigin.length; ++i) {
        if (isOriginAllowed(origin, allowedOrigin[i])) {
          return true;
        }
      }
      return false;
    } else if (isString(allowedOrigin)) {
      return origin === allowedOrigin;
    } else if (allowedOrigin instanceof RegExp) {
      return allowedOrigin.test(origin);
    } else {
      return !!allowedOrigin;
    }
  }

  function configureOrigin(options, req) {
    var requestOrigin = req.headers.origin,
      headers = [],
      isAllowed;

    if (!options.origin || options.origin === '*') {
      // allow any origin
      headers.push([{
        key: 'Access-Control-Allow-Origin',
        value: '*'
      }]);
    } else if (isString(options.origin)) {
      // fixed origin
      headers.push([{
        key: 'Access-Control-Allow-Origin',
        value: options.origin
      }]);
      headers.push([{
        key: 'Vary',
        value: 'Origin'
      }]);
    } else {
      isAllowed = isOriginAllowed(requestOrigin, options.origin);
      // reflect origin
      headers.push([{
        key: 'Access-Control-Allow-Origin',
        value: isAllowed ? requestOrigin : false
      }]);
      headers.push([{
        key: 'Vary',
        value: 'Origin'
      }]);
    }

    return headers;
  }

  function configureMethods(options) {
    var methods = options.methods;
    if (methods.join) {
      methods = options.methods.join(','); // .methods is an array, so turn it into a string
    }
    return {
      key: 'Access-Control-Allow-Methods',
      value: methods
    };
  }

  function configureCredentials(options) {
    if (options.credentials === true) {
      return {
        key: 'Access-Control-Allow-Credentials',
        value: 'true'
      };
    }
    return null;
  }

  function configureAllowedHeaders(options, req) {
    var allowedHeaders = options.allowedHeaders || options.headers;
    var headers = [];

    if (!allowedHeaders) {
      allowedHeaders = req.headers['access-control-request-headers']; // .headers wasn't specified, so reflect the request headers
      headers.push([{
        key: 'Vary',
        value: 'Access-Control-Request-Headers'
      }]);
    } else if (allowedHeaders.join) {
      allowedHeaders = allowedHeaders.join(','); // .headers is an array, so turn it into a string
    }
    if (allowedHeaders && allowedHeaders.length) {
      headers.push([{
        key: 'Access-Control-Allow-Headers',
        value: allowedHeaders
      }]);
    }

    return headers;
  }

  function configureExposedHeaders(options) {
    var headers = options.exposedHeaders;
    if (!headers) {
      return null;
    } else if (headers.join) {
      headers = headers.join(','); // .headers is an array, so turn it into a string
    }
    if (headers && headers.length) {
      return {
        key: 'Access-Control-Expose-Headers',
        value: headers
      };
    }
    return null;
  }

  function configureMaxAge(options) {
    var maxAge = options.maxAge && options.maxAge.toString();
    if (maxAge && maxAge.length) {
      return {
        key: 'Access-Control-Max-Age',
        value: maxAge
      };
    }
    return null;
  }

  function applyHeaders(headers, res) {
    for (var i = 0, n = headers.length; i < n; i++) {
      var header = headers[i];
      if (header) {
        if (Array.isArray(header)) {
          applyHeaders(header, res);
        } else if (header.key === 'Vary' && header.value) {
          vary(res, header.value);
        } else if (header.value) {
          res.setHeader(header.key, header.value);
        }
      }
    }
  }

  function cors(options, req, res, next) {
    var headers = [],
      method = req.method && req.method.toUpperCase && req.method.toUpperCase();

    if (method === 'OPTIONS') {
      // preflight
      headers.push(configureOrigin(options, req));
      headers.push(configureCredentials(options, req));
      headers.push(configureMethods(options, req));
      headers.push(configureAllowedHeaders(options, req));
      headers.push(configureMaxAge(options, req));
      headers.push(configureExposedHeaders(options, req));
      applyHeaders(headers, res);

      if (options.preflightContinue ) {
        next();
      } else {
        // Safari (and potentially other browsers) need content-length 0,
        //   for 204 or they just hang waiting for a body
        res.statusCode = options.optionsSuccessStatus;
        res.setHeader('Content-Length', '0');
        res.end();
      }
    } else {
      // actual response
      headers.push(configureOrigin(options, req));
      headers.push(configureCredentials(options, req));
      headers.push(configureExposedHeaders(options, req));
      applyHeaders(headers, res);
      next();
    }
  }

  function middlewareWrapper(o) {
    // if options are static (either via defaults or custom options passed in), wrap in a function
    var optionsCallback = null;
    if (typeof o === 'function') {
      optionsCallback = o;
    } else {
      optionsCallback = function (req, cb) {
        cb(null, o);
      };
    }

    return function corsMiddleware(req, res, next) {
      optionsCallback(req, function (err, options) {
        if (err) {
          next(err);
        } else {
          var corsOptions = assign({}, defaults, options);
          var originCallback = null;
          if (corsOptions.origin && typeof corsOptions.origin === 'function') {
            originCallback = corsOptions.origin;
          } else if (corsOptions.origin) {
            originCallback = function (origin, cb) {
              cb(null, corsOptions.origin);
            };
          }

          if (originCallback) {
            originCallback(req.headers.origin, function (err2, origin) {
              if (err2 || !origin) {
                next(err2);
              } else {
                corsOptions.origin = origin;
                cors(corsOptions, req, res, next);
              }
            });
          } else {
            next();
          }
        }
      });
    };
  }

  // can pass either an options hash, an options delegate, or nothing
  module.exports = middlewareWrapper;

}());
<|endoftext|>


<commit_before>/**
 * @author Maximiliano Fierro
 * @class Ext.i18n.Bundle
 * @extends Ext.data.Store
 *
 * Bundle is used to load .properties bundle files based in language and expose the bundle's keys thru getMsg method.

        Ext.application({
        	name: 'AppTest',
            requires: ['Ext.i18n.Bundle'],

            bundle: {
                bundle: 'Application',
                lang: 'en-US',
                path: 'resources',
                noCache: true
            },

            launch: function(){
                Ext.create('Ext.panel.Panel',{
                    renderTo: Ext.getBody(),
                    tbar: Ext.create('Ext.toolbar.Toolbar',{
                        items: [{text: 'text'}]
                    }),
                    items:[{
                        height: 300,
                        html: this.bundle.getMsg('panel.html')
                    }],
                });
            }
        });

 */
Ext.define('Ext.i18n.Bundle', {
	extend: 'Ext.data.Store',
	requires: [
        'Ext.app.Application',
		'Ext.i18n.reader.Property'
	],

	//@private
	defaultLanguage: 'en-US',
	//@private
	resourceExt: '.properties',

	config: {
        autoLoad: true,
        fields: ['key', 'value'],

		/**
		 * @cfg bundle {String} bundle name for properties file. Default to message
		 */
		bundle: 'message',

		/**
		 * @cfg path {String} URI to properties files. Default to resources
		 */
		path: 'resources'

		/**
		 * @cfg lang {String} Language in the form xx-YY where:
		 *		xx: Language code (2 characters lowercase)
         *      YY: Country code (2 characters upercase).
		 * Optional. Default to browser's language. If it cannot be determined default to en-US.
		 */

		/**
		 * @cfg noCache {boolean} whether or not to disable Proxy's cache. Optional. Defaults to true.
		 */

	},

	constructor: function(config){
		config = config || {};

		var me = this,
			language = me.formatLanguageCode(config.lang || me.guessLanguage()),
			noCache = (config.noCache !== false),
			url;

		me.language = language;
		me.bundle = config.bundle || me.bundle;
		me.path = config.path || me.path;

		url = this.buildURL(language);

		delete config.lang;
		delete config.noCache;

		Ext.applyIf(config, {
			proxy:{
				type: 'ajax',
				url: url,
				noCache: noCache,
				reader: {
					type: 'property',
                    idProperty: 'key'
				},
				//avoid sending limit, start & group params to server
				getParams: Ext.emptyFn
			}
		});

		me.callParent([config]);
		me.on('load', me.onBundleLoad, me);
        me.getProxy().on('exception', this.loadParent, this, {single: true});
	},

	/**
	 * @private
	 */
	guessLanguage: function(){
		return (navigator.language || navigator.browserLanguage || navigator.userLanguage || this.defaultLanguage);
	},

	/**
	 * @method: getMsg
	 * Returns the content associated with the bundle key or {bundle key}.undefined if it is not specified.
	 * @param: key {String} Bundle key.
	 * @return: {String} The bundle key content.
	 */
	getMsg: function(key){
		var rec = this.getById(key);
		return rec ? Ext.util.Format.htmlDecode(rec.get('value')) : key + '.undefined';
	},

	/**
	 * @private
	 */
	onBundleLoad: function(store, record, success, op) {
		if(success){
			this.fireEvent('loaded');

		}
    },

	/**
	 * @private
	 */
	onProxyLoad: function(op){
		if(op.getRecords()){
			this.callParent(arguments);
		}
	},

	/**
	 * @private
	 */
	buildURL: function(language){
		var url = '';
		if (this.path) url+= this.path + '/';
		url+=this.bundle;
		if (language) url+= '_'+language;
		url+=this.resourceExt;
		return url;
	},

	/**
	 * @private
	 */
	loadParent: function(){
		this.getProxy().url = this.buildURL();
		this.load();
	},

	/**
	 * @private
	 */
	formatLanguageCode: function(lang){
		var langCodes = lang.split('-');
		langCodes[0] = (langCodes[0]) ? langCodes[0].toLowerCase() : '';
		langCodes[1] = (langCodes[1]) ? langCodes[1].toUpperCase() : '';
		return langCodes.join('-');
	}

}, function(){
    //initialize bundle before app launch
	Ext.override(Ext.app.Application, {
        onBeforeLaunch: function() {
            var me = this,
                overridden = this.onBeforeLaunch.$previous,
                ns;

            //this is solved on 4.1.2
            ns = Ext.namespace(me.name);
            if (ns) {
                ns.getApplication = function() {
                    return me;
                };
            }

            if(me.bundle){
                //configure the bundle instance and defer launch until bundle launch
                me.bundle = Ext.create('Ext.i18n.Bundle', Ext.apply({
                    listeners: {
                        loaded: function(){
                            overridden.apply(me);
                        }
                    }
                }, me.bundle));
        }else{
                me.callOverridden();
            }
        }
    });
});<commit_msg>small lint fix<commit_after>/**
 * @author Maximiliano Fierro
 * @class Ext.i18n.Bundle
 * @extends Ext.data.Store
 *
 * Bundle is used to load .properties bundle files based in language and expose the bundle's keys thru getMsg method.

        Ext.application({
            name: 'AppTest',
            requires: ['Ext.i18n.Bundle'],

            bundle: {
                bundle: 'Application',
                lang: 'en-US',
                path: 'resources',
                noCache: true
            },

            launch: function(){
                Ext.create('Ext.panel.Panel',{
                    renderTo: Ext.getBody(),
                    tbar: Ext.create('Ext.toolbar.Toolbar',{
                        items: [{text: 'text'}]
                    }),
                    items:[{
                        height: 300,
                        html: this.bundle.getMsg('panel.html')
                    }],
                });
            }
        });

 */
Ext.define('Ext.i18n.Bundle', {
	extend: 'Ext.data.Store',
	requires: [
        'Ext.app.Application',
		'Ext.i18n.reader.Property'
	],

	//@private
	defaultLanguage: 'en-US',
	//@private
	resourceExt: '.properties',

	config: {
        autoLoad: true,
        fields: ['key', 'value'],

		/**
		 * @cfg bundle {String} bundle name for properties file. Default to message
		 */
		bundle: 'message',

		/**
		 * @cfg path {String} URI to properties files. Default to resources
		 */
		path: 'resources'

		/**
		 * @cfg lang {String} Language in the form xx-YY where:
		 *		xx: Language code (2 characters lowercase)
         *      YY: Country code (2 characters upercase).
		 * Optional. Default to browser's language. If it cannot be determined default to en-US.
		 */

		/**
		 * @cfg noCache {boolean} whether or not to disable Proxy's cache. Optional. Defaults to true.
		 */

	},

	constructor: function(config){
		config = config || {};

		var me = this,
			language = me.formatLanguageCode(config.lang || me.guessLanguage()),
			noCache = (config.noCache !== false),
			url;

		me.language = language;
		me.bundle = config.bundle || me.bundle;
		me.path = config.path || me.path;

		url = this.buildURL(language);

		delete config.lang;
		delete config.noCache;

		Ext.applyIf(config, {
			proxy:{
				type: 'ajax',
				url: url,
				noCache: noCache,
				reader: {
					type: 'property',
                    idProperty: 'key'
				},
				//avoid sending limit, start & group params to server
				getParams: Ext.emptyFn
			}
		});

		me.callParent([config]);
		me.on('load', me.onBundleLoad, me);
        me.getProxy().on('exception', this.loadParent, this, {single: true});
	},

	/**
	 * @private
	 */
	guessLanguage: function(){
		return (navigator.language || navigator.browserLanguage || navigator.userLanguage || this.defaultLanguage);
	},

	/**
	 * @method: getMsg
	 * Returns the content associated with the bundle key or {bundle key}.undefined if it is not specified.
	 * @param: key {String} Bundle key.
	 * @return: {String} The bundle key content.
	 */
	getMsg: function(key){
		var rec = this.getById(key);
		return rec ? Ext.util.Format.htmlDecode(rec.get('value')) : key + '.undefined';
	},

	/**
	 * @private
	 */
	onBundleLoad: function(store, record, success, op) {
		if(success){
			this.fireEvent('loaded');

		}
    },

	/**
	 * @private
	 */
	onProxyLoad: function(op){
		if(op.getRecords()){
			this.callParent(arguments);
		}
	},

	/**
	 * @private
	 */
	buildURL: function(language){
		var url = '';
		if (this.path) url+= this.path + '/';
		url+=this.bundle;
		if (language) url+= '_'+language;
		url+=this.resourceExt;
		return url;
	},

	/**
	 * @private
	 */
	loadParent: function(){
		this.getProxy().url = this.buildURL();
		this.load();
	},

	/**
	 * @private
	 */
	formatLanguageCode: function(lang){
		var langCodes = lang.split('-');
		langCodes[0] = (langCodes[0]) ? langCodes[0].toLowerCase() : '';
		langCodes[1] = (langCodes[1]) ? langCodes[1].toUpperCase() : '';
		return langCodes.join('-');
	}

}, function(){
    //initialize bundle before app launch
	Ext.override(Ext.app.Application, {
        onBeforeLaunch: function() {
            var me = this,
                overridden = this.onBeforeLaunch.$previous,
                ns;

            //this is solved on 4.1.2
            ns = Ext.namespace(me.name);
            if (ns) {
                ns.getApplication = function() {
                    return me;
                };
            }

            if(me.bundle){
                //configure the bundle instance and defer launch until bundle launch
                me.bundle = Ext.create('Ext.i18n.Bundle', Ext.apply({
                    listeners: {
                        loaded: function(){
                            overridden.apply(me);
                        }
                    }
                }, me.bundle));
        }else{
                me.callOverridden();
            }
        }
    });
});<|endoftext|>


<commit_before>'use strict';

const restify = require('restify');
const ws281x = require('rpi-ws281x-native');
const count = require('./count');
const theme = require('./theme');
const pkg = require('../package.json');

process.on('SIGINT', function () {
  ws281x.reset();
  process.nextTick(function () { process.exit(0); });
});

function init () {
  var server = restify.createServer();

  count.init();
  theme.init(ws281x);

  server.get('/', (req, res, next) => {
    console.log('get', '/');
    res.send({
      name: neopixel,
      version: pkg.version,
      theme: theme.getLastThemeName(),
      isRunning: true
    });
  });

  server.get('/theme', (req, res, next) => {
    console.log('get', '/theme');
    res.send({
      theme: theme.getLastThemeName()
    });
  });

  server.put('/theme/:name', (req, res, next) => {
    console.log('put', '/theme/:name', req.params.name);
    if(theme.setTheme(req.params.name, count.getCount())) {
      res.status(200);
    } else {
      res.status(400);
    }
  });

  server.get('/count', (req, res, next) => {
    console.log('get', '/count');
    res.send({
      count: count.getCount()
    });
  });

  server.put('/count/:num', (req, res, next) => {
    console.log('put', '/count/:num', req.params.num);
    if (count.setCount(req.params.num)) {
      theme.setTheme(theme.getLastThemeName(), count.getCount());
      res.status(200);
    } else {
      res.status(400);
    }
  });

  server.put('/stop', (req, res, next) => {
    console.log('put', '/stop');
    res.status(200);
    theme.stop();
  });

  server.listen(8080);
  console.log('server is already started at port %s', 8080);
}

module.exports = {
  init: init
};
<commit_msg>isRunning<commit_after>'use strict';

const restify = require('restify');
const ws281x = require('rpi-ws281x-native');
const count = require('./count');
const theme = require('./theme');
const pkg = require('../package.json');

process.on('SIGINT', function () {
  ws281x.reset();
  process.nextTick(function () { process.exit(0); });
});

var isRunning = false;

function init () {
  var server = restify.createServer();

  count.init();
  theme.init(ws281x);

  server.get('/', (req, res, next) => {
    console.log('get', '/');
    res.send({
      name: neopixel,
      version: pkg.version,
      theme: theme.getLastThemeName(),
      isRunning: isRunning
    });
  });

  server.get('/theme', (req, res, next) => {
    console.log('get', '/theme');
    res.send({
      theme: theme.getLastThemeName()
    });
  });

  server.put('/theme/:name', (req, res, next) => {
    console.log('put', '/theme/:name', req.params.name);
    if(theme.setTheme(req.params.name, count.getCount())) {
      isRunning = 'theme';
      res.status(200);
    } else {
      res.status(400);
    }
  });

  server.get('/count', (req, res, next) => {
    console.log('get', '/count');
    res.send({
      count: count.getCount()
    });
  });

  server.put('/count/:num', (req, res, next) => {
    console.log('put', '/count/:num', req.params.num);
    if (count.setCount(req.params.num)) {
      if (isRunning === 'theme') {
        theme.setTheme(theme.getLastThemeName(), count.getCount());
      }
      res.status(200);
    } else {
      res.status(400);
    }
  });

  server.put('/stop', (req, res, next) => {
    console.log('put', '/stop');
    res.status(200);
    if (isRunning === 'theme') {
      theme.stop();
    }
    isRunning = false;
  });

  server.listen(8080);
  console.log('server is already started at port %s', 8080);
}

module.exports = {
  init: init
};
<|endoftext|>


<commit_before>/*
 * index.js: Top-level include for the `utile` module.
 *
 * (C) 2011, Nodejitsu Inc.
 * MIT LICENSE
 *
 */

var fs = require('fs'),
    path = require('path'),
    util = require('util');

var utile = module.exports;

//
// Extend the `utile` object with all methods from the
// core node `util` methods.
//
Object.keys(util).forEach(function (key) {
  utile[key] = util[key];
});

//
// @async {Object}
// Simple wrapper to `require('async')`.
//
utile.__defineGetter__('async', function () {
  delete utile.async;
  return utile.async = require('async');
});

//
// ### function mkdirp
// Simple wrapper to `require('mkdirp')`
//
utile.__defineGetter__('mkdirp', function () {
  delete utile.mkdirp;
  return utile.mkdirp = require('mkdirp');
});

//
// ### function rimraf
// Simple wrapper to `require('rimraf')`
//
utile.__defineGetter__('rimraf', function () {
  delete utile.rimraf;
  return utile.rimraf = require('rimraf');
});

//
// ### function cpr
// Simple wrapper to `require('ncp').ncp`
//
utile.__defineGetter__('cpr', function () {
  delete utile.cpr;
  return utile.cpr = require('ncp').ncp;
});

//
// ### @file {Object}
// Lazy-loaded `file` module
//
utile.__defineGetter__('file', function () {
  delete utile.file;
  return utile.file = require('./file');
});

//
// ### @args {Object}
// Lazy-loaded `args` module
//
utile.__defineGetter__('args', function () {
  delete utile.args;
  return utile.args = require('./args');
});

//
// ### @base64 {Object}
// Lazy-loaded `base64` object
//
utile.__defineGetter__('base64', function () {
  delete utile.base64;
  return utile.base64 = require('./base64');
});

//
// ### function rargs(_args)
// #### _args {Arguments} Original function arguments
//
// Top-level method will accept a javascript "arguments" object
// (the actual keyword "arguments" inside any scope) and return
// back an Array.
//
utile.rargs = function (_args) {
  var len = (_args || []).length,
      args = new Array(len),
      i;

  //
  // Convert the raw `_args` to a proper Array.
  //
  for (i = 0; i < len; i++) {
    args[i] = _args[i];
  }

  return args;
};

//
// ### function each (obj, iterator)
// #### @obj {Object} Object to iterate over
// #### @iterator {function} Continuation to use on each key. `function (value, key, object)`
// Iterate over the keys of an object.
//
utile.each = function (obj, iterator) {
  Object.keys(obj).forEach(function (key) {
    iterator(obj[key], key, obj);
  });
};

//
// ### function find (o)
//
//
utile.find = function (obj, pred) {
  var value, key;

  for (key in obj) {
    value = obj[key];
    if (pred(value, key)) {
      return value;
    }
  }
};

//
// ### function createPath (obj, path, value)
// ### @obj {Object} Object to insert value into
// ### @path {Array} List of nested keys to insert value at
// Retreives a value from given Object, `obj`, located at the
// nested keys, `path`.
//
utile.path = function (obj, path) {
  var key, i;

  for (i in path) {
    if (typeof obj === 'undefined') {
      return undefined;
    }

    key = path[i];
    obj = obj[key];
  }

  return obj;
};

//
// ### function createPath (obj, path, value)
// ### @obj {Object} Object to insert value into
// ### @path {Array} List of nested keys to insert value at
// ### @value {*} Value to insert into the object.
// Inserts the `value` into the given Object, `obj`, creating
// any keys in `path` along the way if necessary.
//
utile.createPath = function (obj, path, value) {
  var key, i;

  for (i in path) {
    key = path[i];
    if (!obj[key]) {
      obj[key] = ((+i + 1 === path.length) ? value : {});
    }

    obj = obj[key];
  }
};

//
// ### function mixin (target [source0, source1, ...])
// Copies enumerable properties from `source0 ... sourceN`
// onto `target` and returns the resulting object.
//
utile.mixin = function (target) {
  Array.prototype.slice.call(arguments, 1).forEach(function (o) {
    Object.keys(o).forEach(function (attr) {
      var getter = o.__lookupGetter__(attr),
          setter = o.__lookupSetter__(attr);

      if (!getter && !setter) {
        target[attr] = o[attr];
      }
      else {
        if (setter) { target.__defineSetter__(attr, setter) }
        if (getter) { target.__defineGetter__(attr, getter) }
      }
    });
  });

  return target;
};

//
// ### function capitalize (str)
// #### @str {string} String to capitalize
// Capitalizes the specified `str`.
//
utile.capitalize = function (str) {
  return str && str[0].toUpperCase() + str.slice(1);
};

//
// ### function randomString (length)
// #### @length {integer} The number of bits for the random base64 string returned to contain
// randomString returns a pseude-random ASCII string (subset)
// the return value is a string of length ⌈bits/6⌉ of characters
// from the base64 alphabet.
//
utile.randomString = function (length) {
  var chars, rand, i, ret, mod, bits;

  chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-';
  ret = '';
  // standard 4
  mod = 4;
  // default is 16
  bits = length * mod || 64;

  // in v8, Math.random() yields 32 pseudo-random bits (in spidermonkey it gives 53)
  while (bits > 0) {
    // 32-bit integer
    rand = Math.floor(Math.random() * 0x100000000);
    //we use the top bits
    for (i = 26; i > 0 && bits > 0; i -= mod, bits -= mod) {
      ret += chars[0x3F & rand >>> i];
    }
  }

  return ret;
};

//
// ### function filter (object, test)
// #### @obj {Object} Object to iterate over
// #### @pred {function} Predicate applied to each property. `function (value, key, object)`
// Returns an object with properties from `obj` which satisfy
// the predicate `pred`
//
utile.filter = function (obj, pred) {
  var copy = Array.isArray(obj) ? [] : {};
  utile.each(obj, function (val, key) {
    if (pred(val, key, obj)) {
      copy[key] = val;
    }
  });

  return copy;
};

//
// ### function requireDir (directory)
// #### @directory {string} Directory to require
// Requires all files and directories from `directory`, returning an object
// with keys being filenames (without trailing `.js`) and respective values
// being return values of `require(filename)`.
//
utile.requireDir = function (directory) {
  var result = {},
      files = fs.readdirSync(directory);

  files.forEach(function (file) {
    if (file.substr(-3) === '.js') {
      file = file.substr(0, file.length - 3);
    }
    result[file] = require(path.resolve(directory, file));
  });
  return result;
};

//
// ### function requireDirLazy (directory)
// #### @directory {string} Directory to require
// Lazily requires all files and directories from `directory`, returning an
// object with keys being filenames (without trailing `.js`) and respective
// values (getters) being return values of `require(filename)`.
//
utile.requireDirLazy = function (directory) {
  var result = {},
      files = fs.readdirSync(directory);

  files.forEach(function (file) {
    if (file.substr(-3) === '.js') {
      file = file.substr(0, file.length - 3);
    }
    result.__defineGetter__(file, function () {
      delete result[file];
      return result[file] = require(path.resolve(directory, file));
    });
  });
  return result;
};

//
// ### function clone (object)
// #### @object {Object} Object to clone
// Shallow clones the specified object.
//
utile.clone = function (object) {
  return Object.keys(object).reduce(function (obj, k) {
    obj[k] = object[k];
    return obj;
  }, {});
};
<commit_msg>[refactor fix] Optimize `utile.mixin` to use `utile.rargs`<commit_after>/*
 * index.js: Top-level include for the `utile` module.
 *
 * (C) 2011, Nodejitsu Inc.
 * MIT LICENSE
 *
 */

var fs = require('fs'),
    path = require('path'),
    util = require('util');

var utile = module.exports;

//
// Extend the `utile` object with all methods from the
// core node `util` methods.
//
Object.keys(util).forEach(function (key) {
  utile[key] = util[key];
});

//
// @async {Object}
// Simple wrapper to `require('async')`.
//
utile.__defineGetter__('async', function () {
  delete utile.async;
  return utile.async = require('async');
});

//
// ### function mkdirp
// Simple wrapper to `require('mkdirp')`
//
utile.__defineGetter__('mkdirp', function () {
  delete utile.mkdirp;
  return utile.mkdirp = require('mkdirp');
});

//
// ### function rimraf
// Simple wrapper to `require('rimraf')`
//
utile.__defineGetter__('rimraf', function () {
  delete utile.rimraf;
  return utile.rimraf = require('rimraf');
});

//
// ### function cpr
// Simple wrapper to `require('ncp').ncp`
//
utile.__defineGetter__('cpr', function () {
  delete utile.cpr;
  return utile.cpr = require('ncp').ncp;
});

//
// ### @file {Object}
// Lazy-loaded `file` module
//
utile.__defineGetter__('file', function () {
  delete utile.file;
  return utile.file = require('./file');
});

//
// ### @args {Object}
// Lazy-loaded `args` module
//
utile.__defineGetter__('args', function () {
  delete utile.args;
  return utile.args = require('./args');
});

//
// ### @base64 {Object}
// Lazy-loaded `base64` object
//
utile.__defineGetter__('base64', function () {
  delete utile.base64;
  return utile.base64 = require('./base64');
});

//
// ### function rargs(_args)
// #### _args {Arguments} Original function arguments
//
// Top-level method will accept a javascript "arguments" object
// (the actual keyword "arguments" inside any scope) and return
// back an Array.
//
utile.rargs = function (_args, slice) {
  if (!slice) {
    slice = 0;
  }

  var len = (_args || []).length,
      args = new Array(len - slice),
      i;

  //
  // Convert the raw `_args` to a proper Array.
  //
  for (i = slice; i < len; i++) {
    args[i] = _args[i];
  }

  return args;
};

//
// ### function each (obj, iterator)
// #### @obj {Object} Object to iterate over
// #### @iterator {function} Continuation to use on each key. `function (value, key, object)`
// Iterate over the keys of an object.
//
utile.each = function (obj, iterator) {
  Object.keys(obj).forEach(function (key) {
    iterator(obj[key], key, obj);
  });
};

//
// ### function find (o)
//
//
utile.find = function (obj, pred) {
  var value, key;

  for (key in obj) {
    value = obj[key];
    if (pred(value, key)) {
      return value;
    }
  }
};

//
// ### function createPath (obj, path, value)
// ### @obj {Object} Object to insert value into
// ### @path {Array} List of nested keys to insert value at
// Retreives a value from given Object, `obj`, located at the
// nested keys, `path`.
//
utile.path = function (obj, path) {
  var key, i;

  for (i in path) {
    if (typeof obj === 'undefined') {
      return undefined;
    }

    key = path[i];
    obj = obj[key];
  }

  return obj;
};

//
// ### function createPath (obj, path, value)
// ### @obj {Object} Object to insert value into
// ### @path {Array} List of nested keys to insert value at
// ### @value {*} Value to insert into the object.
// Inserts the `value` into the given Object, `obj`, creating
// any keys in `path` along the way if necessary.
//
utile.createPath = function (obj, path, value) {
  var key, i;

  for (i in path) {
    key = path[i];
    if (!obj[key]) {
      obj[key] = ((+i + 1 === path.length) ? value : {});
    }

    obj = obj[key];
  }
};

//
// ### function mixin (target [source0, source1, ...])
// Copies enumerable properties from `source0 ... sourceN`
// onto `target` and returns the resulting object.
//
utile.mixin = function (target) {
  utile.rargs(arguments, 1).forEach(function (o) {
    Object.keys(o).forEach(function (attr) {
      var getter = o.__lookupGetter__(attr),
          setter = o.__lookupSetter__(attr);

      if (!getter && !setter) {
        target[attr] = o[attr];
      }
      else {
        if (setter) { target.__defineSetter__(attr, setter) }
        if (getter) { target.__defineGetter__(attr, getter) }
      }
    });
  });

  return target;
};

//
// ### function capitalize (str)
// #### @str {string} String to capitalize
// Capitalizes the specified `str`.
//
utile.capitalize = function (str) {
  return str && str[0].toUpperCase() + str.slice(1);
};

//
// ### function randomString (length)
// #### @length {integer} The number of bits for the random base64 string returned to contain
// randomString returns a pseude-random ASCII string (subset)
// the return value is a string of length ⌈bits/6⌉ of characters
// from the base64 alphabet.
//
utile.randomString = function (length) {
  var chars, rand, i, ret, mod, bits;

  chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-';
  ret = '';
  // standard 4
  mod = 4;
  // default is 16
  bits = length * mod || 64;

  // in v8, Math.random() yields 32 pseudo-random bits (in spidermonkey it gives 53)
  while (bits > 0) {
    // 32-bit integer
    rand = Math.floor(Math.random() * 0x100000000);
    //we use the top bits
    for (i = 26; i > 0 && bits > 0; i -= mod, bits -= mod) {
      ret += chars[0x3F & rand >>> i];
    }
  }

  return ret;
};

//
// ### function filter (object, test)
// #### @obj {Object} Object to iterate over
// #### @pred {function} Predicate applied to each property. `function (value, key, object)`
// Returns an object with properties from `obj` which satisfy
// the predicate `pred`
//
utile.filter = function (obj, pred) {
  var copy = Array.isArray(obj) ? [] : {};
  utile.each(obj, function (val, key) {
    if (pred(val, key, obj)) {
      copy[key] = val;
    }
  });

  return copy;
};

//
// ### function requireDir (directory)
// #### @directory {string} Directory to require
// Requires all files and directories from `directory`, returning an object
// with keys being filenames (without trailing `.js`) and respective values
// being return values of `require(filename)`.
//
utile.requireDir = function (directory) {
  var result = {},
      files = fs.readdirSync(directory);

  files.forEach(function (file) {
    if (file.substr(-3) === '.js') {
      file = file.substr(0, file.length - 3);
    }
    result[file] = require(path.resolve(directory, file));
  });
  return result;
};

//
// ### function requireDirLazy (directory)
// #### @directory {string} Directory to require
// Lazily requires all files and directories from `directory`, returning an
// object with keys being filenames (without trailing `.js`) and respective
// values (getters) being return values of `require(filename)`.
//
utile.requireDirLazy = function (directory) {
  var result = {},
      files = fs.readdirSync(directory);

  files.forEach(function (file) {
    if (file.substr(-3) === '.js') {
      file = file.substr(0, file.length - 3);
    }
    result.__defineGetter__(file, function () {
      delete result[file];
      return result[file] = require(path.resolve(directory, file));
    });
  });
  return result;
};

//
// ### function clone (object)
// #### @object {Object} Object to clone
// Shallow clones the specified object.
//
utile.clone = function (object) {
  return Object.keys(object).reduce(function (obj, k) {
    obj[k] = object[k];
    return obj;
  }, {});
};
<|endoftext|>


<commit_before>"use strict";

/*  ------------------------------------------------------------------------ */

const [processPath, , argument = null] = process.argv.filter (x => !x.startsWith ('--'))
const verbose = process.argv.includes ('--verbose') || false
const strict  = process.argv.includes ('--strict')  || false

/*  ------------------------------------------------------------------------ */

const asTable   = require ('as-table')
    , log       = require ('ololog')
    , ansi      = require ('ansicolor').nice
    , ccxt      = require ('../../ccxt.js')

/*  ------------------------------------------------------------------------ */

const warn = log.bright.yellow.error // .error → stderr

/*  ------------------------------------------------------------------------ */

process.on ('uncaughtException',  e => { log.bright.red.error (e); process.exit (1) })
process.on ('unhandledRejection', e => { log.bright.red.error (e); process.exit (1) })

/*  ------------------------------------------------------------------------ */

let printUsage = function () {
    log ('Non-strict search: node', process.argv[1], 'symbol'.green)
    log ('Non-strict search: node', process.argv[1], 'currency'.green)
    log ('    Strict search: node', process.argv[1], '--strict', 'argument'.green)
}

if (process.argv.length < 3) {
    printUsage ()
    process.exit ()
}

/*  ------------------------------------------------------------------------ */

log ('\nLooking up for:', argument.bright, strict ? '(strict search)' : '(non-strict search)', '\n')

const checkAgainst = strict ?
    (a, b) => ((a == b.toLowerCase ()) || (a == b.toUpperCase ())) :
    (a, b) => (a.includes (b.toLowerCase ()) || a.includes (b.toUpperCase ()))

;(async function test () {

    let exchanges = await Promise.all (ccxt.exchanges.map (async id => {

        // instantiate the exchange
        let exchange = new ccxt[id] ()

        if (exchange.has.publicAPI) {

            try {

                // load markets
                await exchange.loadMarkets ()
                return exchange

            } catch (e) {

                log.red (exchange.id, e.constructor.name)
                return undefined
            }
        }
    }))

    // filter out exchanges that failed to load
    exchanges = exchanges.filter (exchange => exchange)

    log ("\n---------------------------------------------------------------\n")

    log ("Markets And Symbols:\n")

    let markets = ccxt.flatten (exchanges
        .map (exchange =>
            Object.values (exchange.markets).map (market =>
                exchange.extend (market, {
                    exchange: exchange.id[(market.active !== false) ? 'green' : 'yellow'],
                }))))
        .filter (market =>
            checkAgainst (market['symbol'], argument) ||
            checkAgainst (market['id'].toString (), argument))

    log (asTable (markets.map (market => ccxt.omit (market, [ 'info', 'limits', 'precision', 'tiers' ]))))

    log ("\n---------------------------------------------------------------\n")

    log ("Currencies:\n")

    let currencies = ccxt.flatten (exchanges
        .map (exchange =>
            Object.values (exchange.currencies).map (currency =>
                exchange.extend (currency, {
                    exchange: exchange.id[(currency.active !== false) ? 'green' : 'yellow'],
                }))))
        .filter (currency =>
            checkAgainst (currency['code'], argument) ||
            checkAgainst (currency['id'], argument))

    log (asTable (currencies.map (currency => ccxt.omit (currency, [ 'info', 'limits', 'precision' ]))))

    log ("\n---------------------------------------------------------------\n")

    // output a summary
    log (markets.length.toString ().yellow, 'markets and',
      currencies.length.toString ().yellow, "currencies\n")

}) ()
<commit_msg>a minor improvement to examples/js/seach-all-exchanges for non-strict case-insensitive searches<commit_after>"use strict";

/*  ------------------------------------------------------------------------ */

const [processPath, , argument = null] = process.argv.filter (x => !x.startsWith ('--'))
const verbose = process.argv.includes ('--verbose') || false
const strict  = process.argv.includes ('--strict')  || false

/*  ------------------------------------------------------------------------ */

const asTable   = require ('as-table')
    , log       = require ('ololog')
    , ansi      = require ('ansicolor').nice
    , ccxt      = require ('../../ccxt.js')

/*  ------------------------------------------------------------------------ */

const warn = log.bright.yellow.error // .error → stderr

/*  ------------------------------------------------------------------------ */

process.on ('uncaughtException',  e => { log.bright.red.error (e); process.exit (1) })
process.on ('unhandledRejection', e => { log.bright.red.error (e); process.exit (1) })

/*  ------------------------------------------------------------------------ */

let printUsage = function () {
    log ('Non-strict search: node', process.argv[1], 'symbol'.green)
    log ('Non-strict search: node', process.argv[1], 'currency'.green)
    log ('    Strict search: node', process.argv[1], '--strict', 'argument'.green)
}

if (process.argv.length < 3) {
    printUsage ()
    process.exit ()
}

/*  ------------------------------------------------------------------------ */

log ('\nLooking up for:', argument.bright, strict ? '(strict search)' : '(non-strict search)', '\n')

const checkAgainst = strict ?
    (a, b) => ((a == b.toLowerCase ()) || (a == b.toUpperCase ())) :
    (a, b) => a.toLowerCase ().includes (b.toLowerCase ())

;(async function test () {

    let exchanges = await Promise.all (ccxt.exchanges.map (async id => {

        // instantiate the exchange
        let exchange = new ccxt[id] ()

        if (exchange.has.publicAPI) {

            try {

                // load markets
                await exchange.loadMarkets ()
                return exchange

            } catch (e) {

                log.red (exchange.id, e.constructor.name)
                return undefined
            }
        }
    }))

    // filter out exchanges that failed to load
    exchanges = exchanges.filter (exchange => exchange)

    log ("\n---------------------------------------------------------------\n")

    log ("Markets And Symbols:\n")

    let markets = ccxt.flatten (exchanges
        .map (exchange =>
            Object.values (exchange.markets).map (market =>
                exchange.extend (market, {
                    exchange: exchange.id[(market.active !== false) ? 'green' : 'yellow'],
                }))))
        .filter (market =>
            checkAgainst (market['base'],  argument) ||
            checkAgainst (market['quote'], argument) ||
            (market['baseId']  ? checkAgainst (market['baseId'],  argument) : false) ||
            (market['quoteId'] ? checkAgainst (market['quoteId'], argument) : false) ||
            checkAgainst (market['symbol'], argument) ||
            checkAgainst (market['id'].toString (), argument))

    log (asTable (markets.map (market => ccxt.omit (market, [ 'info', 'limits', 'precision', 'tiers' ]))))

    log ("\n---------------------------------------------------------------\n")

    log ("Currencies:\n")

    let currencies = ccxt.flatten (exchanges
        .map (exchange =>
            Object.values (exchange.currencies).map (currency =>
                exchange.extend (currency, {
                    exchange: exchange.id[(currency.active !== false) ? 'green' : 'yellow'],
                }))))
        .filter (currency =>
            checkAgainst (currency['code'], argument) ||
            checkAgainst (currency['id'], argument))

    log (asTable (currencies.map (currency => ccxt.omit (currency, [ 'info', 'limits', 'precision' ]))))

    log ("\n---------------------------------------------------------------\n")

    // output a summary
    log (markets.length.toString ().yellow, 'markets and',
      currencies.length.toString ().yellow, "currencies\n")

}) ()
<|endoftext|>


<commit_before>const path = require('path');
const fs = require('fs');
const { OperationResult } = require('../../core/operation_result');
const Minio = require('minio')

const name = "APTrust S3 uploader";
const description = "Uploads files to any service that supports the S3 API.";
const version = "0.1";
const protocol = "s3";

const MAX_ATTEMPTS = 8;

class S3 {

    /**
     * Custom storage provider.
     * @constructor
     * @param {object} storageService - A storage service object describing
     * the service protocol, credentials, URL, and other info.
     * See easy/storage_service.js.
     * @param {object} emitter - An Node event object that can emit events
     * @returns {object} - A new custom storage provider.
     */
    constructor(storageService, emitter) {
        this.storageService = storageService;
        this.emitter = emitter;
        this.attemptNumber = 0;
    }

    /**
     * Returns a map with descriptive info about this provider.
     * @returns {object} - Contains descriptive info about this provider.
     */
     describe() {
         return { name: name,
                  description: description,
                  version: version,
                  protocol: protocol
                };
     }

    /**
     * Uploads a file to the storage provider. Note that because StorageService
     * includes a bucket property, the file will be uploaded into that
     * bucket/folder on the remote provider. So if StorageService.bucket is
     * 'mybucket/private', and filepath is '/home/josie/photo.jpg', the upload
     * function will create the file 'mybucket/private/photo.jpg' on the remote
     * storage provider.
     * @param {string} filepath - Absolute path to the file to be uploaded.
     */
    upload(filepath) {
        var started = false;
        var fileCount = 0;
        var uploader = this;
        this.attemptNumber += 1;
        try {
            // Can emit events: 'start', 'complete', 'uploadStart',
            // 'uploadProgress', 'uploadComplete', 'warning', 'error'
            var localStat = fs.lstatSync(filepath);
            if (localStat == null || !(localStat.isFile() || localStat.isSymbolicLink())) {
                var msg = `${filepath} is not a file`;
                uploader.emitter.emit('error', msg);
                return;
            }

            var host = uploader.storageService.host;
            var bucket = uploader.storageService.bucket;
            var objectName = path.basename(filepath);

            uploader.emitter.emit('start', `Connecting to ${host}`)

            var s3Client = uploader.getClient();
            uploader.emitter.emit('uploadStart', `Uploading ${filepath} to ${host} ${bucket}/${objectName}`)
            s3Client.fPutObject(bucket, objectName, filepath, function(err) {
                if (err) {
                    if (uploader.attemptNumber < MAX_ATTEMPTS) {
                        // ECONNRESET: Connection reset by peer is common on large uploads.
                        // Minio client is smart enough to pick up where it left off.
                        // Log a warning, wait 5 seconds, then try again.
                        uploader.emitter.emit('warning', `Got error ${err}. Will attempt to resume upload in five seconds.`)
                        setTimeout(uploader.upload, 5000);
                    } else {
                        // Too many attempts.
                        uploader.emitter.emit('complete', false, "Upload failed after ${uploader.attemptNumber} attempts. Last error: ${err}");
                    }
                    return;
                }
                // Note PT #153962363: Buckets must allow GetObject or you'll
                // get "valid credentials required" error.
                s3Client.statObject(bucket, objectName, function(err, remoteStat){
                    if (err) {
                        uploader.emitter.emit('complete', false, "After upload, could not get object stats. " + err);
                        return;
                    }
                    if (remoteStat.size != localStat.size) {
                        var msg = `Object was not correctly uploaded. Local size is ${localStat.size}, remote size is ${remoteStat.size}`;
                        uploader.emitter.emit('complete', false, msg);
                        return;
                    } else {
                        uploader.emitter.emit('uploadComplete', true, `Saved ${objectName} in ${bucket}.`);
                        uploader.emitter.emit('complete', true, `Object uploaded successfully. Size: ${remoteStat.size}, ETag: ${remoteStat.etag}`);
                    }
                });
            })
        } catch (ex) {
           // ... code ...
            console.log(typeof ex);
            console.log(ex);
            uploader.emitter.emit('complete', false, ex);
        }
    }

    list(bucket) {
        var s3Client = this.getClient();
        var stream = s3Client.listObjects(bucket, '', false);
        stream.on('data', function(obj) { console.log(obj) } )
        stream.on('error', function(err) { console.log("Error: " + err) } )
    }

    getClient() {
        var s3Client = new Minio.Client({
            endPoint:  this.storageService.host,
            accessKey: this.storageService.loginName,
            secretKey: this.storageService.loginPassword
        });
        if (this.storageService.host == 's3.amazonaws.com' && this.storageService.bucket.startsWith('aptrust.')) {
            s3Client.region = 'us-east-1';
        }
        if (this.storageService.port == parseInt(this.storageService.port, 10)) {
            s3Client.port = port;
        }
        return s3Client;
    }

    /**
     * Checks to see whether a file already exists on the storage provider.
     * @param {string} filepath - Basename of the file to check.
     * @returns {bool} - True if the file exists.
     */
    exists(filepath) {
        try {
            // ... code ...
        } catch (ex) {
           // ... code ...
        }
        return trueOrFalse;
    }
}

module.exports.Provider = S3;
module.exports.name = name;
module.exports.description = description;
module.exports.version = version;
module.exports.protocol = protocol;
<commit_msg>Better exception handling on unexpected S3 error<commit_after>const path = require('path');
const fs = require('fs');
const log = require('../../core/log');
const Minio = require('minio')
const { OperationResult } = require('../../core/operation_result');

const name = "APTrust S3 uploader";
const description = "Uploads files to any service that supports the S3 API.";
const version = "0.1";
const protocol = "s3";

const MAX_ATTEMPTS = 8;

class S3 {

    /**
     * Custom storage provider.
     * @constructor
     * @param {object} storageService - A storage service object describing
     * the service protocol, credentials, URL, and other info.
     * See easy/storage_service.js.
     * @param {object} emitter - An Node event object that can emit events
     * @returns {object} - A new custom storage provider.
     */
    constructor(storageService, emitter) {
        this.storageService = storageService;
        this.emitter = emitter;
        this.attemptNumber = 0;
    }

    /**
     * Returns a map with descriptive info about this provider.
     * @returns {object} - Contains descriptive info about this provider.
     */
     describe() {
         return { name: name,
                  description: description,
                  version: version,
                  protocol: protocol
                };
     }

    /**
     * Uploads a file to the storage provider. Note that because StorageService
     * includes a bucket property, the file will be uploaded into that
     * bucket/folder on the remote provider. So if StorageService.bucket is
     * 'mybucket/private', and filepath is '/home/josie/photo.jpg', the upload
     * function will create the file 'mybucket/private/photo.jpg' on the remote
     * storage provider.
     * @param {string} filepath - Absolute path to the file to be uploaded.
     */
    upload(filepath) {
        var started = false;
        var fileCount = 0;
        var uploader = this;
        this.attemptNumber += 1;
        try {
            // Can emit events: 'start', 'complete', 'uploadStart',
            // 'uploadProgress', 'uploadComplete', 'warning', 'error'
            var localStat = fs.lstatSync(filepath);
            if (localStat == null || !(localStat.isFile() || localStat.isSymbolicLink())) {
                var msg = `${filepath} is not a file`;
                uploader.emitter.emit('error', msg);
                return;
            }

            var host = uploader.storageService.host;
            var bucket = uploader.storageService.bucket;
            var objectName = path.basename(filepath);

            uploader.emitter.emit('start', `Connecting to ${host}`)

            var s3Client = uploader.getClient();
            uploader.emitter.emit('uploadStart', `Uploading ${filepath} to ${host} ${bucket}/${objectName}`)
            s3Client.fPutObject(bucket, objectName, filepath, function(err) {
                if (err) {
                    if (uploader.attemptNumber < MAX_ATTEMPTS) {
                        // ECONNRESET: Connection reset by peer is common on large uploads.
                        // Minio client is smart enough to pick up where it left off.
                        // Log a warning, wait 5 seconds, then try again.
                        uploader.emitter.emit('warning', `Got error ${err}. Will attempt to resume upload in five seconds.`)
                        setTimeout(uploader.upload, 5000);
                    } else {
                        // Too many attempts.
                        uploader.emitter.emit('complete', false, "Upload failed after ${uploader.attemptNumber} attempts. Last error: ${err}");
                    }
                    return;
                }
                // Note PT #153962363: Buckets must allow GetObject or you'll
                // get "valid credentials required" error.
                s3Client.statObject(bucket, objectName, function(err, remoteStat){
                    if (err) {
                        uploader.emitter.emit('complete', false, "After upload, could not get object stats. " + err);
                        return;
                    }
                    if (remoteStat.size != localStat.size) {
                        var msg = `Object was not correctly uploaded. Local size is ${localStat.size}, remote size is ${remoteStat.size}`;
                        uploader.emitter.emit('complete', false, msg);
                        return;
                    } else {
                        uploader.emitter.emit('uploadComplete', true, `Saved ${objectName} in ${bucket}.`);
                        uploader.emitter.emit('complete', true, `Object uploaded successfully. Size: ${remoteStat.size}, ETag: ${remoteStat.etag}`);
                    }
                });
            })
        } catch (ex) {
            log.error(typeof ex);
            log.error(ex);
            if (uploader && uploader.emitter) {
                uploader.emitter.emit('complete', false, ex);
            } else {
                alert(`Upload failed: ${ex.toString()}`);
            }
        }
    }

    list(bucket) {
        var s3Client = this.getClient();
        var stream = s3Client.listObjects(bucket, '', false);
        stream.on('data', function(obj) { console.log(obj) } )
        stream.on('error', function(err) { console.log("Error: " + err) } )
    }

    getClient() {
        var s3Client = new Minio.Client({
            endPoint:  this.storageService.host,
            accessKey: this.storageService.loginName,
            secretKey: this.storageService.loginPassword
        });
        if (this.storageService.host == 's3.amazonaws.com' && this.storageService.bucket.startsWith('aptrust.')) {
            s3Client.region = 'us-east-1';
        }
        if (this.storageService.port == parseInt(this.storageService.port, 10)) {
            s3Client.port = port;
        }
        return s3Client;
    }

    /**
     * Checks to see whether a file already exists on the storage provider.
     * @param {string} filepath - Basename of the file to check.
     * @returns {bool} - True if the file exists.
     */
    exists(filepath) {
        try {
            // ... code ...
        } catch (ex) {
           // ... code ...
        }
        return trueOrFalse;
    }
}

module.exports.Provider = S3;
module.exports.name = name;
module.exports.description = description;
module.exports.version = version;
module.exports.protocol = protocol;
<|endoftext|>


<commit_before>/*
 * @copyright Copyright (c) Sematext Group, Inc. - All Rights Reserved
 *
 * @licence logparser-js is free-to-use, proprietary software.
 * THIS IS PROPRIETARY SOURCE CODE OF Sematext Group, Inc. (Sematext)
 * This source code may not be copied, reverse engineered, or altered for any purpose.
 * This source code is to be used exclusively by users and customers of Sematext.
 * Please see the full license (found in LICENSE in this distribution) for details on its license and the licenses of its dependencies.
 */
'use strict'
var yaml = require('js-yaml')
var fs = require('fs')
var moment = require('moment')
var crypto = require('crypto')
var MultiLine = require('./multiLine.js')
var geoip = null
var initJobs = []

function LogParser (fileName, options, readyCallback) {
  this.ready = false
  this.readyCallback = readyCallback
  this.options = options
  this.sources = {}
  this.load(fileName || require('path').join(__dirname, '../patterns.yml'), options)
}
function initGeoIp (err, fileName) {
  if (err) {
    this.cfg.geoIPEnabled = false
    if(this.readyCallback) {
      this.readyCallback()
      this.readyCallback = null
    }
    return
  }
  if (fs.existsSync(fileName))
  {
    geoip.init(fileName, {indexCache: true, checkForUpdates: true})
    this.cfg.geoIPEnabled = true
    if (this.cfg.globalTransform)
    {
      this.cfg.globalTransform = this.cfg.globalTransform.bind({
        moment: moment,
        geoip: geoip,
        enrichGeoIp: this.enrichGeoIp
      })
    }
  } else {
    this.cfg.geoIPEnabled = false
  }
  if(this.readyCallback) {
    this.readyCallback()
    this.readyCallback = null
  }
}
LogParser.prototype = {

  load: function (name, options) {
    try {
      this.cfg = yaml.load(fs.readFileSync(name, 'utf8'))
      if (this.cfg.autohash) {
        console.log('Hashing field content enabled for field names: ' + this.cfg.autohash)
      }
      // console.log(this.cfg)
      this.patterns = this.cfg.patterns
      if (options && options.whitelist) {
        this.whitelist(options.whitelist)
      }
      if (options && options.blacklist) {
        this.blacklist(options.blacklist)
      }
      // inject modules to global transform function

      if (this.cfg.geoIP && !(process.env.GEOIP_DISABLED=='true')) {
        var fileName = (process.env.MAXMIND_DB_DIR || this.cfg.maxmindDbDir) + 'GeoIPCity.dat'
        var cbInitGeoIp = null
        try {
          geoip = require('maxmind')
          if (fs.existsSync(fileName))
          {
            initGeoIp.bind(this)(null, fileName)
            cbInitGeoIp = null
          } else {
            cbInitGeoIp = initGeoIp.bind(this)
          }
          var maxmindUpdate=require('./maxmind-update')
          this.maxmindUpdate =  maxmindUpdate(this.cfg.debug,
            (process.env.MAXMIND_DB_DIR || this.cfg.maxmindDbDir),
            cbInitGeoIp)
        } catch (err) {
          console.log(err.stack)
          if(this.readyCallback) {
            setTimeout (this.readyCallback, 0)
          }
        }
      } else {
        if (this.readyCallback)
          this.readyCallback()
      }
    } catch (e) {
      if (e.reason && e.mark) {
        console.log('Error parsing file: ' + name + ' ' + e.reason + ' line:' + e.mark.line + ' column:' + e.mark.columns)
      } else {
        console.log('Error parsing file: ' + name + ' ' + e)
      }
      this.patterns = []
      process.exit()
    } finally {
      return this.patterns
    }
  },
  whitelist: function (whitelist) {
    this.patterns = this.patterns.filter(function (e) {
      return (e.sourceName && e.sourceName.match(whitelist))
    })
  },
  blacklist: function (blacklist) {
    this.patterns = this.patterns.filter(function (e) {
      return !(e.sourceName && e.sourceName.match(blacklist))
    })
  },
  enrichGeoIp: function (parsedObject, fieldName) {
    if (!this.cfg.geoIPEnabled || !fieldName)
        return null
    if (parsedObject[fieldName]) {
      var location = geoip.getLocation(parsedObject[fieldName])
      if (location) {
        parsedObject['geoip'] = {location: [location.longitude, location.latitude], info: location}
      }
    }
  },
  getPatternsForSource: function (sourceName) {
    if (!sourceName) {
      return this.patterns // try all
    }
    var src = this.sources[sourceName]
    if (src && src.patterns) {
      return this.sources[sourceName].patterns
    }
    var exclude = []
    var include = this.patterns.filter(function (p) {
      if (sourceName && sourceName.match && sourceName.match(p.sourceName)) {
        return true
      } else {
        exclude.push(p)
      }
    })
    var patternLists = include.concat(exclude)
    // console.log('Patterns for source ' + sourceName + ' : ex:' + exclude.length + ' incl:' + include.length)
    if (!src) {
      this.sources[sourceName] = {}
    }
    this.sources[sourceName].patterns = patternLists
    return patternLists
  },
  getMultiLineReader: function (sourceName, parser) {
    if (!sourceName) {
      return this.getMultiLineReader('unknown', parser)
    }
    var src = this.sources[sourceName]
    if (src && src.reader) {
      return this.sources[sourceName].reader
    } else {
      this.sources[sourceName] = {}
      var include = this.patterns.filter(function (p) {
        if (sourceName && sourceName.match && sourceName.match(p.sourceName)) {
          return true
        }
      })
      if (include.length > 0) {
        this.sources[sourceName].reader = new MultiLine(include[0].blockStart, parser)
        return this.sources[sourceName].reader
      } else {
        this.sources[sourceName].reader = new MultiLine(/^\S+/, parser)
        return this.sources[sourceName].reader
      }
    }
  },
  hash: function hash (input) {
    var sha1 = crypto.createHash('sha1')
    sha1.update(input.toString())
    return sha1.digest('hex')
  },
  parseDate: function (strDate, dateFormat) {
    var d = null
    if (dateFormat && strDate) {
      d = moment(String(strDate).trim().replace('  ', ' '), dateFormat.trim(), true) || moment(strDate.trim().replace('  ', ' '), this.cfg.dateFormats, true)
    }
    if (d && d.isValid()) {
      return d.toDate()
    } else {
      // console.log('DATE not matched' + strDate + ' ' + dateFormat)
      return null
    }
  },
  matchPatterns: function (p, parsed, line) {
    var match = line.match(p.regex)
    if (match) {
      parsed._type = p.type
      if (p.fields && (match.length > p.fields.length)) {
        for (var i = 0; i < p.fields.length; i++) {
          var value = match[i + 1]
          if (!isNaN(value) && value !== '') {
            value = Number(value)
          }
          if (this.cfg.autohash && this.cfg.autohash.test(p.fields[i])) {
            value = this.hash(value)
          }
          parsed[p.fields[i]] = value
          if(p.fields[i] == p.geoIP) {
            this.enrichGeoIp(parsed, p.geoIP)
          }
        }
        if (parsed['ts']) {
          var timestamp = this.parseDate(parsed['ts'], p.dateFormat)
          if (timestamp) {
            parsed['@timestamp'] = timestamp
          }
        }
        if (p.transform) {
          try {
            p.transform(parsed)
          } catch (ex) {
            console.log('Error in' + p.type + '.transform():' + ex)
          }
        }
        this.enrichGeoIp (p, p.geoIP)
        // remove ts field, because Elasticsearch
        // might have problems to index it
        // it could be recognized as string or data
        // depending on its content
        delete parsed.ts
        return 1
      }
    } else {
      return 0
    }
  },
  // optimize performance, by keeping last matched pattern
  // on top if the list,
  // assuming the next line will have the same format
  bubbleUp: function (plist, pos) {
    if (pos === 0) {
      return
    }
    // remove element on pos
    var tmp = plist[0]
    plist[0] = plist[pos]
    plist[pos] = tmp
  },
  parseLine: function (line, source, cbf) {
    var br = this.getMultiLineReader(source, function (data) {
        try {
          this._parseLine(data, source, cbf)
        } catch (err) {
          // console.log('Error parsing logs from ' + source +  ': ' + err + ' originalLine: ' + line)
          cbf(err, data)
        }
    }.bind(this))
    br.add(line)
  },
  globalTransform: function (source, parsed) {
    if (this.cfg.globalTransform) {
      try {
        this.cfg.globalTransform(source, parsed)
      } catch (ex) {
        console.error('Error in gloabalTransform():' + ex)
      }
    }
  },
  _parseLine: function (line, source, cbf) {
    if (line === null || line === '') {
      cbf('empty', null)
    }
    var parsed = {}
    if (this.cfg.originalLine === true)
    {
      parsed.originalLine = line
    }
    parsed['@source'] = source
    // JSON handling
    var trimedLine=line.trim()
    if (/^\[{0,1}\{.*\}\]{0,1}$/.test(trimedLine)) {
      try {
        parsed = JSON.parse(trimedLine)
        if (!(parsed['@timestamp'])) {
          if (parsed.time && parsed.time instanceof Date) {
            parsed['@timestamp'] = parsed.time
          } else if (parsed.t && parsed.t instanceof Date) {
            parsed['@timestamp'] = parsed.t
          } else if (parsed.timestamp && parsed.task_uuid) {
              // python eliot logs
              parsed['@timestamp'] = new Date(parsed.timestamp*1000)
          }else {
            parsed['@timestamp'] = new Date()
          }
        }
        if (!parsed.message && parsed.msg) {
          parsed.message = parsed.msg
        }
        // TODO JSON GeoIP enrichment
        this.globalTransform(source, parsed)
        return cbf(null, parsed)
      } catch (ex) {
        // ignore treat as text
      }
    }
    var patternList = this.getPatternsForSource(source) || this.patterns
    for (var k in patternList) {
      var patterns = patternList[k]
      for (var i = 0; i < patterns.match.length; i++) {
        if (this.matchPatterns(patterns.match[i], parsed, line)) {
          this.bubbleUp(patternList, k)
          if (!parsed._type) {
            parsed._type = patternList[k].type
          }
          if (this.gloabalTransform) {
            this.globalTransform(source, parsed)
          }
          return cbf(null, parsed)
        }
      }
    }
    return cbf('not found', {'@timestamp': new Date(), message: line, '@source': source}
    )
  }
}

module.exports = LogParser
<commit_msg>handle error when geoip DB is not available, nodejs deprecated fs.exists function<commit_after>/*
 * @copyright Copyright (c) Sematext Group, Inc. - All Rights Reserved
 *
 * @licence logparser-js is free-to-use, proprietary software.
 * THIS IS PROPRIETARY SOURCE CODE OF Sematext Group, Inc. (Sematext)
 * This source code may not be copied, reverse engineered, or altered for any purpose.
 * This source code is to be used exclusively by users and customers of Sematext.
 * Please see the full license (found in LICENSE in this distribution) for details on its license and the licenses of its dependencies.
 */
'use strict'
var yaml = require('js-yaml')
var fs = require('fs')
var moment = require('moment')
var crypto = require('crypto')
var MultiLine = require('./multiLine.js')
var geoip = null
var initJobs = []

function LogParser (fileName, options, readyCallback) {
  this.ready = false
  this.readyCallback = readyCallback
  this.options = options
  this.sources = {}
  this.load(fileName || require('path').join(__dirname, '../patterns.yml'), options)
}
function initGeoIp (err, fileName) {
  if (err) {
    this.cfg.geoIPEnabled = false
    if(this.readyCallback) {
      this.readyCallback()
      this.readyCallback = null
    }
    return
  }
  try {
    fs.statSync(fileName)
    geoip.init(fileName, {indexCache: true, checkForUpdates: true})
    this.cfg.geoIPEnabled = true
    if (this.cfg.globalTransform)
    {
      this.cfg.globalTransform = this.cfg.globalTransform.bind({
        moment: moment,
        geoip: geoip,
        enrichGeoIp: this.enrichGeoIp
      })
    }
  } catch (fsStatError) {
    this.cfg.geoIPEnabled = false
  }
  if(this.readyCallback) {
    this.readyCallback()
    this.readyCallback = null
  }
}
LogParser.prototype = {

  load: function (name, options) {
    try {
      this.cfg = yaml.load(fs.readFileSync(name, 'utf8'))
      if (this.cfg.autohash) {
        console.log('Hashing field content enabled for field names: ' + this.cfg.autohash)
      }
      // console.log(this.cfg)
      this.patterns = this.cfg.patterns
      if (options && options.whitelist) {
        this.whitelist(options.whitelist)
      }
      if (options && options.blacklist) {
        this.blacklist(options.blacklist)
      }
      // inject modules to global transform function

      if (this.cfg.geoIP && !(process.env.GEOIP_DISABLED=='true')) {
        var fileName = (process.env.MAXMIND_DB_DIR || this.cfg.maxmindDbDir) + 'GeoIPCity.dat'
        var cbInitGeoIp = null
        try {
          geoip = require('maxmind')
          if (fs.existsSync(fileName))
          {
            initGeoIp.bind(this)(null, fileName)
            cbInitGeoIp = null
          } else {
            cbInitGeoIp = initGeoIp.bind(this)
          }
          var maxmindUpdate=require('./maxmind-update')
          this.maxmindUpdate =  maxmindUpdate(this.cfg.debug,
            (process.env.MAXMIND_DB_DIR || this.cfg.maxmindDbDir),
            cbInitGeoIp)
        } catch (err) {
          console.log(err.stack)
          if(this.readyCallback) {
            setTimeout (this.readyCallback, 0)
          }
        }
      } else {
        if (this.readyCallback)
          this.readyCallback()
      }
    } catch (e) {
      if (e.reason && e.mark) {
        console.log('Error parsing file: ' + name + ' ' + e.reason + ' line:' + e.mark.line + ' column:' + e.mark.columns)
      } else {
        console.log('Error parsing file: ' + name + ' ' + e)
      }
      this.patterns = []
      process.exit()
    } finally {
      return this.patterns
    }
  },
  whitelist: function (whitelist) {
    this.patterns = this.patterns.filter(function (e) {
      return (e.sourceName && e.sourceName.match(whitelist))
    })
  },
  blacklist: function (blacklist) {
    this.patterns = this.patterns.filter(function (e) {
      return !(e.sourceName && e.sourceName.match(blacklist))
    })
  },
  enrichGeoIp: function (parsedObject, fieldName) {
    if (!this.cfg.geoIPEnabled || !fieldName)
        return null
    if (parsedObject[fieldName]) {
      var location = geoip.getLocation(parsedObject[fieldName])
      if (location) {
        parsedObject['geoip'] = {location: [location.longitude, location.latitude], info: location}
      }
    }
  },
  getPatternsForSource: function (sourceName) {
    if (!sourceName) {
      return this.patterns // try all
    }
    var src = this.sources[sourceName]
    if (src && src.patterns) {
      return this.sources[sourceName].patterns
    }
    var exclude = []
    var include = this.patterns.filter(function (p) {
      if (sourceName && sourceName.match && sourceName.match(p.sourceName)) {
        return true
      } else {
        exclude.push(p)
      }
    })
    var patternLists = include.concat(exclude)
    // console.log('Patterns for source ' + sourceName + ' : ex:' + exclude.length + ' incl:' + include.length)
    if (!src) {
      this.sources[sourceName] = {}
    }
    this.sources[sourceName].patterns = patternLists
    return patternLists
  },
  getMultiLineReader: function (sourceName, parser) {
    if (!sourceName) {
      return this.getMultiLineReader('unknown', parser)
    }
    var src = this.sources[sourceName]
    if (src && src.reader) {
      return this.sources[sourceName].reader
    } else {
      this.sources[sourceName] = {}
      var include = this.patterns.filter(function (p) {
        if (sourceName && sourceName.match && sourceName.match(p.sourceName)) {
          return true
        }
      })
      if (include.length > 0) {
        this.sources[sourceName].reader = new MultiLine(include[0].blockStart, parser)
        return this.sources[sourceName].reader
      } else {
        this.sources[sourceName].reader = new MultiLine(/^\S+/, parser)
        return this.sources[sourceName].reader
      }
    }
  },
  hash: function hash (input) {
    var sha1 = crypto.createHash('sha1')
    sha1.update(input.toString())
    return sha1.digest('hex')
  },
  parseDate: function (strDate, dateFormat) {
    var d = null
    if (dateFormat && strDate) {
      d = moment(String(strDate).trim().replace('  ', ' '), dateFormat.trim(), true) || moment(strDate.trim().replace('  ', ' '), this.cfg.dateFormats, true)
    }
    if (d && d.isValid()) {
      return d.toDate()
    } else {
      // console.log('DATE not matched' + strDate + ' ' + dateFormat)
      return null
    }
  },
  matchPatterns: function (p, parsed, line) {
    var match = line.match(p.regex)
    if (match) {
      parsed._type = p.type
      if (p.fields && (match.length > p.fields.length)) {
        for (var i = 0; i < p.fields.length; i++) {
          var value = match[i + 1]
          if (!isNaN(value) && value !== '') {
            value = Number(value)
          }
          if (this.cfg.autohash && this.cfg.autohash.test(p.fields[i])) {
            value = this.hash(value)
          }
          parsed[p.fields[i]] = value
          if(p.fields[i] == p.geoIP) {
            this.enrichGeoIp(parsed, p.geoIP)
          }
        }
        if (parsed['ts']) {
          var timestamp = this.parseDate(parsed['ts'], p.dateFormat)
          if (timestamp) {
            parsed['@timestamp'] = timestamp
          }
        }
        if (p.transform) {
          try {
            p.transform(parsed)
          } catch (ex) {
            console.log('Error in' + p.type + '.transform():' + ex)
          }
        }
        this.enrichGeoIp (p, p.geoIP)
        // remove ts field, because Elasticsearch
        // might have problems to index it
        // it could be recognized as string or data
        // depending on its content
        delete parsed.ts
        return 1
      }
    } else {
      return 0
    }
  },
  // optimize performance, by keeping last matched pattern
  // on top if the list,
  // assuming the next line will have the same format
  bubbleUp: function (plist, pos) {
    if (pos === 0) {
      return
    }
    // remove element on pos
    var tmp = plist[0]
    plist[0] = plist[pos]
    plist[pos] = tmp
  },
  parseLine: function (line, source, cbf) {
    var br = this.getMultiLineReader(source, function (data) {
        try {
          this._parseLine(data, source, cbf)
        } catch (err) {
          // console.log('Error parsing logs from ' + source +  ': ' + err + ' originalLine: ' + line)
          cbf(err, data)
        }
    }.bind(this))
    br.add(line)
  },
  globalTransform: function (source, parsed) {
    if (this.cfg.globalTransform) {
      try {
        this.cfg.globalTransform(source, parsed)
      } catch (ex) {
        console.error('Error in gloabalTransform():' + ex)
      }
    }
  },
  _parseLine: function (line, source, cbf) {
    if (line === null || line === '') {
      cbf('empty', null)
    }
    var parsed = {}
    if (this.cfg.originalLine === true)
    {
      parsed.originalLine = line
    }
    parsed['@source'] = source
    // JSON handling
    var trimedLine=line.trim()
    if (/^\[{0,1}\{.*\}\]{0,1}$/.test(trimedLine)) {
      try {
        parsed = JSON.parse(trimedLine)
        if (!(parsed['@timestamp'])) {
          if (parsed.time && parsed.time instanceof Date) {
            parsed['@timestamp'] = parsed.time
          } else if (parsed.t && parsed.t instanceof Date) {
            parsed['@timestamp'] = parsed.t
          } else if (parsed.timestamp && parsed.task_uuid) {
              // python eliot logs
              parsed['@timestamp'] = new Date(parsed.timestamp*1000)
          }else {
            parsed['@timestamp'] = new Date()
          }
        }
        if (!parsed.message && parsed.msg) {
          parsed.message = parsed.msg
        }
        // TODO JSON GeoIP enrichment
        this.globalTransform(source, parsed)
        return cbf(null, parsed)
      } catch (ex) {
        // ignore treat as text
      }
    }
    var patternList = this.getPatternsForSource(source) || this.patterns
    for (var k in patternList) {
      var patterns = patternList[k]
      for (var i = 0; i < patterns.match.length; i++) {
        if (this.matchPatterns(patterns.match[i], parsed, line)) {
          this.bubbleUp(patternList, k)
          if (!parsed._type) {
            parsed._type = patternList[k].type
          }
          if (this.gloabalTransform) {
            this.globalTransform(source, parsed)
          }
          return cbf(null, parsed)
        }
      }
    }
    return cbf('not found', {'@timestamp': new Date(), message: line, '@source': source}
    )
  }
}

module.exports = LogParser
<|endoftext|>


<commit_before>const _ = require('lodash')
const html = require('choo/html')
const sf = require('sheetify')
const { getGameState } = require('@robotopia/choo-game')
const { checkGoals } = require('../goal-progress/goal-evaluator')
const buttonView = require('../button')
const modalView = require('../modal')
const { goalListView } = require('../goal-progress')

const prefix = sf`
  :host {
    min-width: 700px;
  }

  :host > .story-text {
    height: 80px;
    background: #dedede;
    position: relative;
    border-radius: 10px;
    padding: 15px;
    margin: 50px 0 75px 125px;
  }

  :host > .story-text:before {
    content: '';
    width: 100px;
    height: 175px;
    position: absolute;
    top: -50px;
    left: -130px;
    background: url('assets/img/rick-avatar.png');
    background-size: contain;
    background-position: center;
    background-repeat: no-repeat;
  }

  :host > .story-text:after {
     content: '';
     position: absolute;
     right: 100%;
     top: 26px;
     width: 0;
     height: 0;
     border-top: 13px solid transparent;
     border-right: 26px solid #dedede;
     border-bottom: 13px solid transparent;
  }

  :host > h1 {
    color: #03a9f4;
  }

  :host > .unlocked {
    width: 100%;
    text-align: center;
  }

  :host > .unlocked > .unlockedBlock {
    border: 5px solid #DDDDDD;
    border-radius: 20px;
    max-height: 250px;
  }

  :host > .levelButtons {
    display: flex;
    flex-direction: row;
    justify-content: center;
  }
`

const winningCondition = (gameState, { level, isStoryModalOpen }, workspace, send) => {
  if (level) {
    const game = getGameState(gameState)
    const story = level.storyModal

    const [mandatoryGoals, optionalGoals] = _.partition(level.goals, (goal) => goal.isMandatory)

    if (checkGoals({ game, workspace }, mandatoryGoals)) {
      const winModal = level.winModal

      const repeatLevelButtonHtml = buttonView({
        label: 'Restart Level',
        onClick: () => {
          send('game:loadGameState', { loadState: level.game })
        }
      })
      const nextLevelButtonHtml = getNextLevelButton(send, level)
      let unlockedHtml

      if (winModal.unlockedBlock) {
        unlockedHtml = html`

You just unlocked the ${winModal.unlockedBlock.name}-Block!

          `
      }

      if (level.onFinish) level.onFinish({ gameState, workspace })

      send('tutorial:sendEvent', {type: 'levelWon'})

      return modalView(html`

Congratulations, you finished the level!

          ${unlockedHtml}

${winModal.text}

Goals:

              ${goalListView({ goals: mandatoryGoals, game, workspace })}

Optional:

              ${goalListView({ goals: optionalGoals, game, workspace })}

            ${repeatLevelButtonHtml}
            ${nextLevelButtonHtml}

      `)
    }

    if (isStoryModalOpen) {
      const startButton = buttonView({
        label: 'Start Tutorial',
        onClick: () => send('tutorial:setDisplayStoryModal', { displayStory: false })
      })

      return modalView(html`

${level.label}

            ${story.text}

Goals:

              ${goalListView({ goals: mandatoryGoals, game, workspace })}

Optional:

              ${goalListView({ goals: optionalGoals, game, workspace })}

          ${startButton}

      `)
    }
  }
}

function getNextLevelButton (send, level) {
  return buttonView({
    label: 'Next',
    onClick: () => send('tutorial:nextLevel', (nextLocation) => {
      send('location:set', nextLocation)
    })
  })
}

module.exports = winningCondition
<commit_msg>:ant: fix: fixed rick image error<commit_after>const _ = require('lodash')
const html = require('choo/html')
const sf = require('sheetify')
const { getGameState } = require('@robotopia/choo-game')
const { checkGoals } = require('../goal-progress/goal-evaluator')
const buttonView = require('../button')
const modalView = require('../modal')
const { goalListView } = require('../goal-progress')

const prefix = sf`
  :host {
    min-width: 700px;
  }

  :host > .story-text {
    height: 80px;
    background: #dedede;
    position: relative;
    border-radius: 10px;
    padding: 15px;
    margin: 50px;
  }

  :host > h1 {
    color: #03a9f4;
  }

  :host > .unlocked {
    width: 100%;
    text-align: center;
  }

  :host > .unlocked > .unlockedBlock {
    border: 5px solid #DDDDDD;
    border-radius: 20px;
    max-height: 250px;
  }

  :host > .levelButtons {
    display: flex;
    flex-direction: row;
    justify-content: center;
  }
`

const winningCondition = (gameState, { level, isStoryModalOpen }, workspace, send) => {
  if (level) {
    const game = getGameState(gameState)
    const story = level.storyModal

    const [mandatoryGoals, optionalGoals] = _.partition(level.goals, (goal) => goal.isMandatory)

    if (checkGoals({ game, workspace }, mandatoryGoals)) {
      const winModal = level.winModal

      const repeatLevelButtonHtml = buttonView({
        label: 'Restart Level',
        onClick: () => {
          send('game:loadGameState', { loadState: level.game })
        }
      })
      const nextLevelButtonHtml = getNextLevelButton(send, level)
      let unlockedHtml

      if (winModal.unlockedBlock) {
        unlockedHtml = html`

You just unlocked the ${winModal.unlockedBlock.name}-Block!

          `
      }

      if (level.onFinish) level.onFinish({ gameState, workspace })

      send('tutorial:sendEvent', {type: 'levelWon'})

      return modalView(html`

Congratulations, you finished the level!

          ${unlockedHtml}

${winModal.text}

Goals:

              ${goalListView({ goals: mandatoryGoals, game, workspace })}

Optional:

              ${goalListView({ goals: optionalGoals, game, workspace })}

            ${repeatLevelButtonHtml}
            ${nextLevelButtonHtml}

      `)
    }

    if (isStoryModalOpen) {
      const startButton = buttonView({
        label: 'Start Tutorial',
        onClick: () => send('tutorial:setDisplayStoryModal', { displayStory: false })
      })

      return modalView(html`

${level.label}

            ${story.text}

Goals:

              ${goalListView({ goals: mandatoryGoals, game, workspace })}

Optional:

              ${goalListView({ goals: optionalGoals, game, workspace })}

          ${startButton}

      `)
    }
  }
}

function getNextLevelButton (send, level) {
  return buttonView({
    label: 'Next',
    onClick: () => send('tutorial:nextLevel', (nextLocation) => {
      send('location:set', nextLocation)
    })
  })
}

module.exports = winningCondition
<|endoftext|>