<commit_before>'use strict';

const wrappers = require('../config/route-config-wrappers');

function extractUser(event) {
  return event.requestContext && event.requestContext.authorizer && event.requestContext.authorizer.id;
}

function extractPath(event) {
  return `${event.httpMethod} ${event.path}`;
}

function extractQueryParams(event) {
  return event.queryStringParameters && JSON.stringify(event.queryStringParameters);
}

function stringifyBody(object) {
  let body =  object && object.body &&
    JSON.stringify((typeof object.body === 'string' ? JSON.parse(object.body) : object.body));
  if (body && body.length > 500) {
    body = body.substring(0, 500) + '...';
  }
  return body;
}

function stringifyHeaders(object) {
  let headers = object && object.headers;
  if (headers && headers['Authorization']) {
    headers['Authorization'] = '******';
  }
  return headers && JSON.stringify(headers);
}

function buildRequestLog(event, objectContainingBody) {
  const user = extractUser(event);
  const path = extractPath(event);
  const queryParams = extractQueryParams(event);
  const headers = stringifyHeaders(objectContainingBody);
  const body = stringifyBody(objectContainingBody);

  return `user=${user} path=${path} queryParams=${queryParams}\n  headers=${headers}\n  body=${body}\n`
}

/**
 * Returns middleware that ensures that each request and response is logged.
 */
module.exports = [
  wrappers.request(function(req, res, next) {
    this.logger.info(`START request. ${buildRequestLog(req.event, req.event)}`);
    return next();
  }),
  wrappers.final(function(req, res, next) {
    if (res.error) {
      this.logger.error(`ERROR processing request. error=${JSON.stringify(res.error)} status=${res.statusCode} ${buildRequestLog(req.event, res)}`);
    } else {
      this.logger.info(`COMPLETED request. status=${res.statusCode} ${buildRequestLog(req.event, res)}`);
    }
    return next();
  })
];<commit_msg>Logging middleware should not break if the body is not json.<commit_after>'use strict';

const wrappers = require('../config/route-config-wrappers');

function extractUser(event) {
  return event.requestContext && event.requestContext.authorizer && event.requestContext.authorizer.id;
}

function extractPath(event) {
  return `${event.httpMethod} ${event.path}`;
}

function extractQueryParams(event) {
  return event.queryStringParameters && JSON.stringify(event.queryStringParameters);
}

function stringifyBody(object) {
  let body = object && object.body;
  if (body) {
    try {
      body = JSON.stringify((typeof object.body === 'string' ? JSON.parse(object.body) : object.body));
    } catch (e) {}
    if (body && typeof body === 'string' && body.length > 500) {
      body = body.substring(0, 500) + '...';
    }
  }
  return body;
}

function stringifyHeaders(object) {
  let headers = object && object.headers;
  if (headers && headers['Authorization']) {
    headers['Authorization'] = '******';
  }
  return headers && JSON.stringify(headers);
}

function buildRequestLog(event, objectContainingBody) {
  const user = extractUser(event);
  const path = extractPath(event);
  const queryParams = extractQueryParams(event);
  const headers = stringifyHeaders(objectContainingBody);
  const body = stringifyBody(objectContainingBody);

  return `user=${user} path=${path} queryParams=${queryParams}\n  headers=${headers}\n  body=${body}\n`
}

/**
 * Returns middleware that ensures that each request and response is logged.
 */
module.exports = [
  wrappers.request(function(req, res, next) {
    this.logger.info(`START request. ${buildRequestLog(req.event, req.event)}`);
    return next();
  }),
  wrappers.final(function(req, res, next) {
    if (res.error) {
      this.logger.error(`ERROR processing request. error=${JSON.stringify(res.error)} status=${res.statusCode} ${buildRequestLog(req.event, res)}`);
    } else {
      this.logger.info(`COMPLETED request. status=${res.statusCode} ${buildRequestLog(req.event, res)}`);
    }
    return next();
  })
];<|endoftext|>


<commit_before>'use strict';

var defaultEnvConfig = require('./default');

module.exports = {
  db: {
    uri: process.env.MONGOLAB_URI,
    options: {
    //  user: 'test',
    //  pass: 'test'
    },

    // Enable mongoose debug mode
    debug: process.env.MONGODB_DEBUG || false
  },
  log: {
    // Can specify one of 'combined', 'common', 'dev', 'short', 'tiny'
    format: 'dev',
    // Stream defaults to process.stdout
    // Uncomment to enable logging to a log on the file system
    options: {
      //stream: 'access.log'
    }
  },
  app: {
    title: defaultEnvConfig.app.title //+ ' - Development Environment'
  },
  facebook: {
    clientID: process.env.FACEBOOK_ID || 'APP_ID',
    clientSecret: process.env.FACEBOOK_SECRET || 'APP_SECRET',
    callbackURL: '/api/auth/facebook/callback' //callbackURL: '/api/auth/facebook/callback'
  },
  twitter: {
    clientID: process.env.TWITTER_KEY || 'CONSUMER_KEY',
    clientSecret: process.env.TWITTER_SECRET || 'CONSUMER_SECRET',
    callbackURL: '/api/auth/twitter/callback'
  },
  google: {
    clientID: process.env.GOOGLE_ID || 'APP_ID',
    clientSecret: process.env.GOOGLE_SECRET || 'APP_SECRET',
    callbackURL: '/api/auth/google/callback'
  },
  linkedin: {
    clientID: process.env.LINKEDIN_ID || 'APP_ID',
    clientSecret: process.env.LINKEDIN_SECRET || 'APP_SECRET',
    callbackURL: '/api/auth/linkedin/callback'
  },
  github: {
    clientID: process.env.GITHUB_ID || 'APP_ID',
    clientSecret: process.env.GITHUB_SECRET || 'APP_SECRET',
    callbackURL: '/api/auth/github/callback'
  },
  paypal: {
    clientID: process.env.PAYPAL_ID || 'CLIENT_ID',
    clientSecret: process.env.PAYPAL_SECRET || 'CLIENT_SECRET',
    callbackURL: '/api/auth/paypal/callback',
    sandbox: true
  },
  mailer: {
    from: process.env.MAILER_FROM || 'MAILER_FROM',
    options: {
      service: process.env.MAILER_SERVICE_PROVIDER || 'MAILER_SERVICE_PROVIDER',
      auth: {
        user: process.env.MAILER_EMAIL_ID || 'MAILER_EMAIL_ID',
        pass: process.env.MAILER_PASSWORD || 'MAILER_PASSWORD'
      }
    }
  },
  livereload: true,
  seedDB: process.env.MONGO_SEED || false
};
<commit_msg>If this doesn't work, I'm gonna call it a night<commit_after>'use strict';

var defaultEnvConfig = require('./default');

module.exports = {
  db: {
    uri: process.env.MONGOLAB_URI,
    options: {
      user: '',
      pass: ''
    },

    // Enable mongoose debug mode
    debug: process.env.MONGODB_DEBUG || false
  },
  log: {
    // Can specify one of 'combined', 'common', 'dev', 'short', 'tiny'
    format: 'dev',
    // Stream defaults to process.stdout
    // Uncomment to enable logging to a log on the file system
    options: {
      //stream: 'access.log'
    }
  },
  app: {
    title: defaultEnvConfig.app.title //+ ' - Development Environment'
  },
  facebook: {
    clientID: process.env.FACEBOOK_ID || 'APP_ID',
    clientSecret: process.env.FACEBOOK_SECRET || 'APP_SECRET',
    callbackURL: '/api/auth/facebook/callback' //callbackURL: '/api/auth/facebook/callback'
  },
  twitter: {
    clientID: process.env.TWITTER_KEY || 'CONSUMER_KEY',
    clientSecret: process.env.TWITTER_SECRET || 'CONSUMER_SECRET',
    callbackURL: '/api/auth/twitter/callback'
  },
  google: {
    clientID: process.env.GOOGLE_ID || 'APP_ID',
    clientSecret: process.env.GOOGLE_SECRET || 'APP_SECRET',
    callbackURL: '/api/auth/google/callback'
  },
  linkedin: {
    clientID: process.env.LINKEDIN_ID || 'APP_ID',
    clientSecret: process.env.LINKEDIN_SECRET || 'APP_SECRET',
    callbackURL: '/api/auth/linkedin/callback'
  },
  github: {
    clientID: process.env.GITHUB_ID || 'APP_ID',
    clientSecret: process.env.GITHUB_SECRET || 'APP_SECRET',
    callbackURL: '/api/auth/github/callback'
  },
  paypal: {
    clientID: process.env.PAYPAL_ID || 'CLIENT_ID',
    clientSecret: process.env.PAYPAL_SECRET || 'CLIENT_SECRET',
    callbackURL: '/api/auth/paypal/callback',
    sandbox: true
  },
  mailer: {
    from: process.env.MAILER_FROM || 'MAILER_FROM',
    options: {
      service: process.env.MAILER_SERVICE_PROVIDER || 'MAILER_SERVICE_PROVIDER',
      auth: {
        user: process.env.MAILER_EMAIL_ID || 'MAILER_EMAIL_ID',
        pass: process.env.MAILER_PASSWORD || 'MAILER_PASSWORD'
      }
    }
  },
  livereload: true,
  seedDB: process.env.MONGO_SEED || false
};
<|endoftext|>


<commit_before>angular.module('sfSense', ['ionic'])

