<commit_before>/*
 * HOMER 5 UI (Xenophon)
 *
 * Copyright (C) 2011-2015 Alexandr Dubovikov <alexandr.dubovikov@gmail.com>
 * Copyright (C) 2011-2015 Lorenzo Mangani <lorenzo.mangani@gmail.com> QXIP B.V.
 * License AGPL-3.0 http://opensource.org/licenses/AGPL-3.0
 *
*/

'use strict';

angular.module('homer.widgets.alarmlist', ['adf.provider'])
  .value('alarmListServiceUrl', 'api/v1/alarm/list')
  .config(function(dashboardProvider){
    dashboardProvider
      .widget('alarmlist', {
        title: 'Alarm List',
        group: 'Admin',
        name: 'alarmlist',
        description: 'Display Alarm Detections',
        templateUrl: 'js/widgets/alarmlist/alarmlist.html',
        controller: 'alarmListCtrl',
        reload: true,
        resolve: {
          alarms: function(alarmListService, config){
              return alarmListService.get();
          }
        },
        edit: {
          templateUrl: 'js/widgets/alarmlist/edit.html'
        }
      });
  })
  .service('alarmListService', function($q, $http, alarmListServiceUrl){
    return {
      get: function(){
        var deferred = $q.defer();
        $http.get(alarmListServiceUrl+"/get")
          .success(function(data){
	      // console.log('ADM-ROW_DATA');
            if (data && data.data){
	      // console.log('ADM-ROW_DATA_IN');
              deferred.resolve(data.data);
            } else {
              deferred.reject();
            }
          })
          .error(function(){
            deferred.reject();
          });

        return deferred.promise;
      },
      save: function(ldata){
        var deferred = $q.defer();
        console.log(ldata);
        $http.post(alarmListServiceUrl+"/new", ldata)
          .success(function(data){
            if (data && data.data){
              deferred.resolve(data.data);
            } else {
              deferred.reject();
            }
          })
          .error(function(){
            deferred.reject();
          });

        return deferred.promise;
      },
      update: function(ldata){
        var deferred = $q.defer();
        console.log(ldata);
        $http.post(alarmListServiceUrl+"/edit", ldata)
          .success(function(data){
            if (data && data.data){
              deferred.resolve(data.data);
            } else {
              deferred.reject();
            }
          })
          .error(function(){
            deferred.reject();
          });

        return deferred.promise;
      },
      delete: function($uid){
        var deferred = $q.defer();
        $http.delete(alarmListServiceUrl+"/delete/"+$uid)
          .success(function(data){
            if (data && data.data){
              deferred.resolve(data.data);
            } else {
              deferred.reject();
            }
          })
          .error(function(){
            deferred.reject();
          });

        return deferred.promise;
      }
    };
  })
  .controller('alarmListCtrl', [
     '$scope',
     'alarms',
     'dialogs',
     'alarmListService',
     '$timeout',
     '$window',
     'SweetAlert',
     homer.modules.core.services.profile,
     'eventbus',
     '$location',
     function($scope, alarms, dialogs, alarmListService, $timeout, $window, SweetAlert, userProfile, eventbus, $location){

	$scope.getBkgColorTable = function (status) {

			var color = "#EDFBFF";
			if(status == 1) color = "#FF8080";
                        return {
                                "background-color": color
                        }
        };

        console.log(userProfile);

	//var rowtpl='
'
	//    		+ '

'
	//    		+'
';

        var rowtpl='
'
	    		+ '

'
	    		+'
';

	$scope.gridListOptions = {
		showFooter: false,
		enableSorting: true,
		enableFiltering: true,
		multiSelect: false,
		enableRowSelection: false,
		enableSelectAll: false,
		enableRowHeaderSelection: false,
		rowTemplate: rowtpl,
		noUnselect: true
	};

	$scope.gridListOptions.rowIdentity = function(row) {
        	  return row.id;
	};

	$scope.gridListOptions.onRegisterApi = function(gridApi){
                $scope.gridApi = gridApi;
	};

	$scope.onDblClickRow = function(rowItem) {
           console.log("Double click", rowItem);
	   if(rowItem.entity.status == 1) {
		rowItem.entity.status = 0;
		var ldata = {};
                ldata['param'] = {
                    id: rowItem.entity.id,
                    status: 0
                };

                console.log(ldata);

                alarmListService.update(ldata).then(function (mdata) {
                        rowItem.entity.status = 0;
                });

	   }

	};

	$scope.showAlarm = function(localrow, event) {
	        console.log("SHOW IT");

	        var ts = localrow.entity.alarm_ts * 1000;
	        var fromDate = new Date(new Date(ts).setMinutes(new Date(ts).getMinutes() - 5 ));
	        var toDate = new Date(new Date(ts).setMinutes(new Date(ts).getMinutes() + 5 ));

	        var search_time = { from: fromDate, to: toDate};
	        console.log(search_time);

	        eventbus.broadcast(homer.modules.pages.events.setTimeRange, search_time);

	        var source_ip = localrow.entity.source_ip;

                var transaction = {
                            call: true,
                            registration: false,
                            rest: false
                };

                var search = {
                      //  user_agent: "%friendly%"
                      source_ip: source_ip
                };

                userProfile.setProfile("transaction", transaction);
                userProfile.setProfile("search", search);
                $location.path('/result');
        };

	$scope.deleteAlarm = function(rowItem, event) {

		console.log("Delete item", rowItem);
		if(rowItem.entity.status == 1) {
			rowItem.entity.status = 0;
			var ldata = {};
        	        ldata['param'] = {
                	    id: rowItem.entity.id,
	                    status: 0
        	        };

                	console.log(ldata);

	                alarmListService.update(ldata).then(function (mdata) {
        	                rowItem.entity.status = 0;
                	});
		}
		else {
			rowItem.entity.status = 1;
			var ldata = {};
        	        ldata['param'] = {
                	    id: rowItem.entity.id,
	                    status: 1
        	        };
	                alarmListService.update(ldata).then(function (mdata) {
        	                rowItem.entity.status = 1;
                	});
		}

		console.log("DELETE ALARM");
        };

	$scope.alarmValue = function( grid, rowItem ) {
		return rowItem.entity.status == 1 ? "read" : "unread";
	};

	$scope.showAgo = function( grid, rowItem ) {

		var _MS_PER_HOUR = 60 * 60;
		var d2 = new Date();
		var diffHours =  Math.floor((d2.getTime()/1000 - (rowItem.entity.alarm_ts)) / _MS_PER_HOUR);
		return diffHours;
	};

	$scope.showDateValue = function( grid, rowItem ) {
	        function pad(s) { return (s < 10) ? '0' + s : s; }
		var d = new Date(rowItem.entity.alarm_ts*1000);
		return [pad(d.getFullYear()), pad(d.getMonth()+1), d.getDate()].join('-') + ' ' + [pad(d.getHours()), pad(d.getMinutes()), pad(d.getSeconds())].join(':');
	};

	$scope.Delete = function(row) {
	          var index = $scope.gridListOptions.data.indexOf(row.entity);
        	  $scope.gridListOptions.data.splice(index, 1);
	};

	$scope.gridListOptions.columnDefs = [
		{ name: 'id', enableCellEdit: false, width: 50 },
		{ name: 'type', displayName: 'Type' },
		{ name: 'total', displayName: 'Total' },
		{ name: 'source_ip', displayName: 'Source IP' },
		{ name: 'description', displayName: 'Description' },
		{ name: 'create_date',
		  field: 'alarm_ts',
		  displayName: 'Create date' ,
		  type: 'date',
		  cellTemplate: '
{{grid.appScope.showDateValue(grid, row)}}
'
                },
		{ name: 'ago',
		  displayName: 'Age Hours' ,
		  field: 'alarm_ts',
		  width: 150,
		  cellTemplate: '
{{grid.appScope.showAgo(grid, row)}}
'
                },
		{ name: 'status',
		  displayName: 'Status',
		  type: 'boolean',
		  width: 70,
		  cellTemplate: '<button  ng-click="grid.appScope.deleteAlarm(row, $event)" class="btn btn-normal btn-danger">{{grid.appScope.alarmValue(grid, row)}}</button>'
                }

      	];

	console.log('ADM-ROW_USER');
	$scope.gridListOptions.data = alarms;
  }]);

<commit_msg>added selection for alarm list<commit_after>/*
 * HOMER 5 UI (Xenophon)
 *
 * Copyright (C) 2011-2015 Alexandr Dubovikov <alexandr.dubovikov@gmail.com>
 * Copyright (C) 2011-2015 Lorenzo Mangani <lorenzo.mangani@gmail.com> QXIP B.V.
 * License AGPL-3.0 http://opensource.org/licenses/AGPL-3.0
 *
*/

'use strict';