.factory('googleMaps', function(){
  // OVERVIEW
  // 1. setup map options
  // 2. create map
  // 3. get data for crime lat and lng
  // 4. create markers
  // 5. add markers to map
  var map;
  var markers = {};
  var isViolent = {
    'ASSAULT': true,
    'NON-CRIMINAL': false,
    'OTHER OFFENSES': false,
    'ROBBERY': true,
    'LARCENY/THEFT': false,
    'VANDALISM': false,
    'BURGLARY': false,
    'VEHICLE THEFT': false,
    'FRAUD': false,
    'DRUNKENNESS': false,
    'WARRANTS': false,
    'TRESPASS': false,
    'KIDNAPPING': true,
    'SEX OFFENSES': true,
    'WEAPON LAWS': true,
    'DRUG/NARCOTIC': false,
    'FORGERY/COUNTERFEITING': false,
    'MISSING PERSON': false,
    'LIQUOR LAWS': false,
    'BAD CHECKS': false,
    'RUNAWAY': false,
    'EMBEZZLEMENT': false
  };

  var iconPath = '../www/img/icons/';

  // TODO: add marker img for each category
  var markerImg = {
    'BURGLARY': 'robbery.png',
    'LARCENY/THEFT': 'theft.png',
    'ASSAULT': 'robbery.png',
    'MISSING PERSON': 'missing.png',
    'DEFAULT': 'blast.png'
  };

  var createMarker = function(crime) {

    if (markers[crime.id] === undefined) { // if crime isn't displayed yet add it
      var latlng = new google.maps.LatLng(crime.latitude,crime.longitude);

      var icon;

      if(markerImg[crime.category]){
        icon = iconPath + markerImg[crime.category];
      } else {
        icon = iconPath + markerImg.DEFAULT;
      }

      var newMarker = new google.maps.Marker({
        position: latlng,
        animation: google.maps.Animation.DROP,
        title: crime.category,
        icon: icon,
        map: map,
        id: crime.id,
        category: crime.category,
        date: crime.date,
        time: crime.time,
        description: crime.descript,
        type: crime.type.toLowerCase()
      });

      // make a new InfoWindow and associate it to the marker
      newMarker.info = new google.maps.InfoWindow({
        content: '
' + newMarker.description + '
'
      });
      // add the map listener here
      google.maps.event.addListener(newMarker, 'mouseover', function(){
        newMarker.info.open(map, newMarker);
      });

      markers[crime.id] = newMarker; // add it to the markers object
    }
  };

  return {

    // Add in google maps functions here

    createMap: function(lat, lng){
      var mapOptions = {
        center: new google.maps.LatLng(lat, lng),
        zoom: 17,
        panControl: false,
        zoomControl: false,
        mapTypeControl: false,
        streetViewControl: false,
        overviewMapControl: false
      };

      map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
    },

    // CreateMap is not invoked yet so we define addListener to add the event listener
    // Once the map has been created, call addListener
    // Moving method outside of the create call allows access to other services in googleMaps
    // There will only be one map variable so accept only the event and function
    addListener: function(event, func) {
      google.maps.event.addListener(map, event, func);
    },

    createMarkers: function(crimes) {
        for(var i = 0; i < crimes.length; i++){
          createMarker(crimes[i]);
        }
    },

    clearMap: function() {
      // first hide all the markers by setting map to null
      for (var i = 0; i < markers.length; i++) {
        markers[i].setMap(null);
      }
      // we no longer want access to the markers so remove them
      markers = {};
    },

    moveTo: function(lat, lng){
      var latlng = new google.maps.LatLng(lat,lng);
      map.panTo(latlng);
    },

    getCenter: function() {
      // returns latlng object with lat() and lng() methods
      return map.getCenter();
    },

    searchLocByAddress: function(address, cb) {
      var city = 'san francisco';
      var re = RegExp(city, 'i');

      if(!re.exec(address)){
        address = address + ' ' + city;
      }

      geocoder = new google.maps.Geocoder();

      geocoder.geocode( {'address': address}, function(results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
          map.setCenter(results[0].geometry.location);

          cb(results[0].geometry.location.k, results[0].geometry.location.A);

        } else {
          navigator.notification.alert('Error with find location: ' + status);
        }
      });
    },

    searchLoc: function(lat, lng, cb){
      var latlng = new google.maps.LatLng(lat,lng);
      map.setCenter(latlng);
      cb(lat, lng);
    },

    filterBy: function(filter){
      //the filter will match the type field on the markers
      for (var markerID in markers) {

        var marker = markers[markerID];
        var cat = marker.type;

        // check if the filter is all, if so, show all markers
        if (filter === 'all') {
          marker.setMap(map);
        } else { // a filter was specified
          if (filter === cat) { // filter matches marker type
            marker.setMap(map);
          } else { // filter doesn't match marker type
            marker.setMap(null);
          }
        }
      }
    }
  };
})

.controller('MapCtrl', function($scope, $http, googleMaps){

  $scope.filters = ['other', 'assault', 'theft'];

  var hideKeyboard = function() {
    document.activeElement.blur();
    $("input").blur();
  };

  var init = function() {
    // SF center lat and lng
    var lat = 37.783522;
    var lng = -122.408964;

    googleMaps.createMap(lat, lng);

    // After map has been created, add listeners here
    googleMaps.addListener('dragend', function(){
      // get the lng and lat and call getCrimes with them
      var newCenter = googleMaps.getCenter();
      // clear the map of current markers and infowindows
      // googleMaps.clearMap();
      $scope.getCrimes(newCenter.lat(), newCenter.lng());
    });
  };

  $scope.gpsSearchCrime = function(){

    var onSuccess = function(pos){
      var lat = pos.coords.latitude;
      var lng = pos.coords.longitude;
      googleMaps.searchLoc(lat, lng, $scope.getCrimes);
    };

    var onError = function(error) {
      navigator.notification.alert('Code: ' + error.code + '\n' + 'Message:' + error.message);
    };

    navigator.geolocation.getCurrentPosition(onSuccess, onError);
  };

  $scope.getCrimes = function(lat, lng){

    var url = "http://sf-sense-server.herokuapp.com/near?longitude=" + lng + "&latitude="+ lat + "&distance=0.3";

    $http({
      headers: {
      "Authorization" : "Basic " + btoa("sf-sense:858F8CDDB1F324A762DBEFDC77844")
      },
      url: url,
      dataType: 'json',
      method: "GET"
    }).success(function(response){
      googleMaps.createMarkers(response);
    }).error(function(error){
      navigator.notification.alert('There was an error: ' + error);
    });
  };

  $scope.searchCrime = function() {
    // $scope.mapSearch is a street address
    // on success, calls getCrimes with the lat/lng

    // if map search if undefined use current location. Placeholder is current location.
    if(!$scope.mapSearch) {
      $scope.gpsSearchCrime();
    } else {
      googleMaps.searchLocByAddress($scope.mapSearch, $scope.getCrimes);
    }

    hideKeyboard();
  };

  $scope.filterBy = function (filterArg) {
    if (!filterArg) filterArg = 'all';
    googleMaps.filterBy(filterArg);
  };

  $scope.trackLocation = function() {
    alert('Tracking');
    var bgGeo = window.plugins.backgroundGeoLocation;

    var onSuccess = function(pos){
      var lat = pos.latitude;
      var lng = pos.longitude;
      alert(lat);
      // googleMaps.searchLoc(lat, lng, $scope.getCrimes);
    };

    var onError = function(error) {
      navigator.notification.alert('Code: ' + error.code + '\n' + 'Message:' + error.message);
    };

    bgGeo.configure(onSuccess, onError, {
      desiredAccuracy: 10,
      stationaryRadius: 20,
      distanceFilter: 30,
      debug: true // <-- enable this hear sounds for background-geolocation life-cycle.
    });

    bgGeo.start();
  };

  init();
})

.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
    // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
    // for form inputs)
    if(window.cordova && window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
    }
    if(window.StatusBar) {
      StatusBar.styleDefault();
    }
  });
});

<commit_msg>Fixes bug, new markers are displayed based on current filter<commit_after>angular.module('sfSense', ['ionic'])

.factory('googleMaps', function(){
  // OVERVIEW
  // 1. setup map options
  // 2. create map
  // 3. get data for crime lat and lng
  // 4. create markers
  // 5. add markers to map
  var map;
  var markers = {};
  var filterOn = 'all';
  var isViolent = {
    'ASSAULT': true,
    'NON-CRIMINAL': false,
    'OTHER OFFENSES': false,
    'ROBBERY': true,
    'LARCENY/THEFT': false,
    'VANDALISM': false,
    'BURGLARY': false,
    'VEHICLE THEFT': false,
    'FRAUD': false,
    'DRUNKENNESS': false,
    'WARRANTS': false,
    'TRESPASS': false,
    'KIDNAPPING': true,
    'SEX OFFENSES': true,
    'WEAPON LAWS': true,
    'DRUG/NARCOTIC': false,
    'FORGERY/COUNTERFEITING': false,
    'MISSING PERSON': false,
    'LIQUOR LAWS': false,
    'BAD CHECKS': false,
    'RUNAWAY': false,
    'EMBEZZLEMENT': false
  };

  var iconPath = '../www/img/icons/';

  // TODO: add marker img for each category
  var markerImg = {
    'BURGLARY': 'robbery.png',
    'LARCENY/THEFT': 'theft.png',
    'ASSAULT': 'robbery.png',
    'MISSING PERSON': 'missing.png',
    'DEFAULT': 'blast.png'
  };

  var createMarker = function(crime) {

    if (markers[crime.id] === undefined) { // if crime isn't displayed yet add it
      var latlng = new google.maps.LatLng(crime.latitude,crime.longitude);

      var icon;

      if(markerImg[crime.category]){
        icon = iconPath + markerImg[crime.category];
      } else {
        icon = iconPath + markerImg.DEFAULT;
      }

      var newMarker = new google.maps.Marker({
        position: latlng,
        animation: google.maps.Animation.DROP,
        title: crime.category,
        icon: icon,
        id: crime.id,
        category: crime.category,
        date: crime.date,
        time: crime.time,
        description: crime.descript,
        type: crime.type.toLowerCase()
      });

      // check if the marker should be displayed or not
      if (filterOn === 'all' || filterOn === crime.type) {
        newMarker.setMap(map);
      }
      // make a new InfoWindow and associate it to the marker
      newMarker.info = new google.maps.InfoWindow({
        content: '
' + newMarker.description + '
'
      });
      // add the map listener here
      google.maps.event.addListener(newMarker, 'mouseover', function(){
        newMarker.info.open(map, newMarker);
      });

      markers[crime.id] = newMarker; // add it to the markers object
    }
  };

  return {

    // Add in google maps functions here

    createMap: function(lat, lng){
      var mapOptions = {
        center: new google.maps.LatLng(lat, lng),
        zoom: 17,
        panControl: false,
        zoomControl: false,
        mapTypeControl: false,
        streetViewControl: false,
        overviewMapControl: false
      };

      map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
    },

    // CreateMap is not invoked yet so we define addListener to add the event listener
    // Once the map has been created, call addListener
    // Moving method outside of the create call allows access to other services in googleMaps
    // There will only be one map variable so accept only the event and function
    addListener: function(event, func) {
      google.maps.event.addListener(map, event, func);
    },

    createMarkers: function(crimes) {
        for(var i = 0; i < crimes.length; i++){
          createMarker(crimes[i]);
        }
    },

    clearMap: function() {
      // first hide all the markers by setting map to null
      for (var i = 0; i < markers.length; i++) {
        markers[i].setMap(null);
      }
      // we no longer want access to the markers so remove them
      markers = {};
    },

    moveTo: function(lat, lng){
      var latlng = new google.maps.LatLng(lat,lng);
      map.panTo(latlng);
    },

    getCenter: function() {
      // returns latlng object with lat() and lng() methods
      return map.getCenter();
    },

    searchLocByAddress: function(address, cb) {
      var city = 'san francisco';
      var re = RegExp(city, 'i');

      if(!re.exec(address)){
        address = address + ' ' + city;
      }

      geocoder = new google.maps.Geocoder();

      geocoder.geocode( {'address': address}, function(results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
          map.setCenter(results[0].geometry.location);

          cb(results[0].geometry.location.k, results[0].geometry.location.A);

        } else {
          navigator.notification.alert('Error with find location: ' + status);
        }
      });
    },

    searchLoc: function(lat, lng, cb){
      var latlng = new google.maps.LatLng(lat,lng);
      map.setCenter(latlng);
      cb(lat, lng);
    },

    filterBy: function(filter){
      // set filterOn
      filterOn = filter;
      // the filter will match the type field on the markers
      for (var markerID in markers) {

        var marker = markers[markerID];
        var cat = marker.type;

        // check if the filter is all, if so, show all markers
        if (filter === 'all') {
          marker.setMap(map);
        } else { // a filter was specified
          if (filter === cat) { // filter matches marker type
            marker.setMap(map);
          } else { // filter doesn't match marker type
            marker.setMap(null);
          }
        }
      }
    }
  };
})

.controller('MapCtrl', function($scope, $http, googleMaps){

  $scope.filters = ['other', 'assault', 'theft'];

  var hideKeyboard = function() {
    document.activeElement.blur();
    $("input").blur();
  };

  var init = function() {
    // SF center lat and lng
    var lat = 37.783522;
    var lng = -122.408964;

    googleMaps.createMap(lat, lng);

    // After map has been created, add listeners here
    googleMaps.addListener('dragend', function(){
      // get the lng and lat and call getCrimes with them
      var newCenter = googleMaps.getCenter();
      // clear the map of current markers and infowindows
      // googleMaps.clearMap();
      $scope.getCrimes(newCenter.lat(), newCenter.lng());
    });
  };

  $scope.gpsSearchCrime = function(){

    var onSuccess = function(pos){
      var lat = pos.coords.latitude;
      var lng = pos.coords.longitude;
      googleMaps.searchLoc(lat, lng, $scope.getCrimes);
    };

    var onError = function(error) {
      navigator.notification.alert('Code: ' + error.code + '\n' + 'Message:' + error.message);
    };

    navigator.geolocation.getCurrentPosition(onSuccess, onError);
  };

  $scope.getCrimes = function(lat, lng){

    var url = "http://sf-sense-server.herokuapp.com/near?longitude=" + lng + "&latitude="+ lat + "&distance=0.3";

    $http({
      headers: {
      "Authorization" : "Basic " + btoa("sf-sense:858F8CDDB1F324A762DBEFDC77844")
      },
      url: url,
      dataType: 'json',
      method: "GET"
    }).success(function(response){
      googleMaps.createMarkers(response);
    }).error(function(error){
      navigator.notification.alert('There was an error: ' + error);
    });
  };

  $scope.searchCrime = function() {
    // $scope.mapSearch is a street address
    // on success, calls getCrimes with the lat/lng

    // if map search if undefined use current location. Placeholder is current location.
    if(!$scope.mapSearch) {
      $scope.gpsSearchCrime();
    } else {
      googleMaps.searchLocByAddress($scope.mapSearch, $scope.getCrimes);
    }

    hideKeyboard();
  };

  $scope.filterBy = function (filterArg) {
    if (!filterArg) filterArg = 'all';
    googleMaps.filterBy(filterArg);
  };

  $scope.trackLocation = function() {
    alert('Tracking');
    var bgGeo = window.plugins.backgroundGeoLocation;

    var onSuccess = function(pos){
      var lat = pos.latitude;
      var lng = pos.longitude;
      alert(lat);
      // googleMaps.searchLoc(lat, lng, $scope.getCrimes);
    };

    var onError = function(error) {
      navigator.notification.alert('Code: ' + error.code + '\n' + 'Message:' + error.message);
    };

    bgGeo.configure(onSuccess, onError, {
      desiredAccuracy: 10,
      stationaryRadius: 20,
      distanceFilter: 30,
      debug: true // <-- enable this hear sounds for background-geolocation life-cycle.
    });

    bgGeo.start();
  };

  init();
})

.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
    // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
    // for form inputs)
    if(window.cordova && window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
    }
    if(window.StatusBar) {
      StatusBar.styleDefault();
    }
  });
});

<|endoftext|>


<commit_before>dojo.experimental("dojox.widget.Portlet");
dojo.provide("dojox.widget.Portlet");
dojo.require("dijit.TitlePane");
dojo.require("dojo.fx");

dojo.declare("dojox.widget.Portlet", [dijit._Container, dijit.TitlePane],{
	// summary: A container widget that is designed to be contained
	//		in a dojox.layout.GridContainer. Child widgets can insert
	//		an icon into the title bar of the Portlet, which when
	//		clicked, executes the "toggle" method of the child widget.
	//		A child widget must specify the attribute
	//		"portletIconClass", and the optional class
	//		"portletIconHoverClass", as well as the
	//		"toggle" function.

	// resizeChildren: Boolean
	//		If true, when the Portlet is resized, any child widgets
	//		with a 'resize' method have that method called.
	resizeChildren: true,

	// closable: Boolean
	//		If true, a close button is placed in the title bar,
	//		and the Portlet can be hidden. If false, the Portlet
	//		cannot be closed.
	closable: true,

	// _parents: Array
	//		 An array of all the StackContainer widgets that this Portlet
	//		is contained in.	These are used to determine if the portlet
	//		is visible or not.
	_parents: null,

	// _size: Object
	//		Cache of the previous size of the portlet, used to determine
	//		if the size has changed and if the child widgets should be
	//		resized.
	_size: null,

	// dragRestriction: Boolean
	//		To remove the drag capability.
	dragRestriction : false,

	buildRendering: function(){
		this.inherited(arguments);

		// Hide the portlet until it is fully constructed.
		dojo.style(this.domNode, "visibility", "hidden");
	},

	postCreate: function(){
		this.inherited(arguments);

		// Add the portlet classes
		dojo.addClass(this.domNode, "dojoxPortlet");
		dojo.removeClass(this.arrowNode, "dijitArrowNode");
		dojo.addClass(this.arrowNode, "dojoxPortletIcon dojoxArrowDown");
		dojo.addClass(this.titleBarNode, "dojoxPortletTitle");
		dojo.addClass(this.hideNode, "dojoxPortletContentOuter");

		// Choose the class to add depending on if the portlet is draggable or not.
		dojo.addClass(this.domNode, "dojoxPortlet-" + (!this.dragRestriction ? "movable" : "nonmovable"));

		if(this.resizeChildren){
			// If children should be resized	when the portlet size changes,
			// listen for items being dropped, when the window is resized,
			// or when another portlet's size changes.

			dojo.subscribe("/dnd/drop", dojo.hitch(this, "_updateSize"));

			dojo.subscribe("/Portlet/sizechange", dojo.hitch(this, "onSizeChange"));
			dojo.connect(window, "onresize", this, "_updateSize");

			// Subscribe to all possible child-selection events that could affect this
			// portlet
			var _this = this;
			var doSelectSubscribe = function(id, lastId){
				var widget = dijit.byId(id);
				if(widget.selectChild){
					var s = dojo.subscribe(id + "-selectChild", dojo.hitch(_this, function(child){
						var n = _this.domNode.parentNode;

						while(n){
							if(n == child.domNode){

								// Only fire this once, as the widget is now visible
								// at least once, so child measurements should be accurate.
								dojo.unsubscribe(s);
								_this._updateSize();
								break;
							}
							n = n.parentNode;
						}
					}));

					// Record the StackContainer and child widget that this portlet
					// is in, so it can figure out whether or not it is visible.
					// If it is not visible, it will not update it's size dynamically.
					var child = dijit.byId(lastId);
					if(widget && child){
						_this._parents.push({parent: widget, child: child});
					}
				}
			}
			var lastId;
			this._parents = [];

			// Find all parent widgets, and if they are StackContainers,
			// subscribe to their selectChild method calls.
			for(var p = this.domNode.parentNode; p != null; p = p.parentNode){
				var id = p.getAttribute ? p.getAttribute("widgetId") : null;
				if(id){
					doSelectSubscribe(id, lastId);
					lastId = id;
				}
			}
		}

		// Inform all portlets that the size of this one has changed,
		// and therefore perhaps they have too
		dojo.connect(this._wipeOut, "onEnd", this, "_publish");
		dojo.connect(this._wipeIn, "onEnd", this, "_publish");

		if(this.closable){
			this.closeIcon = this._createIcon("dojoxCloseNode", "dojoxCloseNodeHover", dojo.hitch(this, "onClose"));
			dojo.style(this.closeIcon, "display", "");
		}
	},

	startup: function(){
		if(this._started){return;}

		var children = this.getChildren();
		this._placeSettingsWidgets();

		// Start up the children
		dojo.forEach(children, function(child){
			try{
				if(!child.started && !child._started){
					child.startup()
				}
			}
			catch(e){
				console.log(this.id + ":" + this.declaredClass, e);
			}
		});

		this.inherited(arguments);

		this._updateSize();
		dojo.style(this.domNode, "visibility", "visible");
	},

	_placeSettingsWidgets: function(){
		// summary: Checks all the children to see if they are instances
		//		of dojox.widget.PortletSettings.	If they are,
		//		create an icon for them in the title bar which when clicked,
		//		calls their toggle() method.

		dojo.forEach(this.getChildren(), dojo.hitch(this, function(child){
			if(child.portletIconClass && child.toggle && !child.attr("portlet")){
				this._createIcon(child.portletIconClass, child.portletIconHoverClass, dojo.hitch(child, "toggle"));
				dojo.place(child.domNode, this.containerNode, "before");
				child.attr("portlet", this);
			}
		}));
	},

	_createIcon: function(clazz, hoverClazz, fn){
		// summary:
		//		creates an icon in the title bar.

		var icon = dojo.create("div",{
			"class": "dojoxPortletIcon " + clazz,
			"waiRole": "presentation"
		});
		dojo.place(icon, this.arrowNode, "before");

		dojo.connect(icon, "onclick", fn);

		if(hoverClazz){
			dojo.connect(icon, "onmouseover", function(){
				dojo.addClass(icon, hoverClazz);
			});
			dojo.connect(icon, "onmouseout", function(){
				dojo.removeClass(icon, hoverClazz);
			});
		}
		return icon;
	},

	onClose: function(evt){
		// summary:
		//		Hides the portlet. Note that it does not
		//		persist this, so it is up to the client to
		//		listen to this method and persist the closed state
		//		in their own way.
		dojo.style(this.domNode, "display", "none");
	},

	onSizeChange: function(widget){
		// summary:
		//		Updates the Portlet size if any other Portlet
		//		changes its size.
		if(widget == this){
			return;
		}
		this._updateSize();
	},

	_updateSize: function(){
		// summary:
		//		Updates the size of all child widgets.
		if(!this.open || !this._started || !this.resizeChildren){
			return;
		}
		var size ={
			w: dojo.style(this.domNode, "width"),
			h: dojo.style(this.domNode, "height")
		};

		// If the Portlet is in a StackWidget, and it is not
		// visible, do not update the size, as it could
		// make child widgets miscalculate.
		for(var i = 0; i < this._parents.length; i++){
			var p = this._parents[i];
			var sel = p.parent.selectedChildWidget
			if(sel && sel != p.child){
				return;
			}
		}

		if(this._size){
			// If the size of the portlet hasn't changed, don't
			// resize the children, as this can be expensive
			if(this._size.w == size.w && this._size.h == size.h){
				return;
			}
		}
		this._size = size;

		if(this._timer){
			clearTimeout(this._timer);
		}

		// Delay applying the size change in case the size
		// changes very frequently, for performance reasons.
		this._timer = setTimeout(dojo.hitch(this, function(){
			var fns = ["resize", "layout"];
			this._timer = null;
			var kids = this.getChildren();

			dojo.forEach(kids, function(child){
				for(var i = 0; i < fns.length; i++){
					if(dojo.isFunction(child[fns[i]])){
						try{
							child[fns[i]]();
						} catch(e){
							console.log(e);
						}
						break;
					}
				}
			});
			this.onUpdateSize();
		}), 100);
	},

	onUpdateSize: function(){
		// summary:
		//		Stub function called when the size is changed.
	},

	_publish: function(){
		// summary: Publishes an event that all other portlets listen to.
		//		This causes them to update their child widgets if their
		//		size has changed.
		dojo.publish("/Portlet/sizechange",[this]);
	},

	_onTitleClick: function(evt){
		if(evt.target == this.arrowNode){
			this.inherited(arguments);
		}
	},

	addChild: function(child){
		// summary:
		//		Adds a child widget to the portlet.
		this._size = null;
		this.inherited(arguments);

		if(this._started){
			this._placeSettingsWidgets();
			this._updateSize();
		}
		if(this._started && !child.started && !child._started){
			child.startup();
		}
	}
});