angular.module('homer.widgets.alarmlist', ['adf.provider'])
  .value('alarmListServiceUrl', 'api/v1/alarm/list')
  .config(function(dashboardProvider){
    dashboardProvider
      .widget('alarmlist', {
        title: 'Alarm List',
        group: 'Admin',
        name: 'alarmlist',
        description: 'Display Alarm Detections',
        templateUrl: 'js/widgets/alarmlist/alarmlist.html',
        controller: 'alarmListCtrl',
        reload: true,
        resolve: {
          alarms: function(alarmListService, config){
              return alarmListService.get();
          }
        },
        edit: {
          templateUrl: 'js/widgets/alarmlist/edit.html'
        }
      });
  })
  .service('alarmListService', function($q, $http, alarmListServiceUrl, userProfile){
    return {
      get: function($scope, config, path, query){

        var deferred = $q.defer();
        var url = alarmListServiceUrl + "/get";
	var objQuery = {};

        objQuery = alarmlistWdgt.query($scope, objQuery, userProfile);

	$http.post(url, objQuery).success(function(data) {
		//config.debugresp = JSON.stringify(data);
                if (data && data.status) {
                    var status = data.status;
                    if (status < 300) {
                        deferred.resolve(data.data);
                    } else {
                        deferred.reject(data.data);
                    }
                }
	}).error(function() {
                deferred.reject();
        });

	return deferred.promise;
      },
      save: function(ldata){
        var deferred = $q.defer();
        $http.post(alarmListServiceUrl+"/new", ldata)
          .success(function(data){
            if (data && data.data){
              deferred.resolve(data.data);
            } else {
              deferred.reject();
            }
          })
          .error(function(){
            deferred.reject();
          });

        return deferred.promise;
      },
      update: function(ldata){
        var deferred = $q.defer();
        $http.post(alarmListServiceUrl+"/edit", ldata)
          .success(function(data){
            if (data && data.data){
              deferred.resolve(data.data);
            } else {
              deferred.reject();
            }
          })
          .error(function(){
            deferred.reject();
          });

        return deferred.promise;
      },
      delete: function($uid){
        var deferred = $q.defer();
        $http.delete(alarmListServiceUrl+"/delete/"+$uid)
          .success(function(data){
            if (data && data.data){
              deferred.resolve(data.data);
            } else {
              deferred.reject();
            }
          })
          .error(function(){
            deferred.reject();
          });

        return deferred.promise;
      }
    };
  })
  .controller('alarmListCtrl', [
     '$scope',
     'alarms',
     'dialogs',
     'alarmListService',
     '$timeout',
     '$window',
     'SweetAlert',
     homer.modules.core.services.profile,
     'eventbus',
     '$location',
     function($scope, alarms, dialogs, alarmListService, $timeout, $window, SweetAlert, userProfile, eventbus, $location){

	$scope.getBkgColorTable = function (status) {

			var color = "#EDFBFF";
			if(status == 1) color = "#FF8080";
                        return {
                                "background-color": color
                        }
        };

	//var rowtpl='
'
	//    		+ '

'
	//    		+'
';

        var rowtpl='
'
	    		+ '

'
	    		+'
';

	$scope.gridListOptions = {
		showFooter: false,
		enableSorting: true,
		enableFiltering: true,
		multiSelect: false,
		enableRowSelection: false,
		enableSelectAll: false,
		enableRowHeaderSelection: false,
		rowTemplate: rowtpl,
		noUnselect: true
	};

	$scope.gridListOptions.rowIdentity = function(row) {
        	  return row.id;
	};

	$scope.gridListOptions.onRegisterApi = function(gridApi){
                $scope.gridApi = gridApi;
	};

	$scope.onDblClickRow = function(rowItem) {
           console.log("Double click", rowItem);
	   if(rowItem.entity.status == 1) {
		rowItem.entity.status = 0;
		var ldata = {};
                ldata['param'] = {
                    id: rowItem.entity.id,
                    status: 0
                };

                console.log(ldata);

                alarmListService.update(ldata).then(function (mdata) {
                        rowItem.entity.status = 0;
                });

	   }

	};

	$scope.showAlarm = function(localrow, event) {
	        console.log("SHOW IT");

	        var ts = localrow.entity.alarm_ts * 1000;
	        var fromDate = new Date(new Date(ts).setMinutes(new Date(ts).getMinutes() - 5 ));
	        var toDate = new Date(new Date(ts).setMinutes(new Date(ts).getMinutes() + 5 ));

	        var search_time = { from: fromDate, to: toDate};
	        console.log(search_time);

	        eventbus.broadcast(homer.modules.pages.events.setTimeRange, search_time);

	        var source_ip = localrow.entity.source_ip;

                var transaction = {
                            call: true,
                            registration: false,
                            rest: false
                };

                var search = {
                      //  user_agent: "%friendly%"
                      source_ip: source_ip
                };

                userProfile.setProfile("transaction", transaction);
                userProfile.setProfile("search", search);
                $location.path('/result');
        };

	$scope.deleteAlarm = function(rowItem, event) {

		console.log("Delete item", rowItem);
		if(rowItem.entity.status == 1) {
			rowItem.entity.status = 0;
			var ldata = {};
        	        ldata['param'] = {
                	    id: rowItem.entity.id,
	                    status: 0
        	        };

                	console.log(ldata);

	                alarmListService.update(ldata).then(function (mdata) {
        	                rowItem.entity.status = 0;
                	});
		}
		else {
			rowItem.entity.status = 1;
			var ldata = {};
        	        ldata['param'] = {
                	    id: rowItem.entity.id,
	                    status: 1
        	        };
	                alarmListService.update(ldata).then(function (mdata) {
        	                rowItem.entity.status = 1;
                	});
		}

		console.log("DELETE ALARM");
        };

	$scope.alarmValue = function( grid, rowItem ) {
		return rowItem.entity.status == 1 ? "read" : "unread";
	};

	$scope.showAgo = function( grid, rowItem ) {

		var _MS_PER_HOUR = 60 * 60;
		var d2 = new Date();
		var diffHours =  Math.floor((d2.getTime()/1000 - (rowItem.entity.alarm_ts)) / _MS_PER_HOUR);
		return diffHours;
	};

	$scope.showDateValue = function( grid, rowItem ) {
	        function pad(s) { return (s < 10) ? '0' + s : s; }
		var d = new Date(rowItem.entity.alarm_ts*1000);
		return [pad(d.getFullYear()), pad(d.getMonth()+1), d.getDate()].join('-') + ' ' + [pad(d.getHours()), pad(d.getMinutes()), pad(d.getSeconds())].join(':');
	};

	$scope.Delete = function(row) {
	          var index = $scope.gridListOptions.data.indexOf(row.entity);
        	  $scope.gridListOptions.data.splice(index, 1);
	};

	$scope.gridListOptions.columnDefs = [
		{ name: 'id', enableCellEdit: false, width: 50 },
		{ name: 'type', displayName: 'Type' },
		{ name: 'total', displayName: 'Total' },
		{ name: 'source_ip', displayName: 'Source IP' },
		{ name: 'description', displayName: 'Description' },
		{ name: 'create_date',
		  field: 'alarm_ts',
		  displayName: 'Create date' ,
		  type: 'date',
		  cellTemplate: '
{{grid.appScope.showDateValue(grid, row)}}
'
                },
		{ name: 'ago',
		  displayName: 'Age Hours' ,
		  field: 'alarm_ts',
		  width: 150,
		  cellTemplate: '
{{grid.appScope.showAgo(grid, row)}}
'
                },
		{ name: 'status',
		  displayName: 'Status',
		  type: 'boolean',
		  width: 70,
		  cellTemplate: '<button  ng-click="grid.appScope.deleteAlarm(row, $event)" class="btn btn-normal btn-danger">{{grid.appScope.alarmValue(grid, row)}}</button>'
                }

      	];

	$scope.gridListOptions.data = alarms;
  }]);

////////////////////////////////////////////////////////////////////////////////////////////
// Widget object
////////////////////////////////////////////////////////////////////////////////////////////
var alarmlistWdgt = {};

//==========================================================================================
// Add filters
//==========================================================================================
alarmlistWdgt.query = function($scope, query, userProfile) {

    var timedate = userProfile.getProfile("timerange");

    query.timestamp = {};

    query.timestamp.from = timedate.from.getTime();
    query.timestamp.to = timedate.to.getTime();

    query.param = {};

    query.param.limit = 30;
    //query.param.limit = $scope.config.panel.limit;
    //query.param.total = $scope.config.panel.total;

    if (typeof filters == 'object') {
        filters.forEach(function(filter) {
            var obj = {};
            obj[filter.type] = filter.value;
            filterParams.push(obj);
        });

        query.param.filter = filterParams;
    }

    return query;
};
<|endoftext|>


<commit_before>var fs = require('fs');
var path = require('path');
var spawn = require('child_process').spawn;

var browserResolve = require('browser-resolve');
var nodeResolve = require('resolve');
var detective = require('detective');
var through = require('through');
var concat = require('concat-stream');

module.exports = function (mains, opts) {
    if (!opts) opts = {};
    var cache = opts.cache;

    if (!Array.isArray(mains)) mains = [ mains ].filter(Boolean);
    mains = mains.map(function (file) {
        return typeof file === 'object' ? file : path.resolve(file);
    });

    var visited = {};
    var pending = 0;

    var output = through();

    var transforms = [].concat(opts.transform).filter(Boolean);
    var resolve = opts.resolve || browserResolve;

    var top = { id: '/', filename: '/', paths: [] };
    mains.forEach(function (main) { walk(main, top) });

    if (mains.length === 0) {
        output.pause();
        output.queue(null);
        process.nextTick(function () { output.resume() });
    }

    return output;

    function walk (id, parent, cb) {
        pending ++;

        if (id && typeof id === 'object' && typeof id.pipe === 'function') {
            return id.pipe(concat(function (src) {
                var n = Math.floor(Math.pow(16,8) * Math.random()).toString(16);
                var basedir = opts.basedir || process.cwd();
                var file = path.join(basedir, 'fake_' + n + '.js');
                var pkgfile = path.join(basedir, 'package.json');
                fs.readFile(pkgfile, function (err, pkgsrc) {
                    var pkg = {};
                    if (!err) {
                        try { pkg = JSON.parse(pkgsrc) }
                        catch (e) {};
                    }
                    var trx = getTransform(pkg);
                    applyTransforms(file, trx, src, pkg);
                });
            }));
        }

        var c = opts.cache && opts.cache[parent.id];
        var resolver = c && typeof c === 'object'
        && !Buffer.isBuffer(c) && c.deps[id]
            ? function (xid, xparent, cb) {
                cb(null, opts.cache[parent.id].deps[id]);
            }
            : resolve;
        ;

        if (opts.packageFilter) parent.packageFilter = opts.packageFilter;

        resolver(id, parent, function (err, file, pkg) {
            if (err) return output.emit('error', err);
            if (!file) return output.emit('error', new Error([
                'module not found: "' + id + '" from file ',
                parent.filename
            ].join('')));
            if (cb) cb(file);
            if (visited[file]) {
                if (--pending === 0) output.queue(null);
                return;
            }
            visited[file] = true;

            var trx = getTransform(pkg);

            if (cache && cache[file]) {
                parseDeps(file, cache[file], pkg);
            }
            else fs.readFile(file, 'utf8', function (err, src) {
                if (err) return output.emit('error', err);
                applyTransforms(file, trx, src, pkg);
            });
        }, {extensions: opts.extensions});
    }

    function getTransform (pkg) {
        var trx = [];
        if (opts.transformKey) {
            var n = pkg;
            opts.transformKey.forEach(function (key) {
                if (n && typeof n === 'object') n = n[key];
            });
            trx = [].concat(n).filter(Boolean);
        }
        return trx;
    }

    function applyTransforms (file, trx, src, pkg) {
        var isTopLevel = mains.some(function (main) {
            var m = path.relative(path.dirname(main), file);
            return m.split('/').indexOf('node_modules') < 0;
        });
        var transf = (isTopLevel ? transforms : []).concat(trx);
        if (transf.length === 0) return done();

        (function ap (trs) {
            if (trs.length === 0) return done();
            makeTransform(file, trs[0], function (err, s) {
                if (err) return output.emit('error', err);

                s.on('error', output.emit.bind(output, 'error'));
                s.pipe(concat(function (data) {
                    src = data;
                    ap(trs.slice(1));
                }));
                s.end(src);
            });
        })(transf);

        function done () {
            parseDeps(file, src, pkg);
        }
    }

    function parseDeps (file, src, pkg) {
        var deps;
        if (!Buffer.isBuffer(src) && typeof src === 'object') {
            deps = Object.keys(src.deps);
            src = src.source;
        }
        else if (opts.noParse && opts.noParse.indexOf(file) >= 0) {
            deps = [];
        }
        else if (/\.json$/.test(file)) {
            deps = [];
        }
        else {
            try { deps = detective(src) }
            catch (ex) {
                var message = ex && ex.message ? ex.message : ex;
                return output.emit('error', new Error(
                    'Parsing file ' + file + ': ' + message
                ));
            }
        }
        var p = deps.length;
        var current = { id: file, filename: file, paths: [], package: pkg };
        var resolved = {};

        deps.forEach(function (id) {
            if (opts.filter && !opts.filter(id)) {
                resolved[id] = false;
                if (--p === 0) done();
                return;
            }

            walk(id, current, function (r) {
                resolved[id] = r;
                if (--p === 0) done();
            });
        });
        if (deps.length === 0) done();

        function done () {
            var rec = {
                id: file,
                source: src,
                deps: resolved
            };
            if (mains.indexOf(file) >= 0) {
                rec.entry = true;
            }
            output.queue(rec);
            if (--pending === 0) output.queue(null);
        }
    }

    function makeTransform (file, tr, cb) {
        if (typeof tr === 'function') return cb(null, tr(file));

        var params = { basedir: path.dirname(file), extensions: opts.extensions };
        nodeResolve(tr, params, function nr (err, res, again) {
            if (err && again) return cb(err);

            if (err) {
                return fs.stat(file, function (err_, s) {
                    if (err_) return cb(err_);
                    if (!s.isFIFO()) return cb(err);

                    params.basedir = process.cwd();
                    nodeResolve(tr, params, function (e, r) {
                        nr(e, r, true)
                    });
                });
            }

            if (!res) return cb(new Error([
                'cannot find transform module ', tr,
                ' while transforming ', file
            ].join('')));

            cb(null, require(res)(file));
        });
    }
};
<commit_msg>pass extensions to browser-resolve through parent<commit_after>var fs = require('fs');
var path = require('path');
var spawn = require('child_process').spawn;

var browserResolve = require('browser-resolve');
var nodeResolve = require('resolve');
var detective = require('detective');
var through = require('through');
var concat = require('concat-stream');

module.exports = function (mains, opts) {
    if (!opts) opts = {};
    var cache = opts.cache;

    if (!Array.isArray(mains)) mains = [ mains ].filter(Boolean);
    mains = mains.map(function (file) {
        return typeof file === 'object' ? file : path.resolve(file);
    });

    var visited = {};
    var pending = 0;

    var output = through();

    var transforms = [].concat(opts.transform).filter(Boolean);
    var resolve = opts.resolve || browserResolve;

    var top = { id: '/', filename: '/', paths: [] };
    mains.forEach(function (main) { walk(main, top) });

    if (mains.length === 0) {
        output.pause();
        output.queue(null);
        process.nextTick(function () { output.resume() });
    }

    return output;

    function walk (id, parent, cb) {
        pending ++;

        if (id && typeof id === 'object' && typeof id.pipe === 'function') {
            return id.pipe(concat(function (src) {
                var n = Math.floor(Math.pow(16,8) * Math.random()).toString(16);
                var basedir = opts.basedir || process.cwd();
                var file = path.join(basedir, 'fake_' + n + '.js');
                var pkgfile = path.join(basedir, 'package.json');
                fs.readFile(pkgfile, function (err, pkgsrc) {
                    var pkg = {};
                    if (!err) {
                        try { pkg = JSON.parse(pkgsrc) }
                        catch (e) {};
                    }
                    var trx = getTransform(pkg);
                    applyTransforms(file, trx, src, pkg);
                });
            }));
        }

        var c = opts.cache && opts.cache[parent.id];
        var resolver = c && typeof c === 'object'
        && !Buffer.isBuffer(c) && c.deps[id]
            ? function (xid, xparent, cb) {
                cb(null, opts.cache[parent.id].deps[id]);
            }
            : resolve;
        ;

        if (opts.packageFilter) parent.packageFilter = opts.packageFilter;
        if (opts.extensions) parent.extensions = opts.extensions;

        resolver(id, parent, function (err, file, pkg) {
            if (err) return output.emit('error', err);
            if (!file) return output.emit('error', new Error([
                'module not found: "' + id + '" from file ',
                parent.filename
            ].join('')));
            if (cb) cb(file);
            if (visited[file]) {
                if (--pending === 0) output.queue(null);
                return;
            }
            visited[file] = true;

            var trx = getTransform(pkg);

            if (cache && cache[file]) {
                parseDeps(file, cache[file], pkg);
            }
            else fs.readFile(file, 'utf8', function (err, src) {
                if (err) return output.emit('error', err);
                applyTransforms(file, trx, src, pkg);
            });
        });
    }

    function getTransform (pkg) {
        var trx = [];
        if (opts.transformKey) {
            var n = pkg;
            opts.transformKey.forEach(function (key) {
                if (n && typeof n === 'object') n = n[key];
            });
            trx = [].concat(n).filter(Boolean);
        }
        return trx;
    }

    function applyTransforms (file, trx, src, pkg) {
        var isTopLevel = mains.some(function (main) {
            var m = path.relative(path.dirname(main), file);
            return m.split('/').indexOf('node_modules') < 0;
        });
        var transf = (isTopLevel ? transforms : []).concat(trx);
        if (transf.length === 0) return done();

        (function ap (trs) {
            if (trs.length === 0) return done();
            makeTransform(file, trs[0], function (err, s) {
                if (err) return output.emit('error', err);

                s.on('error', output.emit.bind(output, 'error'));
                s.pipe(concat(function (data) {
                    src = data;
                    ap(trs.slice(1));
                }));
                s.end(src);
            });
        })(transf);

        function done () {
            parseDeps(file, src, pkg);
        }
    }

    function parseDeps (file, src, pkg) {
        var deps;
        if (!Buffer.isBuffer(src) && typeof src === 'object') {
            deps = Object.keys(src.deps);
            src = src.source;
        }
        else if (opts.noParse && opts.noParse.indexOf(file) >= 0) {
            deps = [];
        }
        else if (/\.json$/.test(file)) {
            deps = [];
        }
        else {
            try { deps = detective(src) }
            catch (ex) {
                var message = ex && ex.message ? ex.message : ex;
                return output.emit('error', new Error(
                    'Parsing file ' + file + ': ' + message
                ));
            }
        }
        var p = deps.length;
        var current = { id: file, filename: file, paths: [], package: pkg };
        var resolved = {};

        deps.forEach(function (id) {
            if (opts.filter && !opts.filter(id)) {
                resolved[id] = false;
                if (--p === 0) done();
                return;
            }

            walk(id, current, function (r) {
                resolved[id] = r;
                if (--p === 0) done();
            });
        });
        if (deps.length === 0) done();

        function done () {
            var rec = {
                id: file,
                source: src,
                deps: resolved
            };
            if (mains.indexOf(file) >= 0) {
                rec.entry = true;
            }
            output.queue(rec);
            if (--pending === 0) output.queue(null);
        }
    }

    function makeTransform (file, tr, cb) {
        if (typeof tr === 'function') return cb(null, tr(file));

        var params = { basedir: path.dirname(file) };
        nodeResolve(tr, params, function nr (err, res, again) {
            if (err && again) return cb(err);

            if (err) {
                return fs.stat(file, function (err_, s) {
                    if (err_) return cb(err_);
                    if (!s.isFIFO()) return cb(err);

                    params.basedir = process.cwd();
                    nodeResolve(tr, params, function (e, r) {
                        nr(e, r, true)
                    });
                });
            }

            if (!res) return cb(new Error([
                'cannot find transform module ', tr,
                ' while transforming ', file
            ].join('')));

            cb(null, require(res)(file));
        });
    }
};
<|endoftext|>


<commit_before>"use strict";

var http = require("http"),
    util = require("util");

var async = require("async"),
    cors = require("cors"),
    d3 = require("d3"),
    express = require("express"),
    app = express(),
    request = require("request"),
    Canvas = require("canvas"),
    Image = Canvas.Image,
    SphericalMercator = require("sphericalmercator"),
    merc = new SphericalMercator({ size: 256 });

var PROVIDERS = require("./providers.json");

app.configure(function() {
  app.use(express.responseTime());
  app.use(express.logger());
  app.use(cors());

  http.globalAgent.maxSockets = 32;
});

app.get("/mapimg", function(req, res) {
  console.log(req.query);
  var zoom = 2,
      bbox,
      width = +req.query.w || 1500,
      height = +req.query.h || 1000,
      extent = req.query.extent.split(":", 4);

  // rewrite extent in xy order
  extent = [extent.slice(0, 2).reverse(), extent.slice(2, 4).reverse()];

  // loop until the pixel delta is larger than the desired width and height
  do {
    zoom++;
    bbox = [merc.px(extent[0], zoom), merc.px(extent[1], zoom)];
  } while (bbox[1][0] - bbox[0][0] < width || bbox[1][1] - bbox[0][1] < height);

  var tileRange = merc.xyz(merc.ll(bbox[0], zoom).concat(merc.ll(bbox[1], zoom)), zoom);

  var tiles = d3.range(tileRange.minX, tileRange.maxX + 1).map(function(x) {
    // tileRange.*Y is backward because our y coordinates start at the top
    return d3.range(tileRange.maxY, tileRange.minY + 1).map(function(y) {
      return {
        zoom: zoom,
        x: x,
        y: y
      };
    });
  });

  var providerUrl = PROVIDERS[req.query.p];

  if (!providerUrl) {
    // no such source available
    return res.send(404);
  }

  var urls = tiles.reduce(function(a, b) {
    return a.concat(b);
  }, []).map(function(x) {
    return util.format(providerUrl, x.zoom, x.x, x.y);
  });

  var tasks = urls.map(function(url) {
    return function(callback) {
      console.time(url);
      console.time(url + ".ttfb");
      var timed = false;

      request({
        url: url,
        encoding: null
      }, function(err, res, body) {
        console.timeEnd(url);

        if (err) {
          console.error(err);
        }

        if (res && res.statusCode === 200) {
          var img = new Image();
          img.src = body;

          return callback(null, img);
        } else if (res) {
          console.log(res.statusCode);
        }

        return callback();
      }).on("response", function() {
        if (!timed) {
          timed = true;
          console.timeEnd(url + ".ttfb");
        }
      });
    };
  });

  console.time("fetching tiles");

  async.parallel(tasks, function(err, results) {
    console.timeEnd("fetching tiles");

    var rows = tiles.length,
        cols = tiles[0].length;

    console.time("stitching");

    var canvas = new Canvas(tiles.length * 256, tiles[0].length * 256),
        ctx = canvas.getContext("2d");

    var x = 0,
        y = 0;
    results.forEach(function(img, i) {
      if (img) {
        ctx.drawImage(img, x, y, 256, 256);
      }

      if (i % cols === cols - 1) {
        x += 256;
        y = 0;
      } else {
        y += 256;
      }
    });

    console.timeEnd("stitching");

    console.time("scaling");

    var target = new Canvas(width, height),
        targetCtx = target.getContext("2d");

    var nw = merc.px(extent[0], zoom),
        se = merc.px(extent[1], zoom),
        startX = nw[0] % 256,
        startY = nw[1] % 256,
        sourceWidth = se[0] - nw[0],
        sourceHeight = se[1] - nw[1];

    console.log("width: %d, height: %d", width, height);
    targetCtx.drawImage(canvas, startX, startY, sourceWidth, sourceHeight, 0, 0, width, height);

    console.timeEnd("scaling");

    console.time("outputting");

    target.toBuffer(function(err, buf) {
      console.timeEnd("outputting");

      if (err) {
        console.error(err);
        return res.send(500);
      }

      res.set("Content-Type", "image/png");
      res.send(buf);
    });
  });
});