dojo.declare("dojox.widget.PortletSettings", [dijit._Container, dijit.layout.ContentPane],{
	// summary:
	//		A settings widget to be used with a dojox.widget.Portlet.
	// description:
	//		This widget should be placed inside a dojox.widget.Portlet widget.
	//		It is used to set some preferences for that Portlet.	It is essentially
	//		a ContentPane, and should contain other widgets and DOM nodes that
	//		do the real work of setting preferences for the portlet.

	// portletIconClass: String
	//		The CSS class to apply to the icon in the Portlet title bar that is used
	//		to toggle the visibility of this widget.
	portletIconClass: "dojoxPortletSettingsIcon",

	// portletIconHoverClass: String
	//		The CSS class to apply to the icon in the Portlet title bar that is used
	//		to toggle the visibility of this widget when the mouse hovers over it.
	portletIconHoverClass: "dojoxPortletSettingsIconHover",

	postCreate: function(){
		// summary:
		//		Sets the require CSS classes on the widget.

		// Start the PortletSettings widget hidden, always.
		dojo.style(this.domNode, "display", "none");
		dojo.addClass(this.domNode, "dojoxPortletSettingsContainer");

		// Remove the unwanted content pane class.
		dojo.removeClass(this.domNode, "dijitContentPane");
	},

	_setPortletAttr: function(portlet){
		// summary:
		//		Sets the portlet that encloses this widget.
		this.portlet = portlet;
	},

	toggle: function(){
		// summary:
		//		Toggles the visibility of this widget.
		var n = this.domNode;
		if(dojo.style(n, "display") == "none"){
			dojo.style(n,{
				"display": "block",
				"height": "1px",
				"width": "auto"
			});
			dojo.fx.wipeIn({
				node: n
			}).play();
		}else{
			dojo.fx.wipeOut({
				node: n,
				onEnd: dojo.hitch(this, function(){
					dojo.style(n,{"display": "none", "height": "", "width":""});
				}
			)}).play();
		}
	}
});

dojo.declare("dojox.widget.PortletDialogSettings",
	dojox.widget.PortletSettings,{
	// summary:
	//		A settings widget to be used with a dojox.widget.Portlet, which displays
	//		the contents of this widget in a dijit.Dialog box.

	// dimensions: Array
	//		The size of the dialog to display.	This defaults to [300, 300]
	dimensions: null,

	constructor: function(props, node){
		this.dimensions = props.dimensions || [300, 100];
	},

	toggle: function(){
		// summary:
		//		Shows and hides the Dialog box.
		if(!this.dialog){
			dojo["require"]("dijit.Dialog");
			this.dialog = new dijit.Dialog({title: this.title});

			dojo.body().appendChild(this.dialog.domNode);

			// Move this widget inside the dialog
			this.dialog.containerNode.appendChild(this.domNode);

			dojo.style(this.dialog.domNode,{
				"width" : this.dimensions[0] + "px",
				"height" : this.dimensions[1] + "px"
			});
			dojo.style(this.domNode, "display", "");
		}
		if(this.dialog.open){
			this.dialog.hide();
		}else{
			this.dialog.show(this.domNode);
		}
	}
});
<commit_msg>Refs #9993 Fixes the issue where a clicking on an icon in a dojox.widget.Portlet could cause a drag to start, instead of registering the click on the icon.<commit_after>dojo.experimental("dojox.widget.Portlet");
dojo.provide("dojox.widget.Portlet");
dojo.require("dijit.TitlePane");
dojo.require("dojo.fx");

dojo.declare("dojox.widget.Portlet", [dijit._Container, dijit.TitlePane],{
	// summary: A container widget that is designed to be contained
	//		in a dojox.layout.GridContainer. Child widgets can insert
	//		an icon into the title bar of the Portlet, which when
	//		clicked, executes the "toggle" method of the child widget.
	//		A child widget must specify the attribute
	//		"portletIconClass", and the optional class
	//		"portletIconHoverClass", as well as the
	//		"toggle" function.

	// resizeChildren: Boolean
	//		If true, when the Portlet is resized, any child widgets
	//		with a 'resize' method have that method called.
	resizeChildren: true,

	// closable: Boolean
	//		If true, a close button is placed in the title bar,
	//		and the Portlet can be hidden. If false, the Portlet
	//		cannot be closed.
	closable: true,

	// _parents: Array
	//		 An array of all the StackContainer widgets that this Portlet
	//		is contained in.	These are used to determine if the portlet
	//		is visible or not.
	_parents: null,

	// _size: Object
	//		Cache of the previous size of the portlet, used to determine
	//		if the size has changed and if the child widgets should be
	//		resized.
	_size: null,

	// dragRestriction: Boolean
	//		To remove the drag capability.
	dragRestriction : false,

	buildRendering: function(){
		this.inherited(arguments);

		// Hide the portlet until it is fully constructed.
		dojo.style(this.domNode, "visibility", "hidden");
	},

	postCreate: function(){
		this.inherited(arguments);

		// Add the portlet classes
		dojo.addClass(this.domNode, "dojoxPortlet");
		dojo.removeClass(this.arrowNode, "dijitArrowNode");
		dojo.addClass(this.arrowNode, "dojoxPortletIcon dojoxArrowDown");
		dojo.addClass(this.titleBarNode, "dojoxPortletTitle");
		dojo.addClass(this.hideNode, "dojoxPortletContentOuter");

		// Choose the class to add depending on if the portlet is draggable or not.
		dojo.addClass(this.domNode, "dojoxPortlet-" + (!this.dragRestriction ? "movable" : "nonmovable"));

		var _this = this;
		if(this.resizeChildren){
			// If children should be resized	when the portlet size changes,
			// listen for items being dropped, when the window is resized,
			// or when another portlet's size changes.

			this.subscribe("/dnd/drop", function(){_this._updateSize();});

			this.subscribe("/Portlet/sizechange", function(widget){_this.onSizeChange(widget);});
			this.connect(window, "onresize", function(){_this._updateSize();});

			// Subscribe to all possible child-selection events that could affect this
			// portlet
			var doSelectSubscribe = dojo.hitch(this, function(id, lastId){
				var widget = dijit.byId(id);
				if(widget.selectChild){
					var s = this.subscribe(id + "-selectChild", function(child){
						var n = _this.domNode.parentNode;

						while(n){
							if(n == child.domNode){

								// Only fire this once, as the widget is now visible
								// at least once, so child measurements should be accurate.
								_this.unsubscribe(s);
								_this._updateSize();
								break;
							}
							n = n.parentNode;
						}
					});

					// Record the StackContainer and child widget that this portlet
					// is in, so it can figure out whether or not it is visible.
					// If it is not visible, it will not update it's size dynamically.
					var child = dijit.byId(lastId);
					if(widget && child){
						_this._parents.push({parent: widget, child: child});
					}
				}
			});
			var lastId;
			this._parents = [];

			// Find all parent widgets, and if they are StackContainers,
			// subscribe to their selectChild method calls.
			for(var p = this.domNode.parentNode; p != null; p = p.parentNode){
				var id = p.getAttribute ? p.getAttribute("widgetId") : null;
				if(id){
					doSelectSubscribe(id, lastId);
					lastId = id;
				}
			}
		}

		// Prevent clicks on icons from causing a drag to start.
		this.connect(this.titleBarNode, "onmousedown", function(evt){
			if (dojo.hasClass(evt.target, "dojoxPortletIcon")) {
				dojo.stopEvent(evt);
				return false;
			}
			return true;
		});

		// Inform all portlets that the size of this one has changed,
		// and therefore perhaps they have too
		this.connect(this._wipeOut, "onEnd", function(){_this._publish();});
		this.connect(this._wipeIn, "onEnd", function(){_this._publish();});

		if(this.closable){
			this.closeIcon = this._createIcon("dojoxCloseNode", "dojoxCloseNodeHover", dojo.hitch(this, "onClose"));
			dojo.style(this.closeIcon, "display", "");
		}
	},

	startup: function(){
		if(this._started){return;}

		var children = this.getChildren();
		this._placeSettingsWidgets();

		// Start up the children
		dojo.forEach(children, function(child){
			try{
				if(!child.started && !child._started){
					child.startup()
				}
			}
			catch(e){
				console.log(this.id + ":" + this.declaredClass, e);
			}
		});

		this.inherited(arguments);

		//this._updateSize();
		dojo.style(this.domNode, "visibility", "visible");
	},

	_placeSettingsWidgets: function(){
		// summary: Checks all the children to see if they are instances
		//		of dojox.widget.PortletSettings.	If they are,
		//		create an icon for them in the title bar which when clicked,
		//		calls their toggle() method.

		dojo.forEach(this.getChildren(), dojo.hitch(this, function(child){
			if(child.portletIconClass && child.toggle && !child.attr("portlet")){
				this._createIcon(child.portletIconClass, child.portletIconHoverClass, dojo.hitch(child, "toggle"));
				dojo.place(child.domNode, this.containerNode, "before");
				child.attr("portlet", this);
			}
		}));
	},

	_createIcon: function(clazz, hoverClazz, fn){
		// summary:
		//		creates an icon in the title bar.

		var icon = dojo.create("div",{
			"class": "dojoxPortletIcon " + clazz,
			"waiRole": "presentation"
		});
		dojo.place(icon, this.arrowNode, "before");

		this.connect(icon, "onclick", fn);

		if(hoverClazz){
			this.connect(icon, "onmouseover", function(){
				dojo.addClass(icon, hoverClazz);
			});
			this.connect(icon, "onmouseout", function(){
				dojo.removeClass(icon, hoverClazz);
			});
		}
		return icon;
	},

	onClose: function(evt){
		// summary:
		//		Hides the portlet. Note that it does not
		//		persist this, so it is up to the client to
		//		listen to this method and persist the closed state
		//		in their own way.
		dojo.style(this.domNode, "display", "none");
	},

	onSizeChange: function(widget){
		// summary:
		//		Updates the Portlet size if any other Portlet
		//		changes its size.
		if(widget == this){
			return;
		}
		this._updateSize();
	},

	_updateSize: function(){
		// summary:
		//		Updates the size of all child widgets.
		if(!this.open || !this._started || !this.resizeChildren){
			return;
		}

		if(this._timer){
			clearTimeout(this._timer);
		}
		// Delay applying the size change in case the size
		// changes very frequently, for performance reasons.
		this._timer = setTimeout(dojo.hitch(this, function(){
			var size ={
				w: dojo.style(this.domNode, "width"),
				h: dojo.style(this.domNode, "height")
			};

			// If the Portlet is in a StackWidget, and it is not
			// visible, do not update the size, as it could
			// make child widgets miscalculate.
			for(var i = 0; i < this._parents.length; i++){
				var p = this._parents[i];
				var sel = p.parent.selectedChildWidget
				if(sel && sel != p.child){
					return;
				}
			}

			if(this._size){
				// If the size of the portlet hasn't changed, don't
				// resize the children, as this can be expensive
				if(this._size.w == size.w && this._size.h == size.h){
					return;
				}
			}
			this._size = size;

			var fns = ["resize", "layout"];
			this._timer = null;
			var kids = this.getChildren();

			dojo.forEach(kids, function(child){
				for(var i = 0; i < fns.length; i++){
					if(dojo.isFunction(child[fns[i]])){
						try{
							child[fns[i]]();
						} catch(e){
							console.log(e);
						}
						break;
					}
				}
			});
			this.onUpdateSize();
		}), 100);
	},

	onUpdateSize: function(){
		// summary:
		//		Stub function called when the size is changed.
	},

	_publish: function(){
		// summary: Publishes an event that all other portlets listen to.
		//		This causes them to update their child widgets if their
		//		size has changed.
		dojo.publish("/Portlet/sizechange",[this]);
	},

	_onTitleClick: function(evt){
		if(evt.target == this.arrowNode){
			this.inherited(arguments);
		}
	},

	addChild: function(child){
		// summary:
		//		Adds a child widget to the portlet.
		this._size = null;
		this.inherited(arguments);

		if(this._started){
			this._placeSettingsWidgets();
			this._updateSize();
		}
		if(this._started && !child.started && !child._started){
			child.startup();
		}
	},

	_setCss: function(){
		this.inherited(arguments);
		dojo.style(this.arrowNode, "display", this.toggleable ? "":"none");
	}
});