app.listen(process.env.PORT || 8080, function() {
  console.log("Listening at http://%s:%d/", this.address().address, this.address().port);
});
<commit_msg>Implement non-scaling extent/zoom stitch<commit_after>"use strict";

var TILE_SIZE = process.env.TILE_SIZE || 256,
    DEFAULT_WIDTH = process.env.DEFAULT_WIDTH || 1500,
    DEFAULT_HEIGHT = process.env.DEFAULT_HEIGHT || 1000;

var http = require("http"),
    util = require("util");

var async = require("async"),
    cors = require("cors"),
    d3 = require("d3"),
    express = require("express"),
    app = express(),
    request = require("request"),
    Canvas = require("canvas"),
    Image = Canvas.Image,
    SphericalMercator = require("sphericalmercator"),
    merc = new SphericalMercator({ size: TILE_SIZE });

var PROVIDERS = require("./providers.json");

app.configure(function() {
  app.use(express.responseTime());
  app.use(express.logger());
  app.use(cors());

  http.globalAgent.maxSockets = 32;
});

var getTilesForView = function(view) {
  var tileRange = merc.xyz(view.extent, view.zoom);

  return d3.range(tileRange.minX, tileRange.maxX + 1).map(function(x) {
    // tileRange.*Y is backward because our y coordinates start at the top
    return d3.range(tileRange.maxY, tileRange.minY + 1).map(function(y) {
      return {
        zoom: view.zoom,
        x: x,
        y: y
      };
    });
  });
};

/**
 * Determine an appropriate zoom level given an extent and desired dimensions.
 */
var getView = function(extent, width, height) {
  var zoom = 2,
      bbox;

  var bounds = [[extent[0], extent[1]], [extent[2], extent[3]]];

  // loop until the pixel delta is larger than the desired width and height
  do {
    zoom++;
    bbox = [merc.px(bounds[0], zoom), merc.px(bounds[1], zoom)];
  } while (bbox[1][0] - bbox[0][0] < width || bbox[1][1] - bbox[0][1] < height);

  return {
    extent: extent, // return the original extent, otherwise it ends up on tile boundaries
    zoom: zoom
  };
};

var getDimensionsForView = function(view) {
  var bbox = [merc.px([view.extent[0], view.extent[1]], view.zoom),
              merc.px([view.extent[2], view.extent[3]], view.zoom)];

  return {
    width: bbox[1][0] - bbox[0][0],
    height: bbox[1][1] - bbox[0][1]
  };
};

var makeTasks = function(urls) {
  return urls.map(function(url) {
    return function(callback) {
      console.time(url);
      console.time(url + ".ttfb");
      var timed = false;

      request({
        url: url,
        encoding: null
      }, function(err, res, body) {
        console.timeEnd(url);

        if (err) {
          console.error(err);
        }

        if (res && res.statusCode === 200) {
          var img = new Image();
          img.src = body;

          return callback(null, img);
        } else if (res) {
          console.log(res.statusCode);
        }

        return callback();
      }).on("response", function() {
        if (!timed) {
          timed = true;
          console.timeEnd(url + ".ttfb");
        }
      });
    };
  });
};

var makeUrls = function(providerUrl, tiles) {
  return tiles.reduce(function(a, b) {
    return a.concat(b);
  }, []).map(function(x) {
    return util.format(providerUrl, x.zoom, x.x, x.y);
  });
};

/**
 * Parse extent and attach it to the request as params.extent (as [s, w, n, e]).
 */
var parseExtent = function(req, res, next) {
  if (!req.query.extent) {
    return res.send(400, "'extent' is required");
  }

  // extract the extent
  var extent = req.query.extent.split(":", 4);

  // coerce extent coordinates into Numbers
  extent = extent.map(function(x) {
    return +x;
  });

  req.stitch = req.stitch || {};

  // rewrite coordinates in xy order
  req.stitch.extent = extent.slice(0, 2).reverse().concat(extent.slice(2, 4).reverse());

  return next();
};

var validateProvider = function(req, res, next) {
  req.stitch = req.stitch || {};
  req.stitch.providerTemplate = PROVIDERS[req.query.p];

  if (!req.stitch.providerTemplate) {
    // no such source available
    return res.send(404, "No such provider: " + req.query.p);
  }

  return next();
};

/**
 * Stitch tiles into a single image.
 *
 * @param {string} providerTemplate Provider URL template.
 * @param {Object} view Extent and zoom.
 * @param {Function} callback (Error, Canvas) callback.
 */
var stitch = function(providerTemplate, view, callback) {
  var tiles = getTilesForView(view);
  var urls = makeUrls(providerTemplate, tiles);
  var tasks = makeTasks(urls);

  var rows = tiles.length,
      cols = tiles[0].length;

  console.time("fetching tiles");

  async.parallel(tasks, function(err, results) {
    console.timeEnd("fetching tiles");

    console.time("stitching");

    var canvas = new Canvas(rows * TILE_SIZE, cols * TILE_SIZE),
        ctx = canvas.getContext("2d");

    var x = 0,
        y = 0;
    results.forEach(function(img, i) {
      if (img) {
        ctx.drawImage(img, x, y, TILE_SIZE, TILE_SIZE);
      }

      if (i % cols === cols - 1) {
        x += TILE_SIZE;
        y = 0;
      } else {
        y += TILE_SIZE;
      }
    });

    console.timeEnd("stitching");

    return callback(null, canvas);
  });
};

/**
 * Flush a canvas to a response.
 *
 * @param {Canvas} canvas Canvas to flush.
 * @param {ServerResponse} res Response to flush to.
 */
var flush = function(canvas, res) {
  console.time("outputting");

  canvas.toBuffer(function(err, buf) {
    console.timeEnd("outputting");

    if (err) {
      console.error(err);
      return res.send(500);
    }

    res.set("Content-Type", "image/png");
    return res.send(buf);
  });
};

/**
 * Crop a stitched set of tiles to the desired view, scaling as necessary.
 *
 * @param {Canvas} canvas Source canvas (width and height will be a multiple of
 * TILE_SIZE).
 * @param {Object} view Extent and zoom.
 * @param {Number} width Target width.
 * @param {Number} height Target height.
 */
var crop = function(canvas, view, width, height) {
  var target = new Canvas(width, height),
      targetCtx = target.getContext("2d");

  var nw = merc.px([view.extent[0], view.extent[1]], view.zoom),
      se = merc.px([view.extent[2], view.extent[3]], view.zoom),
      startX = nw[0] % TILE_SIZE,
      startY = nw[1] % TILE_SIZE,
      sourceWidth = se[0] - nw[0],
      sourceHeight = se[1] - nw[1];

  console.log("width: %d, height: %d", width, height);
  targetCtx.drawImage(canvas, startX, startY, sourceWidth, sourceHeight,
                              0, 0, width, height);

  return target;
};

app.get("/", validateProvider, parseExtent, function(req, res) {
  var view = {
    extent: req.stitch.extent,
    zoom: +req.query.zoom
  };

  var dims = getDimensionsForView(view);

  stitch(req.stitch.providerTemplate, view, function(err, canvas) {
    var target = crop(canvas, view, dims.width, dims.height);

    flush(target, res);
  });
});

app.get("/mapimg", validateProvider, parseExtent, function(req, res) {
  var width = +req.query.w || DEFAULT_WIDTH,
      height = +req.query.h || DEFAULT_HEIGHT;

  var view = getView(req.stitch.extent, width, height);

  stitch(req.stitch.providerTemplate, view, function(err, canvas) {
    console.time("scaling");
    var target = crop(canvas, view, width, height);
    console.timeEnd("scaling");

    flush(target, res);
  });
});

app.listen(process.env.PORT || 8080, function() {
  console.log("Listening at http://%s:%d/", this.address().address, this.address().port);
});
<|endoftext|>


<commit_before>var exec = require('child_process').exec;
var path = require('path');

const DBUS_COMMAND = "bash "+__dirname+"/dbus.sh ";
const DBUS_DEST_DEFAULT = 'org.mpris.MediaPlayer2.omxplayer';

class OmxInstance {

	constructor(options) {
		this.options = options;

		if (options && typeof options.layer === 'number') {
			this.dbusDest = DBUS_DEST_DEFAULT + '_layer' + options.layer;
			this.layer = options.layer;
			console.log('setup for layered mode');
		} else {
			this.dbusDest = DBUS_DEST_DEFAULT;
			this.layer = 0;
			console.log('not layered mode');
		}
		console.log('dbus name will be', this.dbusDest);

		exec('mkfifo omxpipe'+this.layer);

		if (options && options.progressInterval) {
			console.log('custom progress interval:', options.progressInterval);
			this.progressInterval = options.progressInterval;
		} else {
			this.progressInterval = 1000;
		}

		this.progressHandler = null;

	}

	getLayer() {
		return this.layer;
	}

	cancelProgressHandlerIfActive() {
		if (this.progressHandler) {
			clearInterval(this.progressHandler);
			console.log('progressHandler cancelled');
		}
	}

	dbusCommand (command)  {
		let merge = "bash " +__dirname+"/dbus.sh " + this.dbusDest + " " + command;
		if (command != 'getplaystatus' && command !='getvolume' && command != 'getposition') { console.log('merge:', merge); }
		return merge;
	}

	resume () {
		exec(this.dbusCommand('play'), (error, stdout, stderr) => {
			if (error) console.error('resume() error:', error);
			console.log('should play/resume/restart');
		});
	}

	pause () {
		exec(this.dbusCommand('pause'), (error, stdout, stderr) => {
			if (error) console.error('pause() error:', error);
			console.log('should pause');
		});
	}

	stop (callback) {
		exec(this.dbusCommand('stop'), (error, stdout, stderr) => {
			if (error) console.error('stop() error:', error);
			console.log('should stop');
			this.cancelProgressHandlerIfActive();
			if (callback) callback();
		});
	}

	quit (callback) {
		exec(this.dbusCommand('quit'), (error, stdout, stderr) => {
			this.cancelProgressHandlerIfActive();
			if (callback) callback();
	  });
	}

	seekRelative (offset) {
		//seek offset in seconds; relative from current position; negative values will cause a jump back;
		exec(this.dbusCommand('seek ' +Math.round(offset*1000000)), (error, stdout, stderr) => {});
	}

	setAbsolute (position) {
		//position in seconds from start; //positions larger than the duration will stop the player;
		exec(this.dbusCommand('setposition '+Math.round(position*1000000)), (error, stdout, stderr) => {});
		this.overridePosition = position*1000000;
	}

	setVolume (volume) {
		// volume range [0.0, 1.0];
		if (volume > 0 && volume < 1.0) {
			exec(this.dbusCommand('setvolume '+volume), (error, stdout, stderr) => {});
		}
	}

	setVisibility (visible) {
		let command = visible ? 'unhidevideo' : 'hidevideo';
		exec(this.dbusCommand(command), (err, stdout, stderr) => {});
	}

	setAlpha (alpha) {
		exec(this.dbusCommand('setalpha ' + alpha), (err, stdout, stderr) => {});
	}

	getCurrentPosition () {
		return new Promise( (resolve, reject) => {
			if (typeof(this.overridePosition) == 'number') {
				resolve(this.overridePosition);
				this.overridePosition = null;
			} else {
				exec(this.dbusCommand('getposition'), (error, stdout, stderr) => {
					if (error) reject();
					let position = parseInt(stdout) / 1000; // microseconds to milliseconds
					resolve(position);
				});
			}
		});
	}

	getPlayStatus () {
		return new Promise( (resolve, reject) => {
			exec(this.dbusCommand('getplaystatus'), (error, stdout, stderr) => {
				if (error) {
					console.error('error from getplaystatus:', error);
					reject(error);
				}
				if (stdout.indexOf('Playing') > -1) {
					resolve('playing');
				} else {
					resolve('paused');
				}
			});
		});
	}

	getDuration () {
		return new Promise( (resolve, reject) => {
			if (this.duration) {
				resolve(this.duration);
			} else {
				exec( this.dbusCommand('getduration'), (error, stdout, stderr) => {
					if (error) reject();

					let duration = parseInt(stdout) / 1000; // microseconds to milliseconds
					resolve(duration);
					this.duration = duration; // cache last known duration
				});
			}
		});
	}

	getVolume () {
		exec(this.dbusCommand('getvolume'), (error, stdout, stderr) => {
			if (error) return null;
			let volume = parseFloat(stdout);
			console.log('getVolume:', volume);
		});	}

	onProgress (callback) {
		console.log('add new progress handler for layer', this.layer);
		this.progressHandler = setInterval( () => {
			if (this.shouldBePlaying) {
				this.getPlayStatus()
				.then( (playStatus) => {
					if (playStatus !== 'stopped') {
						this.getCurrentPosition()
						.then( (position) => {
							this.getDuration()
							.then( (duration) => {
								callback({ position: position, duration: duration, status: playStatus });
							});
						});
					} else {
						callback({ status: playStatus });
					}
				})
				.catch( (err) => {
					console.error('error getting playStatus:', err);
					callback({ status: 'error' });
				});
			}
		}, this.progressInterval);
	}

	onStart (callback) {
		console.log('onStart event');
		if (callback) {
			callback();
		}
	}

	waitTillPlaying (callback) {
		console.log('waitTillPlaying');
		let countAttempts = 0;
		let interval;
		interval = setInterval( () => {
			countAttempts++;
			exec(this.dbusCommand('getplaystatus'), (error, stdout, stderr) => {
				if (error) {
					console.log('error on getplaystus:', error);
				} else {
					console.log('getplaystatus result after', countAttempts, ':', stdout);
					clearInterval(interval);
					callback();
				}
			});
		}, 1000);
	}

	open (path, doneCallback, holdMode) {
		console.log('OmxInstance open() for layer #', this.layer, 'holdMode?', holdMode);
		let settings = this.options || {};
		let args = [];
		let command = 'omxplayer';

		args.push('"'+path+'"');

		if (['hdmi','local','both'].indexOf(settings.audioOutput) != -1) {
			args.push('-o');
			args.push(settings.audioOutput);
		}

		if (settings.blackBackground == true) { // defaults to false
			args.push('-b');
		}

		if (settings.backgroundARGB) {
			args.push('-b0x' + settings.backgroundARGB);
		}

		if (settings.disableKeys === true) { //defaults to  false
			args.push('--no-keys')
		}

		if (settings.disableOnScreenDisplay === true) { //defaults to  false
			args.push('--no-osd')
		}

		if (settings.disableGhostbox === true) { //defaults to  false
			args.push('--no-ghost-box');
		}

		if (settings.loop === true) { // defaults to false
			args.push('--loop');
		}

		if (settings.subtitlePath && settings.subtitlePath != "" ){
			args.push('--subtitles');
			args.push('"'+settings.subtitlePath+'"');
		}

		if (settings.startAt){
			args.push('--pos');
			args.push(''+settings.startAt+'');
		}

		if (settings.layer) {
			args.push('--layer');
			args.push(settings.layer);
		}

		if (holdMode) {
			args.push('--alpha');
			args.push(0);
		}

		args.push('--dbus_name');
		args.push(this.dbusDest);

		if (settings.aspectMode) {
			args.push('--aspect-mode');
			args.push(settings.aspectMode);
		}

		let finalOpenCommand = command+' '+args.join(' ')+' < omxpipe'+this.layer;
		console.log('finalOpenCommand:', finalOpenCommand);

		if (this.shouldBePlaying) {
			console.error('omx-layers was instructed to open, but playback is (?) already in progress');
		} else {
			exec(finalOpenCommand, (error, stdout, stderr) => {
				this.cancelProgressHandlerIfActive();
				doneCallback();
				console.log('omxpipe done for layer', this.layer);
				console.log(stdout);
				this.shouldBePlaying = false;
			});
			exec(' . > omxpipe'+this.layer, (error, stdout, stderr) => {
				this.waitTillPlaying( () => {
					console.log('started ok');
					this.shouldBePlaying = true;
					this.onStart(); // apply callback
					if (holdMode) {
						console.log('holdMode ON, so immediately pause and hide');
						this.pause();
						this.setVisibility(false);
					}
				});
			});
		}

	}

}

module.exports = OmxInstance;
<commit_msg>A couple of improvements here: - waitTillPlaying uses a Promise, and rapidly counts up before failing - removed unnecessary checks for "stopped" playstatus (which never exists) - this.duration -> this.cachedDuration, for clarity - do not attempt to use an "override position"<commit_after>var exec = require('child_process').exec;
var path = require('path');

const DBUS_COMMAND = "bash "+__dirname+"/dbus.sh ";
const DBUS_DEST_DEFAULT = 'org.mpris.MediaPlayer2.omxplayer';

const MAX_START_ATTEMPTS = 300;

class OmxInstance {

	constructor(options) {
		this.options = options;

		if (options && typeof options.layer === 'number') {
			this.dbusDest = DBUS_DEST_DEFAULT + '_layer' + options.layer;
			this.layer = options.layer;
			console.log('setup for layered mode');
		} else {
			this.dbusDest = DBUS_DEST_DEFAULT;
			this.layer = 0;
			console.log('not layered mode');
		}
		console.log('dbus name will be', this.dbusDest);

		exec('mkfifo omxpipe'+this.layer);

		if (options && options.progressInterval) {
			console.log('custom progress interval:', options.progressInterval);
			this.progressInterval = options.progressInterval;
		} else {
			this.progressInterval = 1000;
		}

		this.progressHandler = null;

	}

	getLayer() {
		return this.layer;
	}

	cancelProgressHandlerIfActive() {
		if (this.progressHandler) {
			clearInterval(this.progressHandler);
			console.info('progressHandler cancelled');
		}
	}

	dbusCommand (command)  {
		let merge = "bash " +__dirname+"/dbus.sh " + this.dbusDest + " " + command;
		if (command != 'getplaystatus' && command !='getvolume' && command != 'getposition') { console.log('merge:', merge); }
		return merge;
	}

	resume () {
		exec(this.dbusCommand('play'), (error, stdout, stderr) => {
			if (error) console.error('resume() error:', error);
			console.log('should play/resume/restart');
		});
	}

	pause () {
		exec(this.dbusCommand('pause'), (error, stdout, stderr) => {
			if (error) console.error('pause() error:', error);
			console.log('should pause');
		});
	}

	stop (callback) {
		exec(this.dbusCommand('stop'), (error, stdout, stderr) => {
			if (error) console.error('stop() error:', error);
			console.log('should stop');
			this.cancelProgressHandlerIfActive();
			if (callback) callback();
		});
	}

	quit (callback) {
		exec(this.dbusCommand('quit'), (error, stdout, stderr) => {
			this.cancelProgressHandlerIfActive();
			if (callback) callback();
	  });
	}

	seekRelative (offset) {
		//seek offset in seconds; relative from current position; negative values will cause a jump back;
		exec(this.dbusCommand('seek ' +Math.round(offset*1000000)), (error, stdout, stderr) => {});
	}

	setAbsolute (position) {
		//position in seconds from start; //positions larger than the duration will stop the player;
		exec(this.dbusCommand('setposition '+Math.round(position*1000000)), (error, stdout, stderr) => {
			if (error) console.error('setAbsolute() error:', error);
		});
	}

	setVolume (volume) {
		// volume range [0.0, 1.0];
		if (volume > 0 && volume < 1.0) {
			exec(this.dbusCommand('setvolume '+volume), (error, stdout, stderr) => {});
		}
	}

	setVisibility (visible) {
		let command = visible ? 'unhidevideo' : 'hidevideo';
		exec(this.dbusCommand(command), (err, stdout, stderr) => {});
	}

	setAlpha (alpha) {
		exec(this.dbusCommand('setalpha ' + alpha), (err, stdout, stderr) => {});
	}

	getCurrentPosition () {
		return new Promise( (resolve, reject) => {
				exec(this.dbusCommand('getposition'), (error, stdout, stderr) => {
					if (error) reject();
					let position = parseInt(stdout) / 1000; // microseconds to milliseconds
					resolve(position);
				});
		});
	}

	getPlayStatus () {
		return new Promise( (resolve, reject) => {
			exec(this.dbusCommand('getplaystatus'), (error, stdout, stderr) => {
				if (error) {
					console.error('error from getplaystatus:', error);
					reject(error);
				}
				if (stdout.indexOf('Playing') > -1) {
					resolve('playing');
				} else {
					resolve('paused');
				}
			});
		});
	}