dojo.declare("dojox.widget.PortletSettings", [dijit._Container, dijit.layout.ContentPane],{
	// summary:
	//		A settings widget to be used with a dojox.widget.Portlet.
	// description:
	//		This widget should be placed inside a dojox.widget.Portlet widget.
	//		It is used to set some preferences for that Portlet.	It is essentially
	//		a ContentPane, and should contain other widgets and DOM nodes that
	//		do the real work of setting preferences for the portlet.

	// portletIconClass: String
	//		The CSS class to apply to the icon in the Portlet title bar that is used
	//		to toggle the visibility of this widget.
	portletIconClass: "dojoxPortletSettingsIcon",

	// portletIconHoverClass: String
	//		The CSS class to apply to the icon in the Portlet title bar that is used
	//		to toggle the visibility of this widget when the mouse hovers over it.
	portletIconHoverClass: "dojoxPortletSettingsIconHover",

	postCreate: function(){
		// summary:
		//		Sets the require CSS classes on the widget.

		// Start the PortletSettings widget hidden, always.
		dojo.style(this.domNode, "display", "none");
		dojo.addClass(this.domNode, "dojoxPortletSettingsContainer");

		// Remove the unwanted content pane class.
		dojo.removeClass(this.domNode, "dijitContentPane");
	},

	_setPortletAttr: function(portlet){
		// summary:
		//		Sets the portlet that encloses this widget.
		this.portlet = portlet;
	},

	toggle: function(){
		// summary:
		//		Toggles the visibility of this widget.
		var n = this.domNode;
		if(dojo.style(n, "display") == "none"){
			dojo.style(n,{
				"display": "block",
				"height": "1px",
				"width": "auto"
			});
			dojo.fx.wipeIn({
				node: n
			}).play();
		}else{
			dojo.fx.wipeOut({
				node: n,
				onEnd: dojo.hitch(this, function(){
					dojo.style(n,{"display": "none", "height": "", "width":""});
				}
			)}).play();
		}
	}
});

dojo.declare("dojox.widget.PortletDialogSettings",
	dojox.widget.PortletSettings,{
	// summary:
	//		A settings widget to be used with a dojox.widget.Portlet, which displays
	//		the contents of this widget in a dijit.Dialog box.

	// dimensions: Array
	//		The size of the dialog to display.	This defaults to [300, 300]
	dimensions: null,

	constructor: function(props, node){
		this.dimensions = props.dimensions || [300, 100];
	},

	toggle: function(){
		// summary:
		//		Shows and hides the Dialog box.
		if(!this.dialog){
			dojo["require"]("dijit.Dialog");
			this.dialog = new dijit.Dialog({title: this.title});

			dojo.body().appendChild(this.dialog.domNode);

			// Move this widget inside the dialog
			this.dialog.containerNode.appendChild(this.domNode);

			dojo.style(this.dialog.domNode,{
				"width" : this.dimensions[0] + "px",
				"height" : this.dimensions[1] + "px"
			});
			dojo.style(this.domNode, "display", "");
		}
		if(this.dialog.open){
			this.dialog.hide();
		}else{
			this.dialog.show(this.domNode);
		}
	}
});
<|endoftext|>


<commit_before>'use strict';

//  ---------------------------------------------------------------------------

const Exchange = require ('./base/Exchange');
const { ExchangeError, InsufficientFunds, InvalidOrder, AuthenticationError, PermissionDenied, InvalidNonce, OrderNotFound, DDoSProtection } = require ('./base/errors');

//  ---------------------------------------------------------------------------

module.exports = class btcbox extends Exchange {
    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'btcbox',
            'name': 'BtcBox',
            'countries': [ 'JP' ],
            'rateLimit': 1000,
            'version': 'v1',
            'has': {
                'CORS': false,
                'fetchOrder': true,
                'fetchOrders': true,
                'fetchOpenOrders': true,
                'fetchTickers': false,
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/31275803-4df755a8-aaa1-11e7-9abb-11ec2fad9f2d.jpg',
                'api': 'https://www.btcbox.co.jp/api',
                'www': 'https://www.btcbox.co.jp/',
                'doc': 'https://www.btcbox.co.jp/help/asm',
                'fees': 'https://support.btcbox.co.jp/hc/en-us/articles/360001235694-Fees-introduction',
            },
            'api': {
                'public': {
                    'get': [
                        'depth',
                        'orders',
                        'ticker',
                    ],
                },
                'private': {
                    'post': [
                        'balance',
                        'trade_add',
                        'trade_cancel',
                        'trade_list',
                        'trade_view',
                        'wallet',
                    ],
                },
            },
            'markets': {
                'BTC/JPY': { 'id': 'btc', 'symbol': 'BTC/JPY', 'base': 'BTC', 'quote': 'JPY', 'baseId': 'btc', 'quoteId': 'jpy', 'taker': 0.05 / 100, 'maker': 0.05 / 100 },
                'ETH/JPY': { 'id': 'eth', 'symbol': 'ETH/JPY', 'base': 'ETH', 'quote': 'JPY', 'baseId': 'eth', 'quoteId': 'jpy', 'taker': 0.10 / 100, 'maker': 0.10 / 100 },
                'LTC/JPY': { 'id': 'ltc', 'symbol': 'LTC/JPY', 'base': 'LTC', 'quote': 'JPY', 'baseId': 'ltc', 'quoteId': 'jpy', 'taker': 0.10 / 100, 'maker': 0.10 / 100 },
                'BCH/JPY': { 'id': 'bch', 'symbol': 'BCH/JPY', 'base': 'BCH', 'quote': 'JPY', 'baseId': 'bch', 'quoteId': 'jpy', 'taker': 0.10 / 100, 'maker': 0.10 / 100 },
            },
            'exceptions': {
                '104': AuthenticationError,
                '105': PermissionDenied,
                '106': InvalidNonce,
                '107': InvalidOrder, // price should be an integer
                '200': InsufficientFunds,
                '201': InvalidOrder, // amount too small
                '202': InvalidOrder, // price should be [0 : 1000000]
                '203': OrderNotFound,
                '401': OrderNotFound, // cancel canceled, closed or non-existent order
                '402': DDoSProtection,
            },
        });
    }

    async fetchBalance (params = {}) {
        await this.loadMarkets ();
        let balances = await this.privatePostBalance ();
        let result = { 'info': balances };
        let currencies = Object.keys (this.currencies);
        for (let i = 0; i < currencies.length; i++) {
            let currency = currencies[i];
            let lowercase = currency.toLowerCase ();
            if (lowercase === 'dash')
                lowercase = 'drk';
            let account = this.account ();
            let free = lowercase + '_balance';
            let used = lowercase + '_lock';
            if (free in balances)
                account['free'] = parseFloat (balances[free]);
            if (used in balances)
                account['used'] = parseFloat (balances[used]);
            account['total'] = this.sum (account['free'], account['used']);
            result[currency] = account;
        }
        return this.parseBalance (result);
    }

    async fetchOrderBook (symbol, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let request = {};
        let numSymbols = this.symbols.length;
        if (numSymbols > 1)
            request['coin'] = market['baseId'];
        let orderbook = await this.publicGetDepth (this.extend (request, params));
        return this.parseOrderBook (orderbook);
    }

    parseTicker (ticker, market = undefined) {
        let timestamp = this.milliseconds ();
        let symbol = undefined;
        if (market)
            symbol = market['symbol'];
        let last = this.safeFloat (ticker, 'last');
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': this.safeFloat (ticker, 'high'),
            'low': this.safeFloat (ticker, 'low'),
            'bid': this.safeFloat (ticker, 'buy'),
            'bidVolume': undefined,
            'ask': this.safeFloat (ticker, 'sell'),
            'askVolume': undefined,
            'vwap': undefined,
            'open': undefined,
            'close': last,
            'last': last,
            'previousClose': undefined,
            'change': undefined,
            'percentage': undefined,
            'average': undefined,
            'baseVolume': this.safeFloat (ticker, 'vol'),
            'quoteVolume': this.safeFloat (ticker, 'volume'),
            'info': ticker,
        };
    }

    async fetchTicker (symbol, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let request = {};
        let numSymbols = this.symbols.length;
        if (numSymbols > 1)
            request['coin'] = market['baseId'];
        let ticker = await this.publicGetTicker (this.extend (request, params));
        return this.parseTicker (ticker, market);
    }

    parseTrade (trade, market) {
        let timestamp = parseInt (trade['date']) * 1000; // GMT time
        return {
            'info': trade,
            'id': trade['tid'],
            'order': undefined,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': market['symbol'],
            'type': undefined,
            'side': trade['type'],
            'price': trade['price'],
            'amount': trade['amount'],
        };
    }

    async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let request = {};
        let numSymbols = this.symbols.length;
        if (numSymbols > 1)
            request['coin'] = market['baseId'];
        let response = await this.publicGetOrders (this.extend (request, params));
        return this.parseTrades (response, market, since, limit);
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        const market = this.market (symbol);
        const request = {
            'amount': amount,
            'price': price,
            'type': side,
            'coin': market['baseId'],
        };
        const response = await this.privatePostTradeAdd (this.extend (request, params));
        //
        //     {
        //         "result":true,
        //         "id":"11"
        //     }
        //
        return this.parseOrder (response, market);
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        // a special case for btcbox – default symbol is BTC/JPY
        if (symbol === undefined) {
            symbol = 'BTC/JPY';
        }
        const market = this.market (symbol);
        const request = {
            'id': id,
            'coin': market['baseId'],
        };
        const response = await this.privatePostTradeCancel (this.extend (request, params));
        //
        //     {"result":true, "id":"11"}
        //
        return this.parseOrder (response, market);
    }

    parseOrderStatus (status) {
        const statuses = {
            // TODO: complete list
            'part': 'open', // partially or not at all executed
            'all': 'closed', // fully executed
            'cancelled': 'canceled',
            'closed': 'closed', // never encountered, seems to be bug in the doc
            'no': 'closed', // not clarified in the docs...
        };
        return this.safeString (statuses, status, status);
    }

    parseOrder (order, market = undefined) {
        //
        // {"id":11,"datetime":"2014-10-21 10:47:20","type":"sell","price":42000,"amount_original":1.2,"amount_outstanding":1.2,"status":"closed","trades":[]}
        //
        const id = this.safeString (order, 'id');
        const datetimeString = this.safeString (order, 'datetime');
        let timestamp = undefined;
        if (datetimeString !== undefined) {
            timestamp = this.parse8601 (order['datetime'] + '+09:00'); // Tokyo time
        }
        const amount = this.safeFloat (order, 'amount_original');
        const remaining = this.safeFloat (order, 'amount_outstanding');
        let filled = undefined;
        if (amount !== undefined) {
            if (remaining !== undefined) {
                filled = amount - remaining;
            }
        }
        const price = this.safeFloat (order, 'price');
        let cost = undefined;
        if (price !== undefined) {
            if (filled !== undefined) {
                cost = filled * price;
            }
        }
        // status is set by fetchOrder method only
        let status = this.parseOrderStatus (this.safeString (order, 'status'));
        // fetchOrders do not return status, use heuristic
        if (status === undefined)
            if (remaining !== undefined && remaining === 0)
                status = 'closed';
        let trades = undefined; // todo: this.parseTrades (order['trades']);
        let symbol = undefined;
        if (market !== undefined) {
            symbol = market['symbol'];
        }
        const side = this.safeString (order, 'type');
        return {
            'id': id,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'lastTradeTimestamp': undefined,
            'amount': amount,
            'remaining': remaining,
            'filled': filled,
            'side': side,
            'type': undefined,
            'status': status,
            'symbol': symbol,
            'price': price,
            'cost': cost,
            'trades': trades,
            'fee': undefined,
            'info': order,
        };
    }

    async fetchOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        // a special case for btcbox – default symbol is BTC/JPY
        if (symbol === undefined) {
            symbol = 'BTC/JPY';
        }
        const market = this.market (symbol);
        const request = this.extend ({
            'id': id,
            'coin': market['baseId'],
        }, params);
        const response = await this.privatePostTradeView (this.extend (request, params));
        return this.parseOrder (response, market);
    }

    async fetchOrdersByType (type, symbol = undefined, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        // a special case for btcbox – default symbol is BTC/JPY
        if (symbol === undefined) {
            symbol = 'BTC/JPY';
        }
        const market = this.market (symbol);
        const request = {
            'type': type, // 'open' or 'all'
            'coin': market['baseId'],
        };
        const response = await this.privatePostTradeList (this.extend (request, params));
        const orders = this.parseOrders (response, market, since, limit);
        // status (open/closed/canceled) is undefined
        // btcbox does not return status, but we know it's 'open' as we queried for open orders
        if (type === 'open') {
            for (let i = 0; i < orders.length; i++) {
                orders[i]['status'] = 'open';
            }
        }
        return orders;
    }

    async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        return await this.fetchOrdersByType ('all', symbol, since, limit, params);
    }

    async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        return await this.fetchOrdersByType ('open', symbol, since, limit, params);
    }

    nonce () {
        return this.milliseconds ();
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let url = this.urls['api'] + '/' + this.version + '/' + path;
        if (api === 'public') {
            if (Object.keys (params).length)
                url += '?' + this.urlencode (params);
        } else {
            this.checkRequiredCredentials ();
            let nonce = this.nonce ().toString ();
            let query = this.extend ({
                'key': this.apiKey,
                'nonce': nonce,
            }, params);
            let request = this.urlencode (query);
            let secret = this.hash (this.encode (this.secret));
            query['signature'] = this.hmac (this.encode (request), this.encode (secret));
            body = this.urlencode (query);
            headers = {
                'Content-Type': 'application/x-www-form-urlencoded',
            };
        }
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }

    handleErrors (httpCode, reason, url, method, headers, body, response) {
        // typical error response: {"result":false,"code":"401"}
        if (httpCode >= 400)
            return; // resort to defaultErrorHandler
        if (body[0] !== '{')
            return; // not json, resort to defaultErrorHandler
        const result = this.safeValue (response, 'result');
        if (result === undefined || result === true)
            return; // either public API (no error codes expected) or success
        const errorCode = this.safeValue (response, 'code');
        const feedback = this.id + ' ' + this.json (response);
        const exceptions = this.exceptions;
        if (errorCode in exceptions)
            throw new exceptions[errorCode] (feedback);
        throw new ExchangeError (feedback); // unknown message
    }
};
<commit_msg>btcbox cleanup for eslint curly<commit_after>'use strict';