	getDuration () {
		return new Promise( (resolve, reject) => {
			if (this.cachedDuration) {
				resolve(this.cachedDuration);
			} else {
				exec( this.dbusCommand('getduration'), (error, stdout, stderr) => {
					if (error) reject();

					let duration = parseInt(stdout) / 1000; // microseconds to milliseconds
					resolve(duration);
					this.cachedDuration = duration; // cache last known duration
				});
			}
		});
	}

	getVolume () {
		exec(this.dbusCommand('getvolume'), (error, stdout, stderr) => {
			if (error) return null;
			let volume = parseFloat(stdout);
			console.log('getVolume:', volume);
		});	}

	onProgress (callback) {
		console.log('add new progress handler for layer', this.layer);
		this.progressHandler = setInterval( () => {
			if (this.shouldBePlaying) {
				this.getPlayStatus()
				.then( (playStatus) => {
					this.getCurrentPosition()
					.then( (position) => {
						this.getDuration()
						.then( (duration) => {
							callback({ position: position, duration: duration, status: playStatus });
						});
					});
				})
				.catch( (err) => {
					console.error('error getting playStatus:', err);
					callback({ status: 'error' });
				});
			}
		}, this.progressInterval);
	}

	onStart (callback) {
		console.log('onStart event');
		if (callback) {
			callback();
		}
	}

	waitTillPlaying (callback) {
		console.log('waitTillPlaying()');
		return new Promise( (resolve, reject) => {
			let countAttempts = 0;
			let interval = setInterval( () => {
				countAttempts++;
				exec(this.dbusCommand('getplaystatus'), (error, stdout, stderr) => {
					if (error) {
						if (countAttempts > MAX_START_ATTEMPTS) {
							console.error(`too many attempts (${countAttempts}) to get playstatus after start!`);
							clearInterval(interval);
							reject(error);
						}
					} else {
						console.info(`getplaystatus success after ${countAttempts} attempts: ${stdout}`);
						clearInterval(interval);
						resolve();
					}
				});
			}, 10);
		});
	}

	open (path, doneCallback, holdMode) {
		console.log('OmxInstance open() for layer #', this.layer, 'holdMode?', holdMode);
		let settings = this.options || {};
		let args = [];
		let command = 'omxplayer';

		args.push('"'+path+'"');

		if (['hdmi','local','both'].indexOf(settings.audioOutput) != -1) {
			args.push('-o');
			args.push(settings.audioOutput);
		}

		if (settings.blackBackground == true) { // defaults to false
			args.push('-b');
		}

		if (settings.backgroundARGB) {
			args.push('-b0x' + settings.backgroundARGB);
		}

		if (settings.disableKeys === true) { //defaults to  false
			args.push('--no-keys')
		}

		if (settings.disableOnScreenDisplay === true) { //defaults to  false
			args.push('--no-osd')
		}

		if (settings.disableGhostbox === true) { //defaults to  false
			args.push('--no-ghost-box');
		}

		if (settings.loop === true) { // defaults to false
			args.push('--loop');
		}

		if (settings.subtitlePath && settings.subtitlePath != "" ){
			args.push('--subtitles');
			args.push('"'+settings.subtitlePath+'"');
		}

		if (settings.startAt){
			args.push('--pos');
			args.push(''+settings.startAt+'');
		}

		if (settings.layer) {
			args.push('--layer');
			args.push(settings.layer);
		}

		if (holdMode) {
			args.push('--alpha');
			args.push(0);
		}

		args.push('--dbus_name');
		args.push(this.dbusDest);

		if (settings.aspectMode) {
			args.push('--aspect-mode');
			args.push(settings.aspectMode);
		}

		let finalOpenCommand = command+' '+args.join(' ')+' < omxpipe'+this.layer;
		console.log('finalOpenCommand:', finalOpenCommand);

		if (this.shouldBePlaying) {
			console.error('omx-layers was instructed to open, but playback is (?) already in progress');
		} else {
			exec(finalOpenCommand, (error, stdout, stderr) => {
				this.cancelProgressHandlerIfActive();
				doneCallback();
				console.log('omxpipe done for layer', this.layer);
				console.log(stdout);
				this.shouldBePlaying = false;
				this.cachedDuration = null;
			});
			exec(' . > omxpipe'+this.layer, (error, stdout, stderr) => {
				this.waitTillPlaying()
					.then( () => {
						console.info('confirmed started ok');
						this.shouldBePlaying = true;
						this.onStart(); // apply callback
						if (holdMode) {
							console.log('holdMode ON, so immediately pause and hide');
							this.pause();
							this.setVisibility(false);
						}
					})
					.catch ( () => {
						console.error('failed to confirm clip start!');
					});
			});
		}

	}

}

module.exports = OmxInstance;
<|endoftext|>


<commit_before>'use strict'

var join = require('path').join
var EventEmitter = require('events')

var pull = require('pull-stream')
var ref = require('ssb-ref')
var ssbKeys = require('ssb-keys')

var u = require('./util')

function isString (s) {
  return typeof s === 'string'
}

function errorCB (err) {
  if (err) throw err
}

module.exports = function (_, opts, keys, path) {
  //_ was legacy db. removed that, but for backwards compatibilty reasons do not change interface
  path = path || _db.location

  keys = keys || ssbKeys.generate()

  var db = require('./db')(join(opts.path || path, 'flume'), keys, opts)

  // UGLY HACK, but...
  // fairly sure that something up the stack expects ssb to be an event emitter.
  db.__proto__ = new EventEmitter() // eslint-disable-line

  db.opts = opts

  var _get = db.get

  db.get = function (key, cb) {
    let isPrivate = false
    let unbox
    if (typeof key === 'object') {
      isPrivate = key.private === true
      unbox = key.unbox
      key = key.id
    }

    if (ref.isMsg(key)) {
      return db.keys.get(key, function (err, data) {
        if (err) return cb(err)

        if (isPrivate && unbox) {
          data = db.unbox(data, unbox)
        }

        let result

        if (isPrivate) {
          result = data.value
        } else {
          result = u.originalValue(data.value)
        }

        cb(null, result)
      })
    } else if (ref.isMsgLink(key)) {
      var link = ref.parseLink(key)
      return db.get({
        id: link.link,
        private: true,
        unbox: link.query.unbox.replace(/\s/g, '+')
      }, cb)
    } else if (Number.isInteger(key)) {
      _get(key, cb) // seq
    } else {
      throw new Error('ssb-db.get: key *must* be a ssb message id or a flume offset')
    }
  }

  db.add = function (msg, cb) {
    db.queue(msg, function (err, data) {
      if (err) cb(err)
      else db.flush(function () { cb(null, data) })
    })
  }

  db.createFeed = function (keys) {
    if (!keys) keys = ssbKeys.generate()
    function add (content, cb) {
      // LEGACY: hacks to support add as a continuable
      if (!cb) { return function (cb) { add(content, cb) } }

      db.append({ content: content, keys: keys }, cb)
    }
    return {
      add: add,
      publish: add,
      id: keys.id,
      keys: keys
    }
  }

  db.createRawLogStream = function (opts) {
    return db.stream(opts)
  }

  // pull in the features that are needed to pass the tests
  // and that sbot, etc uses but are slow.
  require('./extras')(db, opts, keys)

  // writeStream - used in (legacy) replication.
  db.createWriteStream = function (cb) {
    cb = cb || errorCB
    return pull(
      pull.asyncMap(function (data, cb) {
        db.queue(data, function (err, msg) {
          if (err) {
            db.emit('invalid', err, msg)
          }
          setImmediate(cb)
        })
      }),
      pull.drain(null, function (err) {
        if (err) return cb(err)
        db.flush(cb)
      })
    )
  }

  // should be private
  db.createHistoryStream = db.clock.createHistoryStream

  // called with [id, seq] or "<id>:<seq>"
  db.getAtSequence = function (seqid, cb) {
    // will NOT expose private plaintext
    db.clock.get(isString(seqid) ? seqid.split(':') : seqid, function (err, value) {
      if (err) cb(err)
      else cb(null, u.originalData(value))
    })
  }

  db.getVectorClock = function (_, cb) {
    if (!cb) cb = _
    db.last.get(function (err, h) {
      if (err) return cb(err)
      var clock = {}
      for (var k in h) { clock[k] = h[k].sequence }
      cb(null, clock)
    })
  }

  return db
}

<commit_msg>remove _db, and throw error if path not provided<commit_after>'use strict'

var join = require('path').join
var EventEmitter = require('events')

var pull = require('pull-stream')
var ref = require('ssb-ref')
var ssbKeys = require('ssb-keys')

var u = require('./util')

function isString (s) {
  return typeof s === 'string'
}

function errorCB (err) {
  if (err) throw err
}

module.exports = function (_, opts, keys, path) {
  //_ was legacy db. removed that, but for backwards compatibilty reasons do not change interface
  if(!path) throw new Error('path must be provided')

  keys = keys || ssbKeys.generate()

  var db = require('./db')(join(opts.path || path, 'flume'), keys, opts)

  // UGLY HACK, but...
  // fairly sure that something up the stack expects ssb to be an event emitter.
  db.__proto__ = new EventEmitter() // eslint-disable-line

  db.opts = opts

  var _get = db.get

  db.get = function (key, cb) {
    let isPrivate = false
    let unbox
    if (typeof key === 'object') {
      isPrivate = key.private === true
      unbox = key.unbox
      key = key.id
    }

    if (ref.isMsg(key)) {
      return db.keys.get(key, function (err, data) {
        if (err) return cb(err)

        if (isPrivate && unbox) {
          data = db.unbox(data, unbox)
        }

        let result

        if (isPrivate) {
          result = data.value
        } else {
          result = u.originalValue(data.value)
        }

        cb(null, result)
      })
    } else if (ref.isMsgLink(key)) {
      var link = ref.parseLink(key)
      return db.get({
        id: link.link,
        private: true,
        unbox: link.query.unbox.replace(/\s/g, '+')
      }, cb)
    } else if (Number.isInteger(key)) {
      _get(key, cb) // seq
    } else {
      throw new Error('ssb-db.get: key *must* be a ssb message id or a flume offset')
    }
  }

  db.add = function (msg, cb) {
    db.queue(msg, function (err, data) {
      if (err) cb(err)
      else db.flush(function () { cb(null, data) })
    })
  }

  db.createFeed = function (keys) {
    if (!keys) keys = ssbKeys.generate()
    function add (content, cb) {
      // LEGACY: hacks to support add as a continuable
      if (!cb) { return function (cb) { add(content, cb) } }

      db.append({ content: content, keys: keys }, cb)
    }
    return {
      add: add,
      publish: add,
      id: keys.id,
      keys: keys
    }
  }

  db.createRawLogStream = function (opts) {
    return db.stream(opts)
  }

  // pull in the features that are needed to pass the tests
  // and that sbot, etc uses but are slow.
  require('./extras')(db, opts, keys)

  // writeStream - used in (legacy) replication.
  db.createWriteStream = function (cb) {
    cb = cb || errorCB
    return pull(
      pull.asyncMap(function (data, cb) {
        db.queue(data, function (err, msg) {
          if (err) {
            db.emit('invalid', err, msg)
          }
          setImmediate(cb)
        })
      }),
      pull.drain(null, function (err) {
        if (err) return cb(err)
        db.flush(cb)
      })
    )
  }

  // should be private
  db.createHistoryStream = db.clock.createHistoryStream

  // called with [id, seq] or "<id>:<seq>"
  db.getAtSequence = function (seqid, cb) {
    // will NOT expose private plaintext
    db.clock.get(isString(seqid) ? seqid.split(':') : seqid, function (err, value) {
      if (err) cb(err)
      else cb(null, u.originalData(value))
    })
  }

  db.getVectorClock = function (_, cb) {
    if (!cb) cb = _
    db.last.get(function (err, h) {
      if (err) return cb(err)
      var clock = {}
      for (var k in h) { clock[k] = h[k].sequence }
      cb(null, clock)
    })
  }

  return db
}