//  ---------------------------------------------------------------------------

const Exchange = require ('./base/Exchange');
const { ExchangeError, InsufficientFunds, InvalidOrder, AuthenticationError, PermissionDenied, InvalidNonce, OrderNotFound, DDoSProtection } = require ('./base/errors');

//  ---------------------------------------------------------------------------

module.exports = class btcbox extends Exchange {
    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'btcbox',
            'name': 'BtcBox',
            'countries': [ 'JP' ],
            'rateLimit': 1000,
            'version': 'v1',
            'has': {
                'CORS': false,
                'fetchOrder': true,
                'fetchOrders': true,
                'fetchOpenOrders': true,
                'fetchTickers': false,
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/31275803-4df755a8-aaa1-11e7-9abb-11ec2fad9f2d.jpg',
                'api': 'https://www.btcbox.co.jp/api',
                'www': 'https://www.btcbox.co.jp/',
                'doc': 'https://www.btcbox.co.jp/help/asm',
                'fees': 'https://support.btcbox.co.jp/hc/en-us/articles/360001235694-Fees-introduction',
            },
            'api': {
                'public': {
                    'get': [
                        'depth',
                        'orders',
                        'ticker',
                    ],
                },
                'private': {
                    'post': [
                        'balance',
                        'trade_add',
                        'trade_cancel',
                        'trade_list',
                        'trade_view',
                        'wallet',
                    ],
                },
            },
            'markets': {
                'BTC/JPY': { 'id': 'btc', 'symbol': 'BTC/JPY', 'base': 'BTC', 'quote': 'JPY', 'baseId': 'btc', 'quoteId': 'jpy', 'taker': 0.05 / 100, 'maker': 0.05 / 100 },
                'ETH/JPY': { 'id': 'eth', 'symbol': 'ETH/JPY', 'base': 'ETH', 'quote': 'JPY', 'baseId': 'eth', 'quoteId': 'jpy', 'taker': 0.10 / 100, 'maker': 0.10 / 100 },
                'LTC/JPY': { 'id': 'ltc', 'symbol': 'LTC/JPY', 'base': 'LTC', 'quote': 'JPY', 'baseId': 'ltc', 'quoteId': 'jpy', 'taker': 0.10 / 100, 'maker': 0.10 / 100 },
                'BCH/JPY': { 'id': 'bch', 'symbol': 'BCH/JPY', 'base': 'BCH', 'quote': 'JPY', 'baseId': 'bch', 'quoteId': 'jpy', 'taker': 0.10 / 100, 'maker': 0.10 / 100 },
            },
            'exceptions': {
                '104': AuthenticationError,
                '105': PermissionDenied,
                '106': InvalidNonce,
                '107': InvalidOrder, // price should be an integer
                '200': InsufficientFunds,
                '201': InvalidOrder, // amount too small
                '202': InvalidOrder, // price should be [0 : 1000000]
                '203': OrderNotFound,
                '401': OrderNotFound, // cancel canceled, closed or non-existent order
                '402': DDoSProtection,
            },
        });
    }

    async fetchBalance (params = {}) {
        await this.loadMarkets ();
        const response = await this.privatePostBalance (params);
        const result = { 'info': response };
        const codes = Object.keys (this.currencies);
        for (let i = 0; i < codes.length; i++) {
            const code = codes[i];
            const currency = this.currency (code);
            const currencyId = currency['id'];
            const account = this.account ();
            const free = currencyId + '_balance';
            const used = currencyId + '_lock';
            account['free'] = this.safeFloat (response, free);
            account['used'] = this.safeFloat (response, used);
            account['total'] = this.sum (account['free'], account['used']);
            result[currency] = account;
        }
        return this.parseBalance (result);
    }

    async fetchOrderBook (symbol, limit = undefined, params = {}) {
        await this.loadMarkets ();
        const market = this.market (symbol);
        const request = {};
        const numSymbols = this.symbols.length;
        if (numSymbols > 1) {
            request['coin'] = market['baseId'];
        }
        const response = await this.publicGetDepth (this.extend (request, params));
        return this.parseOrderBook (response);
    }

    parseTicker (ticker, market = undefined) {
        const timestamp = this.milliseconds ();
        let symbol = undefined;
        if (market !== undefined) {
            symbol = market['symbol'];
        }
        const last = this.safeFloat (ticker, 'last');
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': this.safeFloat (ticker, 'high'),
            'low': this.safeFloat (ticker, 'low'),
            'bid': this.safeFloat (ticker, 'buy'),
            'bidVolume': undefined,
            'ask': this.safeFloat (ticker, 'sell'),
            'askVolume': undefined,
            'vwap': undefined,
            'open': undefined,
            'close': last,
            'last': last,
            'previousClose': undefined,
            'change': undefined,
            'percentage': undefined,
            'average': undefined,
            'baseVolume': this.safeFloat (ticker, 'vol'),
            'quoteVolume': this.safeFloat (ticker, 'volume'),
            'info': ticker,
        };
    }

    async fetchTicker (symbol, params = {}) {
        await this.loadMarkets ();
        const market = this.market (symbol);
        const request = {};
        const numSymbols = this.symbols.length;
        if (numSymbols > 1) {
            request['coin'] = market['baseId'];
        }
        const response = await this.publicGetTicker (this.extend (request, params));
        return this.parseTicker (response, market);
    }

    parseTrade (trade, market = undefined) {
        let timestamp = this.safeInteger (trade, 'date');
        if (timestamp !== undefined) {
            timestamp *= 1000; // GMT time
        }
        let symbol = undefined;
        if (market !== undefined) {
            symbol = market['symbol'];
        }
        const id = this.safeSting (trade, 'tid');
        const price = this.safeFloat (trade, 'price');
        const amount = this.safeFloat (trade, 'amount');
        let cost = undefined;
        if (amount !== undefined) {
            if (price !== undefined) {
                cost = price * amount;
            }
        }
        const type = undefined;
        const side = this.safeString (trade, 'type');
        return {
            'info': trade,
            'id': id,
            'order': undefined,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': symbol,
            'type': type,
            'side': side,
            'price': price,
            'amount': amount,
            'cost': cost,
        };
    }

    async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        const market = this.market (symbol);
        const request = {};
        const numSymbols = this.symbols.length;
        if (numSymbols > 1) {
            request['coin'] = market['baseId'];
        }
        const response = await this.publicGetOrders (this.extend (request, params));
        return this.parseTrades (response, market, since, limit);
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        const market = this.market (symbol);
        const request = {
            'amount': amount,
            'price': price,
            'type': side,
            'coin': market['baseId'],
        };
        const response = await this.privatePostTradeAdd (this.extend (request, params));
        //
        //     {
        //         "result":true,
        //         "id":"11"
        //     }
        //
        return this.parseOrder (response, market);
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        // a special case for btcbox – default symbol is BTC/JPY
        if (symbol === undefined) {
            symbol = 'BTC/JPY';
        }
        const market = this.market (symbol);
        const request = {
            'id': id,
            'coin': market['baseId'],
        };
        const response = await this.privatePostTradeCancel (this.extend (request, params));
        //
        //     {"result":true, "id":"11"}
        //
        return this.parseOrder (response, market);
    }

    parseOrderStatus (status) {
        const statuses = {
            // TODO: complete list
            'part': 'open', // partially or not at all executed
            'all': 'closed', // fully executed
            'cancelled': 'canceled',
            'closed': 'closed', // never encountered, seems to be bug in the doc
            'no': 'closed', // not clarified in the docs...
        };
        return this.safeString (statuses, status, status);
    }

    parseOrder (order, market = undefined) {
        //
        // {"id":11,"datetime":"2014-10-21 10:47:20","type":"sell","price":42000,"amount_original":1.2,"amount_outstanding":1.2,"status":"closed","trades":[]}
        //
        const id = this.safeString (order, 'id');
        const datetimeString = this.safeString (order, 'datetime');
        let timestamp = undefined;
        if (datetimeString !== undefined) {
            timestamp = this.parse8601 (order['datetime'] + '+09:00'); // Tokyo time
        }
        const amount = this.safeFloat (order, 'amount_original');
        const remaining = this.safeFloat (order, 'amount_outstanding');
        let filled = undefined;
        if (amount !== undefined) {
            if (remaining !== undefined) {
                filled = amount - remaining;
            }
        }
        const price = this.safeFloat (order, 'price');
        let cost = undefined;
        if (price !== undefined) {
            if (filled !== undefined) {
                cost = filled * price;
            }
        }
        // status is set by fetchOrder method only
        let status = this.parseOrderStatus (this.safeString (order, 'status'));
        // fetchOrders do not return status, use heuristic
        if (status === undefined) {
            if (remaining !== undefined && remaining === 0) {
                status = 'closed';
            }
        }
        let trades = undefined; // todo: this.parseTrades (order['trades']);
        let symbol = undefined;
        if (market !== undefined) {
            symbol = market['symbol'];
        }
        const side = this.safeString (order, 'type');
        return {
            'id': id,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'lastTradeTimestamp': undefined,
            'amount': amount,
            'remaining': remaining,
            'filled': filled,
            'side': side,
            'type': undefined,
            'status': status,
            'symbol': symbol,
            'price': price,
            'cost': cost,
            'trades': trades,
            'fee': undefined,
            'info': order,
        };
    }

    async fetchOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        // a special case for btcbox – default symbol is BTC/JPY
        if (symbol === undefined) {
            symbol = 'BTC/JPY';
        }
        const market = this.market (symbol);
        const request = this.extend ({
            'id': id,
            'coin': market['baseId'],
        }, params);
        const response = await this.privatePostTradeView (this.extend (request, params));
        return this.parseOrder (response, market);
    }

    async fetchOrdersByType (type, symbol = undefined, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        // a special case for btcbox – default symbol is BTC/JPY
        if (symbol === undefined) {
            symbol = 'BTC/JPY';
        }
        const market = this.market (symbol);
        const request = {
            'type': type, // 'open' or 'all'
            'coin': market['baseId'],
        };
        const response = await this.privatePostTradeList (this.extend (request, params));
        const orders = this.parseOrders (response, market, since, limit);
        // status (open/closed/canceled) is undefined
        // btcbox does not return status, but we know it's 'open' as we queried for open orders
        if (type === 'open') {
            for (let i = 0; i < orders.length; i++) {
                orders[i]['status'] = 'open';
            }
        }
        return orders;
    }

    async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        return await this.fetchOrdersByType ('all', symbol, since, limit, params);
    }

    async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        return await this.fetchOrdersByType ('open', symbol, since, limit, params);
    }

    nonce () {
        return this.milliseconds ();
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let url = this.urls['api'] + '/' + this.version + '/' + path;
        if (api === 'public') {
            if (Object.keys (params).length) {
                url += '?' + this.urlencode (params);
            }
        } else {
            this.checkRequiredCredentials ();
            const nonce = this.nonce ().toString ();
            const query = this.extend ({
                'key': this.apiKey,
                'nonce': nonce,
            }, params);
            const request = this.urlencode (query);
            const secret = this.hash (this.encode (this.secret));
            query['signature'] = this.hmac (this.encode (request), this.encode (secret));
            body = this.urlencode (query);
            headers = {
                'Content-Type': 'application/x-www-form-urlencoded',
            };
        }
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }

    handleErrors (httpCode, reason, url, method, headers, body, response) {
        if (response === undefined) {
            return; // resort to defaultErrorHandler
        }
        // typical error response: {"result":false,"code":"401"}
        if (httpCode >= 400) {
            return; // resort to defaultErrorHandler
        }
        const result = this.safeValue (response, 'result');
        if (result === undefined || result === true) {
            return; // either public API (no error codes expected) or success
        }
        const errorCode = this.safeValue (response, 'code');
        const feedback = this.id + ' ' + this.json (response);
        const exceptions = this.exceptions;
        if (errorCode in exceptions) {
            throw new exceptions[errorCode] (feedback);
        }
        throw new ExchangeError (feedback); // unknown message
    }
};
<|endoftext|>


<commit_before>'use strict';

module.exports = {
	db: 'mongodb://localhost/mean-survey-dev',
	app: {
		title: 'Mean Survey - Development Environment'
	},
	facebook: {
		clientID: process.env.FACEBOOK_ID || 'APP_ID',
		clientSecret: process.env.FACEBOOK_SECRET || 'APP_SECRET',
		callbackURL: '/auth/facebook/callback'
	},
	twitter: {
		clientID: process.env.TWITTER_KEY || 'CONSUMER_KEY',
		clientSecret: process.env.TWITTER_SECRET || 'CONSUMER_SECRET',
		callbackURL: '/auth/twitter/callback'
	},
	google: {
		clientID: process.env.GOOGLE_ID || 'APP_ID',
		clientSecret: process.env.GOOGLE_SECRET || 'APP_SECRET',
		callbackURL: '/auth/google/callback'
	},
	linkedin: {
		clientID: process.env.LINKEDIN_ID || 'APP_ID',
		clientSecret: process.env.LINKEDIN_SECRET || 'APP_SECRET',
		callbackURL: '/auth/linkedin/callback'
	},
	github: {
		clientID: process.env.GITHUB_ID || 'APP_ID',
		clientSecret: process.env.GITHUB_SECRET || 'APP_SECRET',
		callbackURL: '/auth/github/callback'
	},
	mailer: {
		from: process.env.MAILER_FROM || 'MAILER_FROM',
		options: {
			service: process.env.MAILER_SERVICE_PROVIDER || 'MAILER_SERVICE_PROVIDER',
			auth: {
				user: process.env.MAILER_EMAIL_ID || 'MAILER_EMAIL_ID',
				pass: process.env.MAILER_PASSWORD || 'MAILER_PASSWORD'
			}
		}
	}
};
<commit_msg>change configuration for deploy in cloud<commit_after>'use strict';

module.exports = {
	db: process.env.MONGOHQ_URL || process.env.MONGOLAB_URI || 'mongodb://' + (process.env.DB_1_PORT_27017_TCP_ADDR || 'localhost') + '/mean-survey',
	app: {
		title: 'Mean Survey - Development Environment'
	},
	facebook: {
		clientID: process.env.FACEBOOK_ID || 'APP_ID',
		clientSecret: process.env.FACEBOOK_SECRET || 'APP_SECRET',
		callbackURL: '/auth/facebook/callback'
	},
	twitter: {
		clientID: process.env.TWITTER_KEY || 'CONSUMER_KEY',
		clientSecret: process.env.TWITTER_SECRET || 'CONSUMER_SECRET',
		callbackURL: '/auth/twitter/callback'
	},
	google: {
		clientID: process.env.GOOGLE_ID || 'APP_ID',
		clientSecret: process.env.GOOGLE_SECRET || 'APP_SECRET',
		callbackURL: '/auth/google/callback'
	},
	linkedin: {
		clientID: process.env.LINKEDIN_ID || 'APP_ID',
		clientSecret: process.env.LINKEDIN_SECRET || 'APP_SECRET',
		callbackURL: '/auth/linkedin/callback'
	},
	github: {
		clientID: process.env.GITHUB_ID || 'APP_ID',
		clientSecret: process.env.GITHUB_SECRET || 'APP_SECRET',
		callbackURL: '/auth/github/callback'
	},
	mailer: {
		from: process.env.MAILER_FROM || 'MAILER_FROM',
		options: {
			service: process.env.MAILER_SERVICE_PROVIDER || 'MAILER_SERVICE_PROVIDER',
			auth: {
				user: process.env.MAILER_EMAIL_ID || 'MAILER_EMAIL_ID',
				pass: process.env.MAILER_PASSWORD || 'MAILER_PASSWORD'
			}
		}
	}
};
<|endoftext|>


<commit_before>'use strict';

module.exports = {
 db: (process.env.MONGODB_URI || 'mongodb://localhost/icu-dev'),
  debug: true,
  logging: {
    format: 'tiny'
  },
  //  aggregate: 'whatever that is not false, because boolean false value turns aggregation off', //false
  aggregate: false,
  mongoose: {
    debug: false
  },
  app: {
    //Made By OHAD - name: 'MEAN - FullStack JS - Development'
    name: 'ICU'
  },
  //hostname: 'http://192.168.245.152:3000',
  host: 'http://localhost:3000',
  facebook: {
    clientID: 'DEFAULT_APP_ID',
    clientSecret: 'APP_SECRET',
    callbackURL: 'http://localhost:3000/api/auth/facebook/callback'
  },
  twitter: {
    clientID: 'DEFAULT_CONSUMER_KEY',
    clientSecret: 'CONSUMER_SECRET',
    callbackURL: 'http://localhost:3000/api/auth/twitter/callback'
  },
  github: {
    clientID: 'DEFAULT_APP_ID',
    clientSecret: 'APP_SECRET',
    callbackURL: 'http://localhost:3000/api/auth/github/callback'
  },
  google: {
    clientID: 'DEFAULT_APP_ID',
    clientSecret: 'APP_SECRET',
    callbackURL: 'http://localhost:3000/api/auth/google/callback'
  },
  linkedin: {
    clientID: 'DEFAULT_API_KEY',
    clientSecret: 'SECRET_KEY',
    callbackURL: 'http://localhost:3000/api/auth/linkedin/callback'
  },
  emailFrom: 'SENDER EMAIL ADDRESS', // sender address like ABC <abc@example.com>
  mailer: {
    service: 'SMTP', // Gmail, SMTP
    host: 'smtp.gmail.com', //in case of SMTP
    port: 465, // in case of SMTP
    secure: true, // in case of SMTP
    auth: {
      user: 'EMAIL_ID',
      pass: 'PASSWORD'
    }
  },
//   mailer: {
//     service: 'SMTP', // Gmail, SMTP
//     host: 'localhost', //in case of SMTP
//     port: 25, // in case of SMTP
//     secure: false, // in case of SMTP
//     tls: false, // in case of SMTP
//     ignoreTLS: true
//   },
//   mailer: {
//     service: 'SERVICE_PROVIDER', // Gmail, SMTP
//     auth: {
//       user: 'EMAIL_ID',
//       pass: 'PASSWORD'
//     }
//   },
  secret: 'SOME_TOKEN_SECRET',
    api: {
      uri: 'http://192.168.245.152:3003'
    },
//   elasticsearch: {
//     host: 'http://192.168.245.255',
//     port: 9200,
//     log: 'trace'
//     },
  elasticsearch: {
    host: 'http://localhost',
    port: 9200,
    log: 'trace',
    keepAlive: false,
    sniffOnConnectionFault:true,
    maxRetries:50
  },
//   elasticsearch: {
//     host: 'http://192.168.245.152',
//     port: 3003,
//     log: 'trace'
//   },
//   elasticsearch: {
//     host: 'http://192.168.245.152',
//     port: 9300,
//     log: 'trace'
//   },
  letschat: {
    owner: '562334ccea168c4f323a1be8'
  },
  circles: {
    uri: 'http://localhost:3005'
  }
};
<commit_msg>Add rocketChat to development.js<commit_after>'use strict';