<|endoftext|>


<commit_before>// Copyright (c) 2012-2014 Heapsource.com and Contributors - http://www.heapsource.com
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
var winston = require('winston');
var util = require('util');

//Allow this file to get an exclusive copy of underscore so it can change the template settings without affecting others
delete require.cache[require.resolve('underscore')];
var _ = require('underscore');
delete require.cache[require.resolve('underscore')];

/**
 * A default list of properties in the request object that are allowed to be logged.
 * These properties will be safely included in the meta of the log.
 * 'body' is not included in this list because it can contains passwords and stuff that are sensitive for logging.
 * TODO: Include 'body' and get the defaultRequestFilter to filter the inner properties like 'password' or 'password_confirmation', etc. Pull requests anyone?
 * @type {Array}
 */
var requestWhitelist = ['url', 'headers', 'method', 'httpVersion', 'originalUrl', 'query'];

/**
 * A default list of properties in the request body that are allowed to be logged.
 * This will normally be empty here, since it should be done at the route level.
 * @type {Array}
 */
var bodyWhitelist = [];

/**
 * A default list of properties in the response object that are allowed to be logged.
 * These properties will be safely included in the meta of the log.
 * @type {Array}
 */
var responseWhitelist = ['statusCode'];

/**
 * A default function to filter the properties of the req object.
 * @param req
 * @param propName
 * @return {*}
 */
var defaultRequestFilter = function (req, propName) {
    return req[propName];
};

/**
 * A default function to filter the properties of the res object.
 * @param res
 * @param propName
 * @return {*}
 */
var defaultResponseFilter = function (req, propName) {
    return req[propName];
};

function filterObject(originalObj, whiteList, initialFilter) {

    var obj = {};
    var fieldsSet = false;

    [].concat(whiteList).forEach(function (propName) {
        var value = initialFilter(originalObj, propName);

        if(typeof (value) !== 'undefined') {
            obj[propName] = value;
            fieldsSet = true;
        };
    });

    return fieldsSet?obj:undefined;
}

//
// ### function errorLogger(options)
// #### @options {Object} options to initialize the middleware.
//

function errorLogger(options) {

    ensureValidOptions(options);

    options.requestFilter = options.requestFilter || defaultRequestFilter;

    return function (err, req, res, next) {

        // Let winston gather all the error data.
        var exceptionMeta = winston.exception.getAllInfo(err);
        exceptionMeta.req = filterObject(req, requestWhitelist, options.requestFilter);

        // This is fire and forget, we don't want logging to hold up the request so don't wait for the callback
        for(var i = 0; i < options.transports.length; i++) {
            var transport = options.transports[i];
            transport.logException('middlewareError', exceptionMeta, function () {
                // Nothing to do here
            });
        }

        next(err);
    };
}

//
// ### function logger(options)
// #### @options {Object} options to initialize the middleware.
//

function logger(options) {

    ensureValidOptions(options);

    options.requestFilter = options.requestFilter || defaultRequestFilter;
    options.responseFilter = options.responseFilter || defaultResponseFilter;
    options.level = options.level || "info";
    options.statusLevels = options.statusLevels || false;
    options.msg = options.msg || "HTTP {{req.method}} {{req.url}}";

    return function (req, res, next) {

        req._startTime = (new Date);

        req._routeWhitelists = {
            req: [],
            res: [],
            body: []
        };

        // Manage to get information from the response too, just like Connect.logger does:
        var end = res.end;
        res.end = function(chunk, encoding) {
            res.responseTime = (new Date) - req._startTime;

            res.end = end;
            res.end(chunk, encoding);

            if (options.statusLevels) {
                if (res.statusCode >= 100) { options.level = "info"; }
                if (res.statusCode >= 400) { options.level = "warn"; }
                if (res.statusCode >= 500) { options.level = "error"; }
            };

            var meta = {};

            if(options.meta !== false) {
              var bodyWhitelist;

              requestWhitelist = requestWhitelist.concat(req._routeWhitelists.req || []);
              responseWhitelist = responseWhitelist.concat(req._routeWhitelists.res || []);

              meta.req = filterObject(req, requestWhitelist, options.requestFilter);
              meta.res = filterObject(res, responseWhitelist, options.responseFilter);

              bodyWhitelist = req._routeWhitelists.body || [];

              if (bodyWhitelist) {
                  meta.req.body = filterObject(req.body, bodyWhitelist, options.requestFilter);
              };

              meta.responseTime = res.responseTime;
            }

            // Using mustache style templating
            _.templateSettings = {
              interpolate: /\{\{(.+?)\}\}/g
            };
            var template = _.template(options.msg);
            var msg = template({req: req, res: res});

            // This is fire and forget, we don't want logging to hold up the request so don't wait for the callback
            for(var i = 0; i < options.transports.length; i++) {
                var transport = options.transports[i];
                transport.log(options.level, msg, meta, function () {
                    // Nothing to do here
                });
            }
        };

        next();
    };
}

function ensureValidOptions(options) {
    if(!options) throw new Error("options are required by express-winston middleware");
    if(!options.transports || !(options.transports.length > 0)) throw new Error("transports are required by express-winston middleware");
};

module.exports.errorLogger = errorLogger;
module.exports.logger = logger;
module.exports.requestWhitelist = requestWhitelist;
module.exports.bodyWhitelist = bodyWhitelist;
module.exports.responseWhitelist = responseWhitelist;
module.exports.defaultRequestFilter = defaultRequestFilter;
module.exports.defaultResponseFilter = defaultResponseFilter;
<commit_msg>Added bodyBlacklist option for negative filtering of req.body properties.<commit_after>// Copyright (c) 2012-2014 Heapsource.com and Contributors - http://www.heapsource.com
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
var winston = require('winston');
var util = require('util');

//Allow this file to get an exclusive copy of underscore so it can change the template settings without affecting others
delete require.cache[require.resolve('underscore')];
var _ = require('underscore');
delete require.cache[require.resolve('underscore')];

/**
 * A default list of properties in the request object that are allowed to be logged.
 * These properties will be safely included in the meta of the log.
 * 'body' is not included in this list because it can contains passwords and stuff that are sensitive for logging.
 * TODO: Include 'body' and get the defaultRequestFilter to filter the inner properties like 'password' or 'password_confirmation', etc. Pull requests anyone?
 * @type {Array}
 */
var requestWhitelist = ['url', 'headers', 'method', 'httpVersion', 'originalUrl', 'query'];

/**
 * A default list of properties in the request body that are allowed to be logged.
 * This will normally be empty here, since it should be done at the route level.
 * @type {Array}
 */
var bodyWhitelist = [];

/**
 * A default list of properties in the request body that are not allowed to be logged.
 * @type {Array}
 */
var bodyBlacklist = [];

/**
 * A default list of properties in the response object that are allowed to be logged.
 * These properties will be safely included in the meta of the log.
 * @type {Array}
 */
var responseWhitelist = ['statusCode'];

/**
 * A default function to filter the properties of the req object.
 * @param req
 * @param propName
 * @return {*}
 */
var defaultRequestFilter = function (req, propName) {
    return req[propName];
};

/**
 * A default function to filter the properties of the res object.
 * @param res
 * @param propName
 * @return {*}
 */
var defaultResponseFilter = function (req, propName) {
    return req[propName];
};

function filterObject(originalObj, whiteList, initialFilter) {

    var obj = {};
    var fieldsSet = false;

    [].concat(whiteList).forEach(function (propName) {
        var value = initialFilter(originalObj, propName);

        if(typeof (value) !== 'undefined') {
            obj[propName] = value;
            fieldsSet = true;
        };
    });

    return fieldsSet?obj:undefined;
}

//
// ### function errorLogger(options)
// #### @options {Object} options to initialize the middleware.
//

function errorLogger(options) {

    ensureValidOptions(options);

    options.requestFilter = options.requestFilter || defaultRequestFilter;

    return function (err, req, res, next) {

        // Let winston gather all the error data.
        var exceptionMeta = winston.exception.getAllInfo(err);
        exceptionMeta.req = filterObject(req, requestWhitelist, options.requestFilter);

        // This is fire and forget, we don't want logging to hold up the request so don't wait for the callback
        for(var i = 0; i < options.transports.length; i++) {
            var transport = options.transports[i];
            transport.logException('middlewareError', exceptionMeta, function () {
                // Nothing to do here
            });
        }

        next(err);
    };
}

//
// ### function logger(options)
// #### @options {Object} options to initialize the middleware.
//

function logger(options) {

    ensureValidOptions(options);

    options.requestFilter = options.requestFilter || defaultRequestFilter;
    options.responseFilter = options.responseFilter || defaultResponseFilter;
    options.level = options.level || "info";
    options.statusLevels = options.statusLevels || false;
    options.msg = options.msg || "HTTP {{req.method}} {{req.url}}";

    return function (req, res, next) {

        req._startTime = (new Date);

        req._routeWhitelists = {
            req: [],
            res: [],
            body: []
        };

        req._routeBlacklists = {
            body: []
        };

        // Manage to get information from the response too, just like Connect.logger does:
        var end = res.end;
        res.end = function(chunk, encoding) {
            res.responseTime = (new Date) - req._startTime;

            res.end = end;
            res.end(chunk, encoding);

            if (options.statusLevels) {
                if (res.statusCode >= 100) { options.level = "info"; }
                if (res.statusCode >= 400) { options.level = "warn"; }
                if (res.statusCode >= 500) { options.level = "error"; }
            };

            var meta = {};

            if(options.meta !== false) {
                var bodyWhitelist, blacklist;

                requestWhitelist = requestWhitelist.concat(req._routeWhitelists.req || []);
                responseWhitelist = responseWhitelist.concat(req._routeWhitelists.res || []);

                meta.req = filterObject(req, requestWhitelist, options.requestFilter);
                meta.res = filterObject(res, responseWhitelist, options.responseFilter);

                bodyWhitelist = req._routeWhitelists.body || [];
                blacklist = _.union(bodyBlacklist, (req._routeBlacklists.body || []));

                if (blacklist.length > 0 && bodyWhitelist.length === 0) {
                    var whitelist = _.difference(_.keys(req.body), blacklist);
                    meta.req.body = filterObject(req.body, whitelist, options.requestFilter);
                } else {
                    meta.req.body = filterObject(req.body, bodyWhitelist, options.requestFilter);
                }

                meta.responseTime = res.responseTime;
            }

            // Using mustache style templating
            _.templateSettings = {
                interpolate: /\{\{(.+?)\}\}/g
            };
            var template = _.template(options.msg);
            var msg = template({req: req, res: res});

            // This is fire and forget, we don't want logging to hold up the request so don't wait for the callback
            for(var i = 0; i < options.transports.length; i++) {
                var transport = options.transports[i];
                transport.log(options.level, msg, meta, function () {
                    // Nothing to do here
                });
            }
        };

        next();
    };
}

function ensureValidOptions(options) {
    if(!options) throw new Error("options are required by express-winston middleware");
    if(!options.transports || !(options.transports.length > 0)) throw new Error("transports are required by express-winston middleware");
};

module.exports.errorLogger = errorLogger;
module.exports.logger = logger;
module.exports.requestWhitelist = requestWhitelist;
module.exports.bodyWhitelist = bodyWhitelist;
module.exports.bodyBlacklist = bodyBlacklist;
module.exports.responseWhitelist = responseWhitelist;
module.exports.defaultRequestFilter = defaultRequestFilter;
module.exports.defaultResponseFilter = defaultResponseFilter;
<|endoftext|>


<commit_before>import { parseNeed } from "./parse-need.js";
import Immutable from "immutable";
import won from "../../won-es6.js";

export function addNeed(needs, jsonldNeed, isOwned) {
  let newState;
  let parsedNeed = parseNeed(jsonldNeed, isOwned);

  if (parsedNeed && parsedNeed.get("uri")) {
    let existingNeed = needs.get(parsedNeed.get("uri"));
    const isExistingOwnedNeed = existingNeed && existingNeed.get("isOwned");

    if ((isOwned || isExistingOwnedNeed) && existingNeed) {
      parsedNeed = parsedNeed
        .set("connections", existingNeed.get("connections"))
        .set("isOwned", true);
    } else if (!isOwned && existingNeed) {
      parsedNeed = parsedNeed
        .set("connections", existingNeed.get("connections"))
        .set("isOwned", false);
    }

    return needs.set(parsedNeed.get("uri"), parsedNeed);
  } else {
    const jsonldNeedImm = Immutable.fromJS(jsonldNeed);
    console.error("Tried to add invalid need-object: ", jsonldNeedImm.toJS());
    newState = needs;
  }

  return newState;
}

function addNeedInLoading(needs, needUri, state, isOwned) {
  const oldNeed = needs.get(needUri);
  if (oldNeed) {
    return needs;
  } else {
    let need = Immutable.fromJS({
      uri: needUri,
      isOwned: isOwned,
      state: state,
      connections: Immutable.Map(),
    });
    return needs.setIn([needUri], need);
  }
}

function addTheirNeedInLoading(needs, needUri) {
  const oldNeed = needs.get(needUri);
  if (oldNeed && oldNeed.get("isOwned")) {
    return needs;
  } else {
    let need = Immutable.fromJS({
      uri: needUri,
      isOwned: false,
      connections: Immutable.Map(),
    });
    return needs.setIn([needUri], need);
  }
}

export function addOwnActiveNeedsInLoading(needs, needUris) {
  let newState = needs;
  needUris &&
    needUris.forEach(needUri => {
      newState = addNeedInLoading(
        newState,
        needUri,
        won.WON.ActiveCompacted,
        true
      );
    });
  return newState;
}

export function addOwnInactiveNeedsInLoading(needs, needUris) {
  let newState = needs;
  needUris &&
    needUris.forEach(needUri => {
      newState = addNeedInLoading(
        newState,
        needUri,
        won.WON.InactiveCompacted,
        true
      );
    });
  return newState;
}

export function addTheirNeedsInLoading(needs, needUris) {
  let newState = needs;
  needUris &&
    needUris.forEach(needUri => {
      newState = addTheirNeedInLoading(newState, needUri);
    });
  return newState;
}

export function addOwnInactiveNeedsToLoad(needs, needUris) {
  let newState = needs;
  needUris &&
    needUris.forEach(needUri => {
      newState = addNeedToLoad(
        newState,
        needUri,
        won.WON.InactiveCompacted,
        true
      );
    });
  return newState;
}

function addNeedToLoad(needs, needUri, state, isOwned) {
  if (needs.get(needUri)) {
    return needs;
  } else {
    let need = Immutable.fromJS({
      uri: needUri,
      isOwned: isOwned,
      state: state,
      connections: Immutable.Map(),
    });
    return needs.setIn([needUri], need);
  }
}

export function addNeedInCreation(needs, needInCreation, needUri) {
  let newState;
  let need = Immutable.fromJS(needInCreation);

  if (need) {
    need = need.set("uri", needUri);
    need = need.set("isOwned", true);
    need = need.set("isBeingCreated", true);
    need = need.set("connections", Immutable.Map());

    let title = undefined;

    if (need.get("content")) {
      title = need.getIn(["content", "title"]);
    }

    if (need.get("seeks")) {
      title = need.getIn(["seeks", "title"]);
    }

    need = need.set("humanReadable", title);

    newState = needs.setIn([needUri], need);
  } else {
    console.error("Tried to add invalid need-object: ", needInCreation);
    newState = needs;
  }
  return newState;
}

export function markNeedAsRead(state, needUri) {
  const need = state.get(needUri);

  if (!need) {
    console.error("No need with needUri: <", needUri, ">");
    return state;
  }
  return state.setIn([needUri, "unread"], false);
}

export function changeNeedState(state, needUri, newState) {
  return state.setIn([needUri, "state"], newState);
}
<commit_msg>Removes a part of the code that did not make any sense at all<commit_after>import { parseNeed } from "./parse-need.js";
import Immutable from "immutable";
import won from "../../won-es6.js";

export function addNeed(needs, jsonldNeed, isOwned) {
  let newState;
  let parsedNeed = parseNeed(jsonldNeed, isOwned);

  if (parsedNeed && parsedNeed.get("uri")) {
    let existingNeed = needs.get(parsedNeed.get("uri"));
    const isExistingOwnedNeed = existingNeed && existingNeed.get("isOwned");

    if ((isOwned || isExistingOwnedNeed) && existingNeed) {
      parsedNeed = parsedNeed
        .set("connections", existingNeed.get("connections"))
        .set("isOwned", true);
    } else if (!isOwned && existingNeed) {
      parsedNeed = parsedNeed
        .set("connections", existingNeed.get("connections"))
        .set("isOwned", false);
    }

    return needs.set(parsedNeed.get("uri"), parsedNeed);
  } else {
    console.error("Tried to add invalid need-object: ", jsonldNeed);
    newState = needs;
  }

  return newState;
}

function addNeedInLoading(needs, needUri, state, isOwned) {
  const oldNeed = needs.get(needUri);
  if (oldNeed) {
    return needs;
  } else {
    let need = Immutable.fromJS({
      uri: needUri,
      isOwned: isOwned,
      state: state,
      connections: Immutable.Map(),
    });
    return needs.setIn([needUri], need);
  }
}

function addTheirNeedInLoading(needs, needUri) {
  const oldNeed = needs.get(needUri);
  if (oldNeed && oldNeed.get("isOwned")) {
    return needs;
  } else {
    let need = Immutable.fromJS({
      uri: needUri,
      isOwned: false,
      connections: Immutable.Map(),
    });
    return needs.setIn([needUri], need);
  }
}

export function addOwnActiveNeedsInLoading(needs, needUris) {
  let newState = needs;
  needUris &&
    needUris.forEach(needUri => {
      newState = addNeedInLoading(
        newState,
        needUri,
        won.WON.ActiveCompacted,
        true
      );
    });
  return newState;
}

export function addOwnInactiveNeedsInLoading(needs, needUris) {
  let newState = needs;
  needUris &&
    needUris.forEach(needUri => {
      newState = addNeedInLoading(
        newState,
        needUri,
        won.WON.InactiveCompacted,
        true
      );
    });
  return newState;
}

export function addTheirNeedsInLoading(needs, needUris) {
  let newState = needs;
  needUris &&
    needUris.forEach(needUri => {
      newState = addTheirNeedInLoading(newState, needUri);
    });
  return newState;
}

export function addOwnInactiveNeedsToLoad(needs, needUris) {
  let newState = needs;
  needUris &&
    needUris.forEach(needUri => {
      newState = addNeedToLoad(
        newState,
        needUri,
        won.WON.InactiveCompacted,
        true
      );
    });
  return newState;
}

function addNeedToLoad(needs, needUri, state, isOwned) {
  if (needs.get(needUri)) {
    return needs;
  } else {
    let need = Immutable.fromJS({
      uri: needUri,
      isOwned: isOwned,
      state: state,
      connections: Immutable.Map(),
    });
    return needs.setIn([needUri], need);
  }
}

export function addNeedInCreation(needs, needInCreation, needUri) {
  let newState;
  let need = Immutable.fromJS(needInCreation);

  if (need) {
    need = need.set("uri", needUri);
    need = need.set("isOwned", true);
    need = need.set("isBeingCreated", true);
    need = need.set("connections", Immutable.Map());

    let title = undefined;

    if (need.get("content")) {
      title = need.getIn(["content", "title"]);
    }

    if (need.get("seeks")) {
      title = need.getIn(["seeks", "title"]);
    }

    need = need.set("humanReadable", title);

    newState = needs.setIn([needUri], need);
  } else {
    console.error("Tried to add invalid need-object: ", needInCreation);
    newState = needs;
  }
  return newState;
}

export function markNeedAsRead(state, needUri) {
  const need = state.get(needUri);

  if (!need) {
    console.error("No need with needUri: <", needUri, ">");
    return state;
  }
  return state.setIn([needUri, "unread"], false);
}

export function changeNeedState(state, needUri, newState) {
  return state.setIn([needUri, "state"], newState);
}
<|endoftext|>