module.exports = {
 db: (process.env.MONGODB_URI || 'mongodb://localhost/icu-dev'),
  debug: true,
  logging: {
    format: 'tiny'
  },
  //  aggregate: 'whatever that is not false, because boolean false value turns aggregation off', //false
  aggregate: false,
  mongoose: {
    debug: false
  },
  app: {
    //Made By OHAD - name: 'MEAN - FullStack JS - Development'
    name: 'ICU'
  },
  //hostname: 'http://192.168.245.152:3000',
  host: 'http://localhost:3000',
  facebook: {
    clientID: 'DEFAULT_APP_ID',
    clientSecret: 'APP_SECRET',
    callbackURL: 'http://localhost:3000/api/auth/facebook/callback'
  },
  twitter: {
    clientID: 'DEFAULT_CONSUMER_KEY',
    clientSecret: 'CONSUMER_SECRET',
    callbackURL: 'http://localhost:3000/api/auth/twitter/callback'
  },
  github: {
    clientID: 'DEFAULT_APP_ID',
    clientSecret: 'APP_SECRET',
    callbackURL: 'http://localhost:3000/api/auth/github/callback'
  },
  google: {
    clientID: 'DEFAULT_APP_ID',
    clientSecret: 'APP_SECRET',
    callbackURL: 'http://localhost:3000/api/auth/google/callback'
  },
  linkedin: {
    clientID: 'DEFAULT_API_KEY',
    clientSecret: 'SECRET_KEY',
    callbackURL: 'http://localhost:3000/api/auth/linkedin/callback'
  },
  emailFrom: 'SENDER EMAIL ADDRESS', // sender address like ABC <abc@example.com>
  mailer: {
    service: 'SMTP', // Gmail, SMTP
    host: 'smtp.gmail.com', //in case of SMTP
    port: 465, // in case of SMTP
    secure: true, // in case of SMTP
    auth: {
      user: 'EMAIL_ID',
      pass: 'PASSWORD'
    }
  },
//   mailer: {
//     service: 'SMTP', // Gmail, SMTP
//     host: 'localhost', //in case of SMTP
//     port: 25, // in case of SMTP
//     secure: false, // in case of SMTP
//     tls: false, // in case of SMTP
//     ignoreTLS: true
//   },
//   mailer: {
//     service: 'SERVICE_PROVIDER', // Gmail, SMTP
//     auth: {
//       user: 'EMAIL_ID',
//       pass: 'PASSWORD'
//     }
//   },
  secret: 'SOME_TOKEN_SECRET',
    api: {
      uri: 'http://192.168.245.152:3003'
    },
//   elasticsearch: {
//     host: 'http://192.168.245.255',
//     port: 9200,
//     log: 'trace'
//     },
  elasticsearch: {
    host: 'http://localhost',
    port: 9200,
    log: 'trace',
    keepAlive: false,
    sniffOnConnectionFault:true,
    maxRetries:50
  },
//   elasticsearch: {
//     host: 'http://192.168.245.152',
//     port: 3003,
//     log: 'trace'
//   },
//   elasticsearch: {
//     host: 'http://192.168.245.152',
//     port: 9300,
//     log: 'trace'
//   },
  letschat: {
    owner: '562334ccea168c4f323a1be8'
  },
  circles: {
    uri: 'http://localhost:3005'
  },
  rocketChat: {
    uri: 'http://localhost:3005'
  }
};
<|endoftext|>


<commit_before>zaa.factory('ApiCmsCat', function($resource) {
	return $resource('admin/api-cms-cat/:id');
});

zaa.factory('ApiCmsBlock', function($resource) {
	return $resource('admin/api-cms-block/:id');
});

zaa.factory('CmsLayoutService', function($resource) {
	var service = [];

	service.data = [];

	service.resource = $resource('admin/api-cms-layout/:id');

	service.load = function() {
		service.data = service.resource.query();
	}

	return service;
});

zaa.factory('ApiCmsNavItemPageBlockItem', function($resource) {
	return $resource('admin/api-cms-navitempageblockitem/:id', { id : '@_id' }, {
		save : {
			method : 'POST',
			isArray : false,
			headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}
		},
		update : {
			method : 'PUT',
			isArray : false,
			headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}
		},
		'delete' : {
			method : 'DELETE'
		}
	});
});

zaa.factory('PlaceholderService', function() {
	var service = [];

	service.status = 0; /* 1 = showplaceholders; 0 = hide placeholders */

	service.delegate = function(status) {
		service.status = status;
	}

	return service;
})

zaa.factory('DroppableBlocksService', function($http) {
	var service = [];

	service.blocks = [];

	service.load = function() {
		if (service.blocks.length == 0) { /* do not reload block data if there is already. what about force reload? */
			$http({
				url : 'admin/api-cms-admin/get-all-blocks',
				method : 'GET'
			}).success(function(response) {
				service.blocks = response;
			});
		}
	};

	return service;
});<commit_msg>fixed #243<commit_after>zaa.factory('ApiCmsCat', function($resource) {
	return $resource('admin/api-cms-cat/:id');
});

zaa.factory('ApiCmsBlock', function($resource) {
	return $resource('admin/api-cms-block/:id');
});

zaa.factory('CmsLayoutService', function($resource) {
	var service = [];

	service.data = [];

	service.resource = $resource('admin/api-cms-layout/:id');

	service.load = function() {
		service.data = service.resource.query();
	}

	return service;
});

zaa.factory('ApiCmsNavItemPageBlockItem', function($resource) {
	return $resource('admin/api-cms-navitempageblockitem/:id', { id : '@_id' }, {
		save : {
			method : 'POST',
			isArray : false,
			headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}
		},
		update : {
			method : 'PUT',
			isArray : false,
			headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}
		},
		'delete' : {
			method : 'DELETE'
		}
	});
});

zaa.factory('PlaceholderService', function() {
	var service = [];

	service.status = 1; /* 1 = showplaceholders; 0 = hide placeholders */

	service.delegate = function(status) {
		service.status = status;
	}

	return service;
})

zaa.factory('DroppableBlocksService', function($http) {
	var service = [];

	service.blocks = [];

	service.load = function() {
		if (service.blocks.length == 0) { /* do not reload block data if there is already. what about force reload? */
			$http({
				url : 'admin/api-cms-admin/get-all-blocks',
				method : 'GET'
			}).success(function(response) {
				service.blocks = response;
			});
		}
	};

	return service;
});<|endoftext|>


<commit_before>(function (env) {
    "use strict";
    env.ddg_spice_npm = function(api_result){

        if (api_result.error) {
            return;
        }

        Spice.add({
            id: "npm",
            name: "NPM",
            data: api_result,
            meta: {
                sourceName: "npmjs.org",
                sourceUrl: 'http://npmjs.org/package/' + api_result.name
            },
            templates: {
                detail: Spice.npm.detail
            }
        });
    };
}(this));<commit_msg>Add Spice.failed()<commit_after>(function (env) {
    "use strict";
    env.ddg_spice_npm = function(api_result){

        if (api_result.error) {
            return Spice.failed('npm');
        }

        Spice.add({
            id: "npm",
            name: "NPM",
            data: api_result,
            meta: {
                sourceName: "npmjs.org",
                sourceUrl: 'http://npmjs.org/package/' + api_result.name
            },
            templates: {
                detail: Spice.npm.detail
            }
        });
    };
}(this));
<|endoftext|>


<commit_before>
var mongo = require(__dirname + '/../lib/database');

var config = require(__dirname + '/../_config_');

var worker = require('tweets-mongodb-parser');

mongo.get().then(function(db) {
    process.nextTick(function() {
    	new worker(db, {
    		creds : config.twitterCreds,
    		match : config.tweet_processor_match,
    		check_interval : config.tweet_processor_interval,
    		batch_size : config.tweet_processor_batch_size,
    		account_blacklist : config.tweet_processor_account_blacklist,
    	}).start();
    });
}, function(err) {
	throw err;
});
<commit_msg>parse twitter streaming API in addition to search API to ensure maximum retention<commit_after>
var mongo = require(__dirname + '/../lib/database');

var config = require(__dirname + '/../_config_');

var worker = require('tweets-mongodb-parser');

var Twit = require('twit');

function parseTwitterDate(text)
{
	return new Date(Date.parse(text.replace(/( +)/, ' UTC$1')));
}

mongo.get().then(function(db) {
    process.nextTick(function() {

    	// poll search API

    	new worker(db, {
    		creds : config.twitterCreds,
    		match : config.tweet_processor_match.join(' OR '),
    		check_interval : config.tweet_processor_interval,
    		batch_size : config.tweet_processor_batch_size,
    		account_blacklist : config.tweet_processor_account_blacklist,
    	}).start();

    	// watch stream API as well, to scrape up anything the search API misses

    	var twit = new Twit(config.twitterCreds);
		var stream = twit.stream('statuses/filter', { track : config.tweet_processor_match.join(',') });
		var coll = db.collection('tweets');

		var u, tweet;

		stream.on('tweet', function(status) {
			u = status.user;
			tweet = {
				_id : status.id_str,
				id_str: status.id_str,
				created_at : parseTwitterDate(status.created_at),
				text : status.text,
				user : {
					id : u.id,
					name : u.name,
					screen_name : u.screen_name,
					location : u.location,
					description : u.description,
					url : u.url,
					followers_count : u.followers_count,
					friends_count : u.friends_count,
					time_zone : u.time_zone,
					profile_image_url : u.profile_image_url.replace(/^https?:/i, ''),
				}
			};

			coll.save(tweet, { w : 0 });
		});

		stream.on('limit', function(message) {
			// log something if we are rate limited. The client will adjust automatically to compensate.
			console.warn('Exceeded stream limit - missed ' + message.limit.track + ' tweets');
		});
    });
}, function(err) {
	throw err;
});
<|endoftext|>