<commit_before>import Promise from 'bluebird';
import pgDriver from 'pg';
import debug from './debug';
import makeAsyncApi from './makeAsyncApi';
import SqlTag from './sql';

export {sqlStr, literal, identifier} from './sql';
export const SQL = SqlTag;

function checkAsyncFunction(asyncFunc) {
  if (typeof asyncFunc !== 'function')
    throw new TypeError('async function expected');
}

export default class PgAsync {
  constructor(connectionOptions, driver) {
    this.setConnectionOptions(connectionOptions);
    this.setDriver(driver);

    const wrap = name => {
      this[name] = (sql, ...values) =>
        this.connect(client => client[`${name}Args`](sql, values));
    };
    const wrapArgs = name => {
      this[name] = (sql, values) =>
        this.connect(client => client[name](sql, values));
    };

    wrap('query');
    wrapArgs('queryArgs');

    wrap('rows');
    wrapArgs('rowsArgs');

    wrap('row');
    wrapArgs('rowArgs');

    wrap('value');
    wrapArgs('valueArgs');
  }

  static SQL = SqlTag;
  SQL = SqlTag;

  setConnectionOptions(options) {
    this._connectionOptions = options;
    return this;
  }

  getConnectionOptions() {
    return this._connectionOptions || this.getDriver().defaults;
  }

  getDriver() {
    return this._driver;
  }

  setDriver(driver) {
    if (typeof driver === 'string')
      switch (driver) {
        case '': case 'pg':
          driver = pgDriver;
          break;
        case 'native': case 'pg.native':
          driver = pgDriver.native;
          break;
        default:
          throw new Error(`Unrecognized driver name: ${driver}`);
      }
    this._driver = driver || pgDriver;
    return this;
  }

  async getClient() {
    return new Promise((resolve, reject) => {
      this.getDriver().connect(this.getConnectionOptions(), (err, client, done) => {
        if (err) {
          debug('%s getClient(%j)', err, this.getConnectionOptions());
          if (done) done(err);
          return reject(err);
        }
        return resolve({
          client,
          done: () => {
            debug('Client released');
            done();
          }
        });
      });
    });
  }

  async connect(asyncFunc) {
    checkAsyncFunction(asyncFunc);

    const {client, done} = await this.getClient();
    try {
      const api = makeAsyncApi(client);
      const result = await asyncFunc(api);
      await api._end();
      done();
      return result;
    } catch (err) {
      done(err);
      throw err;
    }
  }

  async transaction(asyncFunc) {
    checkAsyncFunction(asyncFunc);

    return await this.connect(async (client) => {
      client.checkSerialAccess = true;
      await client.startTransaction();
      try {
        const result = await asyncFunc(client);
        await client.commit();
        return result;
      } catch (err) {
        try {
          await client.rollback();
        } catch (_) {
          // client disconnected?
        }
        throw err;
      }
    });
  }

  closeConnections = () => this.getDriver().end();

}
<commit_msg>Fix babel@6.5.2<commit_after>import Promise from 'bluebird';
import pgDriver from 'pg';
import debug from './debug';
import makeAsyncApi from './makeAsyncApi';
import SqlTag from './sql';

export {sqlStr, literal, identifier} from './sql';
export const SQL = SqlTag;

function checkAsyncFunction(asyncFunc) {
  if (typeof asyncFunc !== 'function')
    throw new TypeError('async function expected');
}

export default class PgAsync {
  constructor(connectionOptions, driver) {
    this.setConnectionOptions(connectionOptions);
    this.setDriver(driver);

    const self = this;
    const wrap = name => {
      self[name] = (sql, ...values) =>
        self.connect(client => client[`${name}Args`](sql, values));
    };
    const wrapArgs = name => {
      self[name] = (sql, values) =>
        self.connect(client => client[name](sql, values));
    };

    wrap('query');
    wrapArgs('queryArgs');

    wrap('rows');
    wrapArgs('rowsArgs');

    wrap('row');
    wrapArgs('rowArgs');

    wrap('value');
    wrapArgs('valueArgs');
  }

  static SQL = SqlTag;
  SQL = SqlTag;

  setConnectionOptions(options) {
    this._connectionOptions = options;
    return this;
  }

  getConnectionOptions() {
    return this._connectionOptions || this.getDriver().defaults;
  }

  getDriver() {
    return this._driver;
  }

  setDriver(driver) {
    if (typeof driver === 'string')
      switch (driver) {
        case '': case 'pg':
          driver = pgDriver;
          break;
        case 'native': case 'pg.native':
          driver = pgDriver.native;
          break;
        default:
          throw new Error(`Unrecognized driver name: ${driver}`);
      }
    this._driver = driver || pgDriver;
    return this;
  }

  async getClient() {
    return new Promise((resolve, reject) => {
      this.getDriver().connect(this.getConnectionOptions(), (err, client, done) => {
        if (err) {
          debug('%s getClient(%j)', err, this.getConnectionOptions());
          if (done) done(err);
          return reject(err);
        }
        return resolve({
          client,
          done: () => {
            debug('Client released');
            done();
          }
        });
      });
    });
  }

  async connect(asyncFunc) {
    checkAsyncFunction(asyncFunc);

    const {client, done} = await this.getClient();
    try {
      const api = makeAsyncApi(client);
      const result = await asyncFunc(api);
      await api._end();
      done();
      return result;
    } catch (err) {
      done(err);
      throw err;
    }
  }

  async transaction(asyncFunc) {
    checkAsyncFunction(asyncFunc);

    return await this.connect(async (client) => {
      client.checkSerialAccess = true;
      await client.startTransaction();
      try {
        const result = await asyncFunc(client);
        await client.commit();
        return result;
      } catch (err) {
        try {
          await client.rollback();
        } catch (_) {
          // client disconnected?
        }
        throw err;
      }
    });
  }

  closeConnections = () => this.getDriver().end();

}
<|endoftext|>


<commit_before>require('./opal.js');
require('./nodejs.js');
require('./pathname.js');
require('./base64.js');
require('./open-uri.js');
require('./stringio.js');

module.exports.Opal = Opal;
<commit_msg>Fix linter<commit_after>/* global Opal */
require('./opal.js');
require('./nodejs.js');
require('./pathname.js');
require('./base64.js');
require('./open-uri.js');
require('./stringio.js');

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


<commit_before><commit_msg>Implement exporting libraries<commit_after>import Cafe from './cafe.js';
import Room from './room.js';
import User from './user.js';
import Message from './message.js';

import uploadImage from './uploadImage.js';
import Credentials from './credentials.js';
import Config from './config.js';
import Translate from './translate.js';

import RawSession from './rawSession.js';
import CommandSession from './commandSession.js';
import Session from './session.js';

export {
  Cafe, Room, User, Message,
  uploadImage, Credentials, Config, Translate,
  RawSession, CommandSession, Session
};

export default Session;
<|endoftext|>


<commit_before>// @flow

import React, { Component } from 'react';
import {
  StyleSheet,
  Platform,
  View,
  TextInput,
} from 'react-native';

const omit = (obj, keys) => Object.keys(obj)
  .filter((key) => keys.indexOf(key) < 0)
  .reduce((newObj, key) => Object.assign(newObj, { [key]: obj[key] }), {})

type Props = {
  maxHeight?: number;
  minHeight?: number;
  style: View.propTypes.style;
  onResized?: () => void;
  value: ?string;
};

type State = {
  limit: ?number;
  height: number;
};

export default class AutoGrowTextInput extends React.Component {
  props: Props;
  state: State;

  constructor(props: Props) {
    super(props);

    let limit = null;

    if (this.props.maxLines) {
      limit = this.props.maxHeight;
    }

    this.state = {
      limit,
      height: this._minHeight()
    };
  }

  render() {
    const newProps = omit({
      ...this.props,
      ...Platform.select({
        ios: {
          onContentSizeChange: this._onContentSizeChange,
        },
        android: {
          onChange: this._onContentSizeChange
        },
      }),
    }, [ 'style', 'maxLines' ]);

    const externalStyle = this.props.style;
    const textInputStyle = {
      height: this.state.height
    };

    return (
      <TextInput
        { ...newProps }
        multiline={ true }
        style={[ externalStyle, textInputStyle ]}
      />
    );
  }

  _onContentSizeChange = (event) => {
    const { contentSize } = event.nativeEvent;
    const height = this._calcHeight(contentSize.height, this.state.limit);

    if (height === this.state.height) {
      return;
    }
    this.setState({ height });
    this.props.onResized && this.props.onResized();
  }

  _calcHeight(actualHeight: number, limit:? number) {
    return limit
      ? Math.min(limit, actualHeight)
      : Math.max(this._minHeight(), actualHeight);
  }

  _minHeight() {
    return this.props.minHeight || 30;
  }
};
<commit_msg>added shrinkIfEmpty<commit_after>// @flow

import React, { Component } from 'react';
import {
  StyleSheet,
  Platform,
  View,
  TextInput,
} from 'react-native';

const omit = (obj, keys) => Object.keys(obj)
  .filter((key) => keys.indexOf(key) < 0)
  .reduce((newObj, key) => Object.assign(newObj, { [key]: obj[key] }), {})

type Props = {
  maxHeight?: number;
  minHeight?: number;
  style: View.propTypes.style;
  onResized?: () => void;
  value: ?string;
  shrinkIfEmpty?: boolean;
};

type State = {
  limit: ?number;
  height: number;
};

export default class AutoGrowTextInput extends React.Component {
  props: Props;
  state: State;

  constructor(props: Props) {
    super(props);

    let limit = null;

    if (this.props.maxLines) {
      limit = this.props.maxHeight;
    }

    this.state = {
      limit,
      height: this._minHeight()
    };
  }

  render() {
    const newProps = omit({
      ...this.props,
      ...Platform.select({
        ios: {
          onContentSizeChange: this._onContentSizeChange,
        },
        android: {
          onChange: this._onContentSizeChange
        },
      }),
    }, [ 'style', 'maxLines' ]);

    const { value, shrinkIfEmpty } = newProps;

    const externalStyle = this.props.style;
    const textInputStyle = {
      height: (shrinkIfEmpty && value === '')
        ? this._minHeight()
        : this.state.height
    };

    return (
      <TextInput
        { ...newProps }
        multiline={ true }
        style={[ externalStyle, textInputStyle ]}
      />
    );
  }

  _onContentSizeChange = (event) => {
    const { contentSize } = event.nativeEvent;
    const height = this._calcHeight(contentSize.height, this.state.limit);

    if (height === this.state.height) {
      return;
    }
    this.setState({ height });
    this.props.onResized && this.props.onResized();
  }

  _calcHeight(actualHeight: number, limit:? number) {
    return limit
      ? Math.min(limit, actualHeight)
      : Math.max(this._minHeight(), actualHeight);
  }

  _minHeight() {
    return this.props.minHeight || 30;
  }
};
<|endoftext|>


<commit_before>var express = require('express');
var morgan = require('morgan');
var bodyParser = require('body-parser');
var helmet = require('helmet');

// Config variables.
var VROOM_PATH = '';
var MAX_LOCATION_NUMBER = 50;
var ROUTE_GEOMETRY = false;
var USE_OSRM_V5 = true;
var USE_LIBOSRM = true;
var OSRM_ADDRESS = "0.0.0.0";
var OSRM_PORT = "5000";
var ALLOW_OPTIONS_OVERRIDE = true; // -g only so far.

// App and loaded modules.
var app = express();

// Enable cross-origin ressource sharing.
app.use(function(req, res, next){
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers",
             "Origin, X-Requested-With, Content-Type, Accept");
  next();
});

app.use(bodyParser.json());
app.use(morgan('combined'));
app.use(helmet());

// Callback for size and some input validity checks.
var cb_size_check = function (req, res, next){
  res.setHeader('Content-Type', 'application/json');

  var correct_input = ('jobs' in req.body)
      && ('vehicles' in req.body)
      && (req.body['vehicles'].length >= 1);

  if(!correct_input){
    res.send({code: 1, error: 'Invalid query.'});
    return;
  }

  var nb_locs = req.body['jobs'].length;
  if('start' in req.body['vehicles'][0]){
    nb_locs += 1;
  }
  if('end' in req.body['vehicles'][0]){
    nb_locs += 1;
  }
  if(nb_locs > MAX_LOCATION_NUMBER){
    console.log('Too many locs in query (' + nb_locs + ')');
    res.send({code: 1, error: 'Too many locations.'});
    return;
  }
  next();
}

// Cli wrapper and associated callback.
var exec = require('child_process').exec;

var command = VROOM_PATH + 'vroom ';
var options = (USE_LIBOSRM) ? '-l ': '-a ' + OSRM_ADDRESS + ' -p ' + OSRM_PORT + ' ';
if(ROUTE_GEOMETRY){
  options += '-g ';
}
if(USE_OSRM_V5){
  // As of v5.1.0, profile name doesn't matter, so car will do until
  // it should be made into a variable.
  options += '-m car ';
}

var cb_exec = function (req, res){
  var req_options = '';
  if(!ROUTE_GEOMETRY && ALLOW_OPTIONS_OVERRIDE
     && 'options' in req.body && 'g' in req.body['options']
     && req.body['options']['g']){
    req_options = '-g ';
  }
  exec(command + options + req_options + '\'' + JSON.stringify(req.body) + '\'',
       // TODO find a better way to deal with big outputs.
       {'maxBuffer': 5000*1024},
       function(error, stdout, stderr){
         res.send(stdout);
         if(error !== null){
           console.log(error);
         }
       }
      );
}

app.post('/', [cb_size_check, cb_exec]);

app.listen(3000, function (){
  console.log('vroom-express listening on port 3000!');
});
<commit_msg>Use spawn over exec to handle huge responses. Fixes #1<commit_after>var express = require('express');
var morgan = require('morgan');
var bodyParser = require('body-parser');
var helmet = require('helmet');

// Config variables.
var VROOM_PATH = '';
var MAX_LOCATION_NUMBER = 50;
var ROUTE_GEOMETRY = false;
var USE_OSRM_V5 = true;
var USE_LIBOSRM = true;
var OSRM_ADDRESS = "0.0.0.0";
var OSRM_PORT = "5000";
var ALLOW_OPTIONS_OVERRIDE = true; // -g only so far.

// App and loaded modules.
var app = express();

// Enable cross-origin ressource sharing.
app.use(function(req, res, next){
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers",
             "Origin, X-Requested-With, Content-Type, Accept");
  next();
});

app.use(bodyParser.json());
app.use(morgan('combined'));
app.use(helmet());

// Callback for size and some input validity checks.
var cb_size_check = function (req, res, next){
  res.setHeader('Content-Type', 'application/json');

  var correct_input = ('jobs' in req.body)
      && ('vehicles' in req.body)
      && (req.body['vehicles'].length >= 1);

  if(!correct_input){
    res.send({code: 1, error: 'Invalid query.'});
    return;
  }

  var nb_locs = req.body['jobs'].length;
  if('start' in req.body['vehicles'][0]){
    nb_locs += 1;
  }
  if('end' in req.body['vehicles'][0]){
    nb_locs += 1;
  }
  if(nb_locs > MAX_LOCATION_NUMBER){
    console.log('Too many locs in query (' + nb_locs + ')');
    res.send({code: 1, error: 'Too many locations.'});
    return;
  }
  next();
}

// Cli wrapper and associated callback.
var spawn = require('child_process').spawn;

var vroom_command = VROOM_PATH + 'vroom';
var options = [];
if(USE_LIBOSRM){
  options.push('-l');
}
else{
  options.push('-a', OSRM_ADDRESS);
  options.push('-p', OSRM_PORT);
}
if(ROUTE_GEOMETRY){
  options.push('-g');
}
if(USE_OSRM_V5){
  // As of v5.1.0, profile name doesn't matter, so car will do until
  // it should be made into a variable.
  options.push('-m', 'car');
}

var cb_exec = function (req, res){
  var req_options = options.slice();
  if(!ROUTE_GEOMETRY && ALLOW_OPTIONS_OVERRIDE
     && 'options' in req.body && 'g' in req.body['options']
     && req.body['options']['g']){
    req_options.push('-g');
  }

  req_options.push(JSON.stringify(req.body));
  var vroom = spawn(vroom_command, req_options);

  vroom.stdout.pipe(res);

  vroom.stderr.on('data', function (data){
    console.log(data.toString());
  });
}

app.post('/', [cb_size_check, cb_exec]);

app.listen(3000, function (){
  console.log('vroom-express listening on port 3000!');
});
<|endoftext|>


<commit_before>'use strict';

var validator = require('ajv');
var debug = require('debug')('canornot');

/*var validator = require('is-my-json-valid');
var validator = require('jsen');*/

var _ = {
    defaultsDeep: require('lodash.defaultsdeep'),
    omit: require('lodash.omit')
};

function PermissionError(message) {
    Error.captureStackTrace(this, this.constructor);
    this.name = this.constructor.name;
    this.message = message;
}

require('util').inherits(PermissionError, Error);

module.exports = function (options) {

    options = _.defaultsDeep(options || {}, {
        rejectOnError: true,
        rejectOnPermissionDenied: true,
        returnSchemas: false
    });

    /**
     * @returns {Promise<Object>}
     */
    function getPolicySchema() {
        if (typeof options.policySchema === 'function') {

            // accepts a callback arguments
            if (options.policySchema.length === 1) {
                return new Promise(function (resolve, reject) {

                    return options.policySchema(function (result) {
                        if (result instanceof Error) {
                            reject(result);
                        } else {
                            resolve(result);
                        }
                    });
                });
            } else {
                return Promise.resolve(options.policySchema());
            }

        } else if (typeof options.policySchema === 'object' && typeof options.policySchema.then === 'function') {
            return options.policySchema;
        } else {
            return Promise.resolve(options.policySchema);
        }
    }

    /**
     * @returns {Promise<Object>}
     */
    function getActorSchema() {
        if (typeof options.actorSchema === 'function') {

            // accepts a callback arguments
            if (options.actorSchema.length === 1) {
                return new Promise(function (resolve, reject) {

                    return options.actorSchema(function (result) {
                        if (result instanceof Error) {
                            reject(result);
                        } else {
                            resolve(result);
                        }
                    });
                });
            } else {
                return Promise.resolve(options.actorSchema());
            }

        } else if (typeof options.actorSchema === 'object' && typeof options.actorSchema.then === 'function') {
            return options.actorSchema;
        } else {
            return Promise.resolve(options.actorSchema);
        }
    }

    /**
     * @returns {Promise}
     */
    function init() {

        return Promise.resolve();

        // return Promise.all([getActorSchema(), getPolicySchema()])
        //     .then(function (results) {
        //
        //         var actorSchema = results[0];
        //         var policySchema = results[1];
        //
        //         if (typeof actorSchema !== 'object') {
        //             throw new TypeError('Actor Schema must be an object or a function/promise that returns an object. Saw ' + typeof actorSchema);
        //         }
        //
        //         if (typeof policySchema !== 'object') {
        //             throw new TypeError('Policy Schema must be an object or a function/promise that returns an object. Saw ' + typeof policySchema);
        //         }
        //
        //         if (!loaded) {
        //             try {
        //                 console.log('adding actor schema');
        //                 validator.addSchema(actorSchema, 'actor');
        //                 console.log('adding policy schema');
        //                 validator.addSchema(policySchema, 'policy');
        //                 loaded = true;
        //             } catch (err) {
        //                 console.log('kakked it', err.message);
        //                 throw new Error('Failed to add policy or actor schema: ' + err.message);
        //
        //             }
        //         } else {
        //             console.log('policies already loaded');
        //         }
        //
        //     });
    }

    /**
     * @param {String} permission
     * @param {*} data
     * @returns {Promise.<Boolean>}
     */
    this.can = function (permission, data) {

        if (typeof permission !== 'string') {
            return Promise.reject(new TypeError('Permission must be a string'));
        }

        // ajv seems to pass validation with undefined, but not an empty object
        // so, force it to be an object if data was not passed
        if (data === undefined) {
            data = {};
        }

        return init()
            .then(function () {

                // AJV
                return Promise.all([getActorSchema(), getPolicySchema()])
                    .then(function (schemas) {

                        var actorSchema = schemas[0];
                        var policySchema = schemas[1];

                        if (typeof actorSchema !== 'object') {
                            throw new TypeError('Actor Schema must be an object or a function/promise that returns an object. Saw ' + typeof actorSchema);
                        }

                        if (typeof policySchema !== 'object') {
                            throw new TypeError('Policy Schema must be an object or a function/promise that returns an object. Saw ' + typeof policySchema);
                        }

                        var ajv = validator({
                            missingRefs: 'fail',
                            breakOnError: true
                        });

                        ajv.addSchema(actorSchema, 'actor');

                        //ajv.addSchema(policySchema, 'policy');

                        // var validate = ajv.compile({
                        //     $ref: 'policy#/properties/' + permission
                        // });

                        // var valid = validate(data);
                        //
                        // var validate = ajv.compile({
                        //     $ref: 'policy#/properties/' + permission
                        // });

                        policySchema.additionalProperties = false;

                        var valid = ajv.validate(policySchema, {
                            [permission]: data
                        });

                        debug('policySchema', policySchema);
                        debug('actorSchema', actorSchema);
                        debug('Permission data', JSON.stringify({
                            [permission]: data
                        }));
                        debug('Permission allowed/valid?', valid);

                        if (options.rejectOnPermissionDenied === true) {
                            if (!valid) {
                                debug('Throwing PermissionError', ajv.errors);
                                var err = new PermissionError('Permission Denied for `' + permission + '` against `' + JSON.stringify(data) + '`');
                                err.errors = ajv.errors;
                                throw err;
                            } else {
                                if (options.returnSchemas) {
                                    return {
                                        actor: actorSchema,
                                        policy: policySchema
                                    };
                                } else {
                                    return valid;
                                }
                            }
                        } else {
                            debug('Returning `%s` result: %s', permission, valid);
                            return valid;
                        }

                    });

                // IS MY JSON VALID
                // return Promise.all([getPolicySchema(), getActorSchema()])
                //     .then(function (results) {
                //
                //         var actorSchema = results[0];
                //         var policySchema = results[1];
                //
                //         var validate = validator({
                //             $ref: 'policy#/properties/' + permission
                //         }, {
                //             // verbose: true,
                //             // greedy: true,
                //             schemas: {
                //                 policy: policySchema,
                //                 actor: actorSchema
                //             }
                //         });
                //
                //         console.log('validating', data);
                //         console.info('config', {
                //             $ref: 'policy#/properties/' + permission
                //         }, {
                //             // verbose: true,
                //             // greedy: true,
                //             schemas: {
                //                 policy: policySchema,
                //                 actor: actorSchema
                //             }
                //         });
                //
                //         return validate(data);
                //
                //     });

                // JSEN
                // return Promise.all([getPolicySchema(), getActorSchema()])
                //     .then(function (results) {
                //
                //         var actorSchema = results[0];
                //         var policySchema = results[1];
                //
                //         var validate = validator({
                //             $ref: '#policy/properties/' + permission
                //         }, {
                //             missing$Ref: true,
                //             schemas: {
                //                 policy: policySchema,
                //                 actor: actorSchema
                //             }
                //         });
                //
                //         var valid = validate(data);
                //
                //         return valid;
                //
                //     });

            })
            .catch(function (err) {

                // it's not a basic permission error;
                if (err instanceof PermissionError && options.rejectOnPermissionDenied === true) {
                    throw err;
                } else {
                    if (options.rejectOnError === true) {
                        throw err;
                    } else {
                        return false;
                    }
                }

            });
    };

    this.has = this.can;

};

// so we can access the validator from outside the scope - nice for testing.
module.exports.validator = validator;
<commit_msg>es6 + jsdoc + cleanup + remove lodash modules<commit_after>'use strict';

const validator = require('ajv');
const debug = require('debug')('canornot');

const PermissionError = require('./error').PermissionError;

module.exports = function Canornot(opts = {}) {

    const options = Object.assign({
        rejectOnError: true,
        rejectOnPermissionDenied: true,
        returnSchemas: false
    }, opts);

    /**
     * @returns {Promise<Object>}
     */
    function getPolicySchema() {
        if (typeof options.policySchema === 'function') {

            // accepts a callback arguments
            if (options.policySchema.length === 1) {
                return new Promise(function (resolve, reject) {

                    return options.policySchema(function (result) {
                        if (result instanceof Error) {
                            reject(result);
                        } else {
                            resolve(result);
                        }
                    });
                });
            } else {
                return Promise.resolve(options.policySchema());
            }

        } else if (typeof options.policySchema === 'object' && typeof options.policySchema.then === 'function') {
            return options.policySchema;
        } else {
            return Promise.resolve(options.policySchema);
        }
    }

    /**
     * @returns {Promise<Object>}
     */
    function getActorSchema() {
        if (typeof options.actorSchema === 'function') {

            // accepts a callback arguments
            if (options.actorSchema.length === 1) {
                return new Promise(function (resolve, reject) {

                    return options.actorSchema(function (result) {
                        if (result instanceof Error) {
                            reject(result);
                        } else {
                            resolve(result);
                        }
                    });
                });
            } else {
                return Promise.resolve(options.actorSchema());
            }

        } else if (typeof options.actorSchema === 'object' && typeof options.actorSchema.then === 'function') {
            return options.actorSchema;
        } else {
            return Promise.resolve(options.actorSchema);
        }
    }

    /**
     * @param {String} permission
     * @param {String|Number|Object|Array} [data={}]
     * @returns {Promise.<Boolean>}
     */
    this.can = (permission, data = {}) => {

        if (typeof permission !== 'string') {
            return Promise.reject(new TypeError('Permission must be a string'));
        }

        return Promise.all([getActorSchema(), getPolicySchema()])
            .then(schemas => {

                const [actorSchema, policySchema] = schemas;

                if (typeof actorSchema !== 'object') {
                    debug('Invalid actor schema');
                    throw new TypeError('Actor Schema must be an object or a function/promise that returns an object. Saw ' + typeof actorSchema);
                }

                if (typeof policySchema !== 'object') {
                    debug('Invalid policy schema');
                    throw new TypeError('Policy Schema must be an object or a function/promise that returns an object. Saw ' + typeof policySchema);
                }

                policySchema.additionalProperties = false;

                const ajv = validator({
                    missingRefs: 'fail',
                    breakOnError: true
                });

                ajv.addSchema(actorSchema, 'actor');

                const valid = ajv.validate(policySchema, {
                    [permission]: data
                });

                // tiny bit of safety to stop stringifying everything even if we're not going to be outputting anything
                /* istanbul ignore next */
                if (process.env.DEBUG) {
                    debug('policySchema', JSON.stringify(policySchema));
                    debug('actorSchema', JSON.stringify(actorSchema));
                    debug('Permission data', JSON.stringify({
                        [permission]: data
                    }));
                }

                debug('Permission allowed/valid?', valid);

                if (options.rejectOnPermissionDenied === true) {
                    if (!valid) {
                        debug('Throwing PermissionError', ajv.errors);
                        const err = new PermissionError('Permission Denied for `' + permission + '` against `' + JSON.stringify(data) + '`');
                        err.errors = ajv.errors;
                        throw err;
                    } else {
                        if (options.returnSchemas) {
                            return {
                                actor: actorSchema,
                                policy: policySchema
                            };
                        } else {
                            return valid;
                        }
                    }
                } else {
                    debug('Returning `%s` result: %s', permission, valid);
                    return valid;
                }

            })
            .catch(err => {

                debug('Error fetching actor or policy schema', err.message);

                // it's not a basic permission error;
                if (err instanceof PermissionError && options.rejectOnPermissionDenied === true) {
                    throw err;
                } else {
                    if (options.rejectOnError === true) {
                        throw err;
                    } else {
                        return false;
                    }
                }

            });
    };

    this.has = this.can;

};
<|endoftext|>


<commit_before>'use strict';

// Root packages
exports.ArrayUtils = exports.AU = require('ml-array-utils');
exports.BitArray = require('ml-bit-array');
exports.HashTable = require('ml-hash-table');
exports.Matrix = require('ml-matrix');
exports.PadArray = require('ml-pad-array');
exports.Regression = require('ml-regression');

// Math packages
var Math = exports.Math = {};

var distance = require('ml-distance');
Math.Distance = distance.distance;
Math.Similarity = distance.similarity;
Math.SG = require('ml-savitzky-golay');
Math.Matrix = exports.Matrix;
Math.SparseMatrix = require('ml-sparse-matrix');
Math.BellOptimizer = require('ml-optimize-lorentzian');
Math.CurveFitting = require('ml-curve-fitting');
Math.Kernel = require('ml-kernel');
Math.Optimization = require('optimization');

// Statistics packages
var Stat = exports.Stat = {};

Stat.array = require('ml-stat/array');
Stat.matrix = require('ml-stat/matrix');
Stat.PCA = require('ml-pca');
Stat.Performance = require('ml-performance');

// Random number generation
var RNG = exports.RNG = {};
RNG.XSadd = require('ml-xsadd');

// Supervised learning
var SL = exports.SL = {};

SL.CV = require('ml-cross-validation');
SL.CrossValidation = SL.CV; // Alias
SL.SVM = require('ml-svm');
SL.KNN = require('ml-knn');
SL.NaiveBayes = require('ml-naivebayes');
SL.PLS = require('ml-pls');

// Clustering
var Clust = exports.Clust = {};

Clust.kmeans = require('ml-kmeans');
Clust.hclust = require('ml-hclust');

// Neural networks
var NN = exports.NN = exports.nn = {};

NN.SOM = require('ml-som');
NN.FNN = require('ml-fnn');
<commit_msg>fix(ml-stat): new access route for array and matrix<commit_after>'use strict';

// Root packages
exports.ArrayUtils = exports.AU = require('ml-array-utils');
exports.BitArray = require('ml-bit-array');
exports.HashTable = require('ml-hash-table');
exports.Matrix = require('ml-matrix');
exports.PadArray = require('ml-pad-array');
exports.Regression = require('ml-regression');

// Math packages
var Math = exports.Math = {};

var distance = require('ml-distance');
Math.Distance = distance.distance;
Math.Similarity = distance.similarity;
Math.SG = require('ml-savitzky-golay');
Math.Matrix = exports.Matrix;
Math.SparseMatrix = require('ml-sparse-matrix');
Math.BellOptimizer = require('ml-optimize-lorentzian');
Math.CurveFitting = require('ml-curve-fitting');
Math.Kernel = require('ml-kernel');
Math.Optimization = require('optimization');

// Statistics packages
var Stat = exports.Stat = {};

Stat.array = require('ml-stat').array;
Stat.matrix = require('ml-stat').matrix;
Stat.PCA = require('ml-pca');
Stat.Performance = require('ml-performance');

// Random number generation
var RNG = exports.RNG = {};
RNG.XSadd = require('ml-xsadd');

// Supervised learning
var SL = exports.SL = {};

SL.CV = require('ml-cross-validation');
SL.CrossValidation = SL.CV; // Alias
SL.SVM = require('ml-svm');
SL.KNN = require('ml-knn');
SL.NaiveBayes = require('ml-naivebayes');
SL.PLS = require('ml-pls');

// Clustering
var Clust = exports.Clust = {};

Clust.kmeans = require('ml-kmeans');
Clust.hclust = require('ml-hclust');

// Neural networks
var NN = exports.NN = exports.nn = {};

NN.SOM = require('ml-som');
NN.FNN = require('ml-fnn');
<|endoftext|>


<commit_before>const most = require("most");

const {
  isArray,
  isFunction,
  isInteger,
  isString,
  assign
} = require("lodash");

const toNodeStream = require("./to-node-stream");
const {
  toDashCase,
  htmlStringEscape,
  hasOwn,
  concatAll
} = require("./util");
const {
  getChildContext,
  getContext,
  getRootContext
} = require("./context");
const streamTemplate = require("./template");
const getCachedNodeStream = require("./cache");
const batch = require("./batch");

let BATCH_EVERY = 100;
const tuneAsynchronicity = num => {
  if (!isInteger(num) || num < 1) {
    throw new RangeError("Asynchronicity must be an integer greater than or equal to 1.");
  }
  BATCH_EVERY = num;
};

function *renderAttrs (attrs) {
  for (const attrKey in attrs) {
    if (
      hasOwn(attrs, attrKey) &&
      attrKey !== "children"
    ) {
      const attrVal = attrs[attrKey];

      if (!attrVal || isFunction(attrVal)) { continue; }

      yield ` ${toDashCase(attrKey)}`;
      if (attrVal !== true) { yield `="${attrVal}"`; }
    }
  }
}

function renderChildren (children, context) {
  if (!children) {
    return most.empty();
  }

  return isArray(children) ?
    most.from(children).concatMap(child => traverse(child, context)) :
    // This was:
    //
    //   traverse(children, context);
    //
    // However, for a JSX tree where each node had only one child, this
    // resulted in synchronous evaluation of the entire tree.  In order
    // to circumvent this, we create a new stream of a single value that
    // is flat-mapped into the traversal that we want.
    //
    // This doesn't cost us anything performance-wise, and it gives
    // better guarantees with regard to asychronicity of tree evaluation.
    most.just(null).flatMap(() => traverse(children, context));
}

function renderNode (node, context) {
  return concatAll([
    most.just(`<${node.type}`),
    most.generate(renderAttrs, node.props),
    most.just(">"),
    renderChildren(node.props.children, context),
    most.just(`</${node.type}>`)
  ]);
}

/* eslint-disable no-invalid-this */
function syncSetState (newState, cb) {
  // Mutation is faster and should be safe here.
  this.state = assign(
    this.state,
    isFunction(newState) ?
      newState(this.state, this.props) :
      newState
  );
  if (cb) { cb.call(this); }
}
/* eslint-enable no-invalid-this */

function evalComponent (node, context) {
  const componentContext = getContext(node.type, context);
  // eslint-disable-next-line new-cap
  const instance = new node.type(node.props, componentContext);

  if (isFunction(instance.componentWillMount)) {
    instance.setState = syncSetState;
    instance.componentWillMount();
  }

  const childContext = getChildContext(node.type, instance, context);

  return isFunction(instance.render) ?
    traverse(instance.render(), childContext) :
    traverse(instance, childContext);
}

function traverse (node, context) {
  // A render function might return `null`.
  if (!node) {
    return most.empty();
  }
  // Text node.
  if (isString(node)) {
    return most.just(htmlStringEscape(node));
  }

  // Plain-jane DOM element, not a React component.
  if (isString(node.type)) {
    return getCachedNodeStream(node, (_node) => renderNode(_node, context));
  }
  // React component.
  if (hasOwn(node, "$$typeof")) {
    return getCachedNodeStream(node, (_node) => evalComponent(_node, context));
  }

  throw new TypeError(`Unknown node of type: ${node.type}`);
}

function renderToStream (node) {
  const rootContext = getRootContext();
  return traverse(node, rootContext).thru(batch(BATCH_EVERY));
}

function renderToString (node) {
  return renderToStream(node)
    .reduce((memo, segment) => (memo.push(segment), memo), [])
    .then(segments => segments.join(""));
}

module.exports = {
  renderToStream,
  renderToString,
  toNodeStream,
  streamTemplate,
  tuneAsynchronicity
};
<commit_msg>Components that returned null would not render correctly (see big fat comment).<commit_after>const most = require("most");

const {
  isArray,
  isFunction,
  isInteger,
  isString,
  assign
} = require("lodash");

const toNodeStream = require("./to-node-stream");
const {
  toDashCase,
  htmlStringEscape,
  hasOwn,
  concatAll
} = require("./util");
const {
  getChildContext,
  getContext,
  getRootContext
} = require("./context");
const streamTemplate = require("./template");
const getCachedNodeStream = require("./cache");
const batch = require("./batch");

let BATCH_EVERY = 100;
const tuneAsynchronicity = num => {
  if (!isInteger(num) || num < 1) {
    throw new RangeError("Asynchronicity must be an integer greater than or equal to 1.");
  }
  BATCH_EVERY = num;
};

function *renderAttrs (attrs) {
  for (const attrKey in attrs) {
    if (
      hasOwn(attrs, attrKey) &&
      attrKey !== "children"
    ) {
      const attrVal = attrs[attrKey];

      if (!attrVal || isFunction(attrVal)) { continue; }

      yield ` ${toDashCase(attrKey)}`;
      if (attrVal !== true) { yield `="${attrVal}"`; }
    }
  }
}

function renderChildren (children, context) {
  if (!children) {
    return most.empty();
  }

  return isArray(children) ?
    most.from(children).concatMap(child => traverse(child, context)) :
    // This was:
    //
    //   traverse(children, context);
    //
    // However, for a JSX tree where each node had only one child, this
    // resulted in synchronous evaluation of the entire tree.  In order
    // to circumvent this, we create a new stream of a single value that
    // is flat-mapped into the traversal that we want.
    //
    // This doesn't cost us anything performance-wise, and it gives
    // better guarantees with regard to asychronicity of tree evaluation.
    most.just(null).flatMap(() => traverse(children, context));
}

function renderNode (node, context) {
  return concatAll([
    most.just(`<${node.type}`),
    most.generate(renderAttrs, node.props),
    most.just(">"),
    renderChildren(node.props.children, context),
    most.just(`</${node.type}>`)
  ]);
}

/* eslint-disable no-invalid-this */
function syncSetState (newState, cb) {
  // Mutation is faster and should be safe here.
  this.state = assign(
    this.state,
    isFunction(newState) ?
      newState(this.state, this.props) :
      newState
  );
  if (cb) { cb.call(this); }
}
/* eslint-enable no-invalid-this */

function evalComponent (node, context) {
  const componentContext = getContext(node.type, context);
  // eslint-disable-next-line new-cap
  const instance = new node.type(node.props, componentContext);

  if (isFunction(instance.componentWillMount)) {
    instance.setState = syncSetState;
    instance.componentWillMount();
  }

  const childContext = getChildContext(node.type, instance, context);

  if (isFunction(instance.render)) {
    return traverse(instance.render(), childContext);
  }

  /*
    The following check looks really strange... why _wouldn't_ `instance`
    be an instance of `node.type`?  The answer has to do with JavaScript's
    behavior when values are returned from a constructor invoked with `new`.
    If an object is returned from the constructor, the function is treated
    as if it had been invoked without `new`.

    This behavior is defined in section 9.2.2 step 13a of the ECMAScript
    Language Specification, 7th Edition, here:
    http://www.ecma-international.org/ecma-262/7.0/index.html#sec-ecmascript-function-objects-construct-argumentslist-newtarget

    Specifically relevant is section 9.2.2 step 13a.

    However, in the circumstance of object construction, a `null` return value
    is treated the same as `undefined` and an empty object with prototype
    Constructor will be returned.

    Here it is demonstrated in code:

      const NotNullComponent = () => <div />;
      const notNullComponentNode = <NotNullComponent />;
      const notNullComponentNodeTypeInstance = new notNullComponentNode.type;
      notNullComponentNodeTypeInstance instanceof notNullComponentNode.type;
      // false
      notNullComponentNodeTypeInstance;
      // { '$$typeof': Symbol(react.element),
      //   type: 'div',
      //   key: null,
      //   ref: null,
      //   props: {},
      //   _owner: null,
      //   _store: {} }

      const NullComponent = () => null;
      const nullComponentNode = <NullComponent />;
      const nullComponentNodeTypeInstance = new nullComponentNode.type;
      nullComponentNodeTypeInstance
      // NullComponent {}
      nullComponentNodeTypeInstance instanceof nullComponentNode.type
      // true
  */
  if (instance instanceof node.type) {
    return most.empty();
  }

  return traverse(instance, childContext);
}

function traverse (node, context) {
  // A render function might return `null`.
  if (!node) {
    return most.empty();
  }
  // Text node.
  if (isString(node)) {
    return most.just(htmlStringEscape(node));
  }

  // Plain-jane DOM element, not a React component.
  if (isString(node.type)) {
    return getCachedNodeStream(node, (_node) => renderNode(_node, context));
  }
  // React component.
  if (hasOwn(node, "$$typeof")) {
    return getCachedNodeStream(node, (_node) => evalComponent(_node, context));
  }

  throw new TypeError(`Unknown node of type: ${node.type}`);
}

function renderToStream (node) {
  const rootContext = getRootContext();
  return traverse(node, rootContext).thru(batch(BATCH_EVERY));
}

function renderToString (node) {
  return renderToStream(node)
    .reduce((memo, segment) => (memo.push(segment), memo), [])
    .then(segments => segments.join(""));
}

module.exports = {
  renderToStream,
  renderToString,
  toNodeStream,
  streamTemplate,
  tuneAsynchronicity
};
<|endoftext|>


<commit_before>/**
 * @fileOverview
 * Audio buffer loader.
 * @author Karim Barkati, Victor Saiz, Emmanuel Fréard, Samuel Goldszmidt
 * @version 4.0.0
 */

'use strict';

// Ensure global availability of an "audioContext" instance of web audio AudioContext.
window.audioContext = window.audioContext || new AudioContext() || new webkitAudioContext();

class BufferLoader {

  constructor() {
    this.progressCb = undefined;
  }

  /**
   * Main wrapper function for audio buffer loading.
   * Switch between loadBuffer and loadAll.
   * @public
   * @param fileURLs The URL(s) of the audio files to load. Accepts a URL to the audio file location or an array of URLs.
   */
  load(fileURLs) {
    if (Array.isArray(fileURLs)) {
      return this.loadAll(fileURLs);
    } else {
      return this.loadBuffer(fileURLs);
    }
  }

  /**
   * Load a single audio file,
   * decode it in an AudioBuffer, return a Promise
   * @public
   * @param fileURL The URL of the audio file location to load.
   */
  loadBuffer(fileURL) {
    return this.fileLoadingRequest(fileURL)
      .then(
        this.decodeAudioData,
        function(error) {
          throw error;
        });
  }

  /**
   * Load all audio files at once in a single array,
   * decode them in an array of AudioBuffers,
   * and return a Promise
   * @public
   * @param fileURLs The URLs array of the audio files to load.
   */
  loadAll(fileURLs) {
    var urlsCount = fileURLs.length,
      promises = [],
      that = this;

    for (var i = 0; i < urlsCount; ++i) {
      promises.push(this.fileLoadingRequest(fileURLs[i], i));
    }

    return Promise.all(promises)
      .then(
        function get_all_the_things(arraybuffers) {
          return Promise.all(arraybuffers.map(function(arraybuffer) {
            return that.decodeAudioData(arraybuffer);
          }));
        },
        function(error) {
          throw error; // TODO: better error handler
        });
  }

  /**
   * Load a file asynchronously, return a Promise.
   * @private
   * @param url The URL of the audio file to load.
   */
  fileLoadingRequest(url, index) {
    var self = this;
    var promise = new Promise(
      function(resolve, reject) {
        // Load buffer asynchronously
        var request = new XMLHttpRequest();

        request.open('GET', url, true);
        request.responseType = "arraybuffer";
        request.onload = function() {
          // Test request.status value, as 404 will also get there
          if (request.status === 200 || request.status === 304) {
            resolve(request.response);
          } else {
            reject(new Error(request.statusText));
          }
        };
        request.onprogress = function(evt) {
          if (self.progressCallback) {
            if (index !== undefined) {
              self.progressCallback({
                index: index,
                value: evt.loaded / evt.total
              });
            } else {
              self.progressCallback(evt.loaded / evt.total);
            }
          }
        };
        // Manage network errors
        request.onerror = function() {
          reject(new Error("Network Error"));
        };
        request.send();
      });
    return promise;
  }

  /**
   * Decode Audio Data, return a Promise
   * @private
   * @param arraybuffer The arraybuffer of the loaded audio file to be decoded.
   */
  decodeAudioData(arraybuffer) {
    var promise = new Promise(function(resolve, reject) {
      window.audioContext.decodeAudioData(
        arraybuffer, // returned audio data array
        function successCallback(buffer) {
          resolve(buffer);
        },
        function errorCallback(error) {
          reject(new Error("DecodeAudioData error"));
        }
      );
    });
    return promise;
  }

  /**
   * Set / Get the callback function to get the progress of file loading process.
   * This is only for the file loading progress as decodeAudioData doesn't
   * expose a decode progress value.
   */
  get progressCallback() {
    return this.progressCb;
  }
  set progressCallback(callback) {
    this.progressCb = callback;
  }

}

// CommonJS function export
module.exports = BufferLoader;
<commit_msg>global audio context comes now from a module<commit_after>/**
 * @fileOverview
 * Audio buffer loader.
 * @author Karim Barkati, Victor Saiz, Emmanuel Fréard, Samuel Goldszmidt
 * @version 4.0.0
 */

'use strict';

//make an AudioContext instance globally availbe
require("../audio-context");

class BufferLoader {

  constructor() {
    this.progressCb = undefined;
  }

  /**
   * Main wrapper function for audio buffer loading.
   * Switch between loadBuffer and loadAll.
   * @public
   * @param fileURLs The URL(s) of the audio files to load. Accepts a URL to the audio file location or an array of URLs.
   */
  load(fileURLs) {
    if (Array.isArray(fileURLs)) {
      return this.loadAll(fileURLs);
    } else {
      return this.loadBuffer(fileURLs);
    }
  }

  /**
   * Load a single audio file,
   * decode it in an AudioBuffer, return a Promise
   * @public
   * @param fileURL The URL of the audio file location to load.
   */
  loadBuffer(fileURL) {
    return this.fileLoadingRequest(fileURL)
      .then(
        this.decodeAudioData,
        function(error) {
          throw error;
        });
  }

  /**
   * Load all audio files at once in a single array,
   * decode them in an array of AudioBuffers,
   * and return a Promise
   * @public
   * @param fileURLs The URLs array of the audio files to load.
   */
  loadAll(fileURLs) {
    var urlsCount = fileURLs.length,
      promises = [],
      that = this;

    for (var i = 0; i < urlsCount; ++i) {
      promises.push(this.fileLoadingRequest(fileURLs[i], i));
    }

    return Promise.all(promises)
      .then(
        function get_all_the_things(arraybuffers) {
          return Promise.all(arraybuffers.map(function(arraybuffer) {
            return that.decodeAudioData(arraybuffer);
          }));
        },
        function(error) {
          throw error; // TODO: better error handler
        });
  }

  /**
   * Load a file asynchronously, return a Promise.
   * @private
   * @param url The URL of the audio file to load.
   */
  fileLoadingRequest(url, index) {
    var self = this;
    var promise = new Promise(
      function(resolve, reject) {
        // Load buffer asynchronously
        var request = new XMLHttpRequest();

        request.open('GET', url, true);
        request.responseType = "arraybuffer";
        request.onload = function() {
          // Test request.status value, as 404 will also get there
          if (request.status === 200 || request.status === 304) {
            resolve(request.response);
          } else {
            reject(new Error(request.statusText));
          }
        };
        request.onprogress = function(evt) {
          if (self.progressCallback) {
            if (index !== undefined) {
              self.progressCallback({
                index: index,
                value: evt.loaded / evt.total
              });
            } else {
              self.progressCallback(evt.loaded / evt.total);
            }
          }
        };
        // Manage network errors
        request.onerror = function() {
          reject(new Error("Network Error"));
        };
        request.send();
      });
    return promise;
  }

  /**
   * Decode Audio Data, return a Promise
   * @private
   * @param arraybuffer The arraybuffer of the loaded audio file to be decoded.
   */
  decodeAudioData(arraybuffer) {
    var promise = new Promise(function(resolve, reject) {
      window.audioContext.decodeAudioData(
        arraybuffer, // returned audio data array
        function successCallback(buffer) {
          resolve(buffer);
        },
        function errorCallback(error) {
          reject(new Error("DecodeAudioData error"));
        }
      );
    });
    return promise;
  }

  /**
   * Set / Get the callback function to get the progress of file loading process.
   * This is only for the file loading progress as decodeAudioData doesn't
   * expose a decode progress value.
   */
  get progressCallback() {
    return this.progressCb;
  }
  set progressCallback(callback) {
    this.progressCb = callback;
  }

}

// CommonJS function export
module.exports = BufferLoader;
<|endoftext|>


<commit_before>/**
 * Created by ndyumin on 09.09.2016.
 */

const symbolObservable = require('symbol-observable');

function extract(arr, obj) {
    return arr.filter(item => Object.keys(obj).every(key => item[key] === obj[key]));
}

function removeItem(arr, item) {
    const result = arr.slice(0);
    const index = result.indexOf(item);
    result.splice(index, 1);
    return result;
}

function notifyAll(observers, state) {
    observers.forEach(o => o.next(state));
}

function fromCallbacks(next, error, complete) {
    return {
        next,
        error,
        complete
    };
}

function data(initial) {
    let state = initial;
    let subscriptions = [];
    let observers = [];

    function _unsubscribeAndRemove(observable, reducer) {
        const toBeRemoved = extract(subscriptions, {observable, reducer});
        toBeRemoved.forEach(subscription => subscription.unsubscribe());
        subscriptions = toBeRemoved.reduce(removeItem, subscriptions);
    }

    return {
        [symbolObservable]: function() {
            return this;
        },

        reduce (observable, reducer) {
            const subscription = observable.subscribe({
                next(v) {
                    state = reducer(state, v);
                    notifyAll(observers, state);
                },
                error(e) {

                },
                complete() {
                    _unsubscribeAndRemove(observable, reducer);
                }
            });

            subscriptions.push({
                observable,
                reducer,
                subscription
            });

            return this;
        },

        remove(observable, reducer) {
            _unsubscribeAndRemove(observable, reducer);
        },

        subscribe(observer) {
            if (typeof observer === 'function') {
                observer = fromCallbacks(...arguments);
            }

            observers.push(observer);
            observer.next(state);
            return {
                unsubscribe() {
                    observers = removeItem(observers, observer);
                }
            };
        }
    };
}

function actions(initial) {
    const events = [];
    let subscribers = [];

    function project() {
        return events.reduce(function(state, event) {
            return event.reduce(state, event.update);
        }, initial);
    }

    return {
        subscribe(observer) {
            if (typeof observer === 'function') {
                observer = fromCallbacks(...arguments);
            }
            subscribers.push(observer);
            return {
                unsubscribe() {
                    subscribers = removeItem(subscribers, observer);
                }
            };
        },
        dispatch(event) {
            events.push(event);
            notifyAll(subscribers, project())
        },
        createEvent(reduce) {
            return update =>
                this.dispatch({
                    reduce,
                    update
                });
        }
    };
}

actions.createEvent = function(reduce) {
    return function(update) {
        return {
            reduce,
            update
        };
    }
};

module.exports = {
    data,
    actions
};<commit_msg>add snapshots<commit_after>/**
 * Created by ndyumin on 09.09.2016.
 */

const symbolObservable = require('symbol-observable');

function extract(arr, obj) {
    return arr.filter(item => Object.keys(obj).every(key => item[key] === obj[key]));
}

function removeItem(arr, item) {
    const result = arr.slice(0);
    const index = result.indexOf(item);
    result.splice(index, 1);
    return result;
}

function notifyAll(observers, state) {
    observers.forEach(o => o.next(state));
}

function fromCallbacks(next, error, complete) {
    return {
        next,
        error,
        complete
    };
}

function data(initial) {
    let state = initial;
    let subscriptions = [];
    let observers = [];

    function _unsubscribeAndRemove(observable, reducer) {
        const toBeRemoved = extract(subscriptions, {observable, reducer});
        toBeRemoved.forEach(subscription => subscription.unsubscribe());
        subscriptions = toBeRemoved.reduce(removeItem, subscriptions);
    }

    return {
        [symbolObservable]: function() {
            return this;
        },

        reduce (observable, reducer) {
            const subscription = observable.subscribe({
                next(v) {
                    state = reducer(state, v);
                    notifyAll(observers, state);
                },
                error(e) {

                },
                complete() {
                    _unsubscribeAndRemove(observable, reducer);
                }
            });

            subscriptions.push({
                observable,
                reducer,
                subscription
            });

            return this;
        },

        remove(observable, reducer) {
            _unsubscribeAndRemove(observable, reducer);
        },

        subscribe(observer) {
            if (typeof observer === 'function') {
                observer = fromCallbacks(...arguments);
            }

            observers.push(observer);
            observer.next(state);
            return {
                unsubscribe() {
                    observers = removeItem(observers, observer);
                }
            };
        }
    };
}

function actions(initial) {
    const events = [];
    let subscribers = [];
    let snapshots = [];

    function projectFrom(initial, sequence) {
        return sequence.reduce(function(state, event) {
            return event.reduce(state, event.update);
        }, initial);
    }

    function project() {
        const latestSnapshot = snapshots[snapshots.length - 1];
        if (events.length === snapshots.length) {
            return latestSnapshot;
        } else {
            const sequence = events.slice(snapshots.length);
            return snapshots[events.length - 1] = projectFrom(latestSnapshot || initial, sequence);
        }
    }

    return {
        _project: project``,
        subscribe(observer) {
            if (typeof observer === 'function') {
                observer = fromCallbacks(...arguments);
            }
            subscribers.push(observer);
            return {
                unsubscribe() {
                    subscribers = removeItem(subscribers, observer);
                }
            };
        },
        dispatch(event) {
            events.push(event);
            notifyAll(subscribers, project())
        },
        createEvent(reduce) {
            return update =>
                this.dispatch({
                    reduce,
                    update
                });
        }
    };
}

actions.createEvent = function(reduce) {
    return function(update) {
        return {
            reduce,
            update
        };
    }
};

module.exports = {
    data,
    actions
};<|endoftext|>


<commit_before>'use strict'
const deepEqual = require('deep-equal')

const isPut = obj => (obj && Object.keys(obj).includes('PUT'))
const isNestedArray = arr => (
  arr &&
  arr.every && // Is an array
  arr.every(subArr => subArr.length === 2) // Every array inside has exactly 2 elements.
)

const prettyPrint = (obj, msg) => console.log(msg || '', JSON.stringify(obj, null, 2))

function getNextVal(searchVal, mapping) {
  return (mapping.find(keyVal => deepEqual(keyVal[0], searchVal)) || [])[1]
}

function runGenfunc(genFunc, envMapping, ...initialArgs) {
  if (typeof genFunc !== 'function') {
    console.error(`The first parameter must be a generator function.`)
  }

  if (!isNestedArray(envMapping)) {
    console.error(`The second parameter must be a nested array.`)
  }

  const mapping = [...envMapping, [undefined, undefined]]
  const gen = genFunc(...initialArgs)
  let val, genResult, nextVal
  let puts = []
  let isDone = false

  while (!isDone) {
    nextVal = getNextVal(val, mapping)

    // TODO: Should warn the user if yielded value is not found in the `mapping`.
    // if (nextVal === undefined) {
    //   console.warn(`
    //     Either the yielded value is not found in your Map, or`)
    // }

    genResult = gen.next(nextVal)

    val = genResult.value
    isDone = genResult.done

    if (isPut(val)) {
      puts.push(val)
    }
  }
  return puts
}

module.exports = { runGenfunc, isPut, isNestedArray, getNextVal, prettyPrint }
<commit_msg>(m) Enforce boolean return value<commit_after>'use strict'
const deepEqual = require('deep-equal')

const bool = o => !!o

const isPut = obj => bool(obj && Object.keys(obj).includes('PUT'))

const isNestedArray = arr => bool(
  arr &&
  arr.every && // Is an array
  arr.every(subArr => subArr.length === 2) // Every array inside has exactly 2 elements.
)

const prettyPrint = (obj, msg) => console.log(msg || '', JSON.stringify(obj, null, 2))

function getNextVal(searchVal, mapping) {
  return (mapping.find(keyVal => deepEqual(keyVal[0], searchVal)) || [])[1]
}

function runGenfunc(genFunc, envMapping, ...initialArgs) {
  if (typeof genFunc !== 'function') {
    console.error(`The first parameter must be a generator function.`)
  }

  if (!isNestedArray(envMapping)) {
    console.error(`The second parameter must be a nested array.`)
  }

  const mapping = [...envMapping, [undefined, undefined]]
  const gen = genFunc(...initialArgs)
  let val, genResult, nextVal
  let puts = []
  let isDone = false

  while (!isDone) {
    nextVal = getNextVal(val, mapping)

    // TODO: Should warn the user if yielded value is not found in the `mapping`.
    // if (nextVal === undefined) {
    //   console.warn(`
    //     Either the yielded value is not found in your Map, or`)
    // }

    genResult = gen.next(nextVal)

    val = genResult.value
    isDone = genResult.done

    if (isPut(val)) {
      puts.push(val)
    }
  }
  return puts
}

module.exports = { runGenfunc, isPut, isNestedArray, getNextVal, prettyPrint }
<|endoftext|>


<commit_before>import path from 'path'
import _ from 'lodash'
import Bunyan from 'bunyan'
import bunyanDebugStream from 'bunyan-debug-stream'
import parallel from 'node-parallel'
import request from 'request'
import moment from 'moment-timezone'
import parse from 'xml-parser'
import Twilio from 'twilio'

require('dotenv').config()

const log = Bunyan.createLogger({
	name: 'saro-sms',
	streams: [
		{
			level: 'info',
			type: 'raw',
			stream: bunyanDebugStream({
				basepath: path.resolve('.'),
				forceColor: true,
			}),
		},
		{
			level: 'debug',
			type: 'file',
			path: process.env.LOG_PATH,
		},
	]
})

log.level('debug')

const twilio = new Twilio(process.env.TWILIO_SID, process.env.TWILIO_AUTH_TOKEN)
const senderID = String(process.env.SENDER_ID || '')
const sendInterval = Number(process.env.SEND_INTERVAL_MS) || 30000

function error (...args) {
	log.error(...args)
	process.exit(1)
}

try {
	const sendersFile = path.resolve(process.env.SENDERS_DB_PATH)
	const recipientsFile = path.resolve(process.env.RECIPIENTS_DB_PATH)
	const senders = require(sendersFile)
	var recipients = require(recipientsFile)
	const validNumber = /^\+[0-9]{11,13}$/

	senders.forEach((number) => {
		if ( ! number.match(validNumber)) return error({ number }, 'Invalid sender Twilio number.')
	})

	recipients = recipients.map((recipient, i) => {
		// Note: recipient.name is optional
		if ( ! recipient.location) return error({ recipient }, 'Missing recipient location.')
		if ( ! recipient.number) return error({ recipient }, 'Missing recipient number.')
		if ( ! recipient.latitude) return error({ recipient }, 'Missing recipient latitude.')
		if ( ! recipient.longitude) return error({ recipient }, 'Missing recipient longitude.')

		recipient.name = (recipient.name || 'Unnamed').toUpperCase().trim()
		recipient.location = recipient.location.toUpperCase().trim()
		recipient.twilio_number = senders[i % senders.length]
		recipient.format = (typeof recipient.format === 'number' ? recipient.format : 1)

		if ( ! recipient.number.match(validNumber)) return error({ recipient }, 'Invalid recipient number.')
		if ( ! recipient.twilio_number) return error({ recipient }, 'Invalid recipient Twilio number.')

		return recipient
	})

	//console.log(senders, recipients); process.exit(1)

	const p = parallel().timeout(4 * 60 * 60 * 1000)
	const date = moment.utc().startOf('day')
	const tomorrow = date.clone().add(1, 'day')

	function findMeasurementForDateTime (measurements, date, time = '00:00') {
		const dateString = date.format('YYYY-MM-DD')
		const measurement = _.find(measurements, (child) => child.attributes.dt === `${dateString} ${time}`)

		if (measurement) return measurement.attributes
	}

	function prefixWithLocation (location, text, separator = ' ') {
		if (location.length + separator.length + text.length  <= 160) {
			return `${location}${separator}${text}`
		}

		return `${location.substr(0, 160 - separator.length - text.length - 1 /* dot */)}.${separator}${text}`
	}

	function createTextLineFormat1 (prefix, m) {
		return `${prefix} rain ${Math.ceil(m.pr)}mm ${m.pp}% temp ${m.t}C wind ${m.wn} ${Math.round(m.ws * 3.6)}kmh hum ${m.rh}%`
	}

	function probability (percentage) {
		if (percentage <= 0.10) return 'no'
		if (percentage <= 0.50) return 'small'
		if (percentage > 0.50) return 'high'
		return 'unknown'
	}

	function intensity (mm) {
		if (mm <= 0) return 'no'
		if (mm <= 10) return 'light'
		if (mm > 10) return 'heavy'
		return 'unknown'
	}

	function createTextLineFormat2 (prefix, m) {
		return `${prefix} ${probability(m.pp)} chance ${intensity(m.pr)} rain.`
	}

	function sendText (from, to, text, cb) {
		log.debug({ type: 'sending', from, to, text }, '')

		twilio.messages.create({
			from,
			to,
			body: text,
		}, (err, result) => {
			const sid = (result ? result.sid : null)
			log.debug({ type: 'sent', to, success: ! err, sid }, err && err.message || '')
			cb(err)
		})
	}

	recipients.forEach((recipient, i) => {
		p.add((done) => {
			setTimeout(() => {
				const url = `${process.env.NAVIFEED_URL}&lat=${recipient.latitude}&lon=${recipient.longitude}`

				request({
					method: 'GET',
					url,
					headers: {
						'Accept': 'text/xml',
					},
				}, (err, res, body) => {
					if (err) return error(err)

					log.debug({ type: 'raw', recipient, body })

					const data = parse(body)
					const measurements = _(data).get('root.children.0.children')

					function measurementsForDate (date) {
						var night     = findMeasurementForDateTime(measurements, date, '00:00')
						var morning   = findMeasurementForDateTime(measurements, date, '06:00')
						var afternoon = findMeasurementForDateTime(measurements, date, '12:00')
						var evening   = findMeasurementForDateTime(measurements, date, '18:00')

						if ( ! night || ! morning || ! afternoon || ! evening) {
							var err = 'Expected night, morning, afternoon and evening measurement.'
							log.error({ recipient, body }, err)
							return done(err)
						}

						return { night, morning, afternoon, evening }
					}

					var night, morning, afternoon, evening, text

					switch (recipient.format) {
					default:
					case 1:
						var { morning, afternoon, evening } = measurementsForDate(date)

						text = prefixWithLocation(recipient.location, [
							`${date.format('MMM D')}`,
							createTextLineFormat1('Morn', morning),
							createTextLineFormat1('Aft', afternoon),
							createTextLineFormat1('Eve', evening),
						].join('\n'))

						sendText(senderID, recipient.number, text, done)
						break
					case 2:
						var { night, morning, afternoon, evening } = measurementsForDate(tomorrow)

						text = prefixWithLocation(recipient.location, [
							`${tomorrow.format('MMM D')}`,
							createTextLineFormat2('Night', night),
							createTextLineFormat2('Morning', morning),
							createTextLineFormat2('Afternoon', afternoon),
							createTextLineFormat2('Evening', evening),
						].join('\n'))

						sendText(recipient.twilio_number, recipient.number, text, done)
						break
					}
				})
			}, i * sendInterval)
		})
	})

	p.done((err) => {
		if (err) return error(err)
		log.info('Done.')
	})
} catch (err) {
	error(err)
}
<commit_msg>Improve error handling.<commit_after>import path from 'path'
import _ from 'lodash'
import Bunyan from 'bunyan'
import bunyanDebugStream from 'bunyan-debug-stream'
import parallel from 'node-parallel'
import request from 'request'
import moment from 'moment-timezone'
import parse from 'xml-parser'
import Twilio from 'twilio'

require('dotenv').config()

const log = Bunyan.createLogger({
	name: 'saro-sms',
	streams: [
		{
			level: 'info',
			type: 'raw',
			stream: bunyanDebugStream({
				basepath: path.resolve('.'),
				forceColor: true,
			}),
		},
		{
			level: 'debug',
			type: 'file',
			path: process.env.LOG_PATH,
		},
	]
})

log.level('debug')

const twilio = new Twilio(process.env.TWILIO_SID, process.env.TWILIO_AUTH_TOKEN)
const senderID = String(process.env.SENDER_ID || '')
const sendInterval = Number(process.env.SEND_INTERVAL_MS) || 30000

function error (...args) {
	log.error(...args)
	process.exit(1)
}

try {
	const sendersFile = path.resolve(process.env.SENDERS_DB_PATH)
	const recipientsFile = path.resolve(process.env.RECIPIENTS_DB_PATH)
	const senders = require(sendersFile)
	var recipients = require(recipientsFile)
	const validNumber = /^\+[0-9]{11,13}$/

	senders.forEach((number) => {
		if ( ! number.match(validNumber)) return error({ number }, 'Invalid sender Twilio number.')
	})

	recipients = recipients.map((recipient, i) => {
		// Note: recipient.name is optional
		if ( ! recipient.location) return error({ recipient }, 'Missing recipient location.')
		if ( ! recipient.number) return error({ recipient }, 'Missing recipient number.')
		if ( ! recipient.latitude) return error({ recipient }, 'Missing recipient latitude.')
		if ( ! recipient.longitude) return error({ recipient }, 'Missing recipient longitude.')

		recipient.name = (recipient.name || 'Unnamed').toUpperCase().trim()
		recipient.location = recipient.location.toUpperCase().trim()
		recipient.twilio_number = senders[i % senders.length]
		recipient.format = (typeof recipient.format === 'number' ? recipient.format : 1)

		if ( ! recipient.number.match(validNumber)) return error({ recipient }, 'Invalid recipient number.')
		if ( ! recipient.twilio_number) return error({ recipient }, 'Invalid recipient Twilio number.')

		return recipient
	})

	//console.log(senders, recipients); process.exit(1)

	const p = parallel().timeout(4 * 60 * 60 * 1000)
	const date = moment.utc().startOf('day')
	const tomorrow = date.clone().add(1, 'day')

	function findMeasurementForDateTime (measurements, date, time = '00:00') {
		const dateString = date.format('YYYY-MM-DD')
		const measurement = _.find(measurements, (child) => child.attributes.dt === `${dateString} ${time}`)

		if (measurement) return measurement.attributes
	}

	function prefixWithLocation (location, text, separator = ' ') {
		if (location.length + separator.length + text.length  <= 160) {
			return `${location}${separator}${text}`
		}

		return `${location.substr(0, 160 - separator.length - text.length - 1 /* dot */)}.${separator}${text}`
	}

	function createTextLineFormat1 (prefix, m) {
		return `${prefix} rain ${Math.ceil(m.pr)}mm ${m.pp}% temp ${m.t}C wind ${m.wn} ${Math.round(m.ws * 3.6)}kmh hum ${m.rh}%`
	}

	function probability (percentage) {
		if (percentage <= 0.10) return 'no'
		if (percentage <= 0.50) return 'small'
		if (percentage > 0.50) return 'high'
		return 'unknown'
	}

	function intensity (mm) {
		if (mm <= 0) return 'no'
		if (mm <= 10) return 'light'
		if (mm > 10) return 'heavy'
		return 'unknown'
	}

	function createTextLineFormat2 (prefix, m) {
		return `${prefix} ${probability(m.pp)} chance ${intensity(m.pr)} rain.`
	}

	function sendText (from, to, text, cb) {
		log.debug({ type: 'sending', from, to, text }, '')

		twilio.messages.create({
			from,
			to,
			body: text,
		}, (err, result) => {
			const sid = (result ? result.sid : null)
			log.debug({ type: 'sent', to, success: ! err, sid }, err && err.message || '')
			cb(err)
		})
	}

	recipients.forEach((recipient, i) => {
		p.add((done) => {
			setTimeout(() => {
				const url = `${process.env.NAVIFEED_URL}&lat=${recipient.latitude}&lon=${recipient.longitude}`

				request({
					method: 'GET',
					url,
					headers: {
						'Accept': 'text/xml',
					},
				}, (err, res, body) => {
					if (err) return error(err)

					try {
						log.debug({ type: 'raw', recipient, body })

						const data = parse(body)
						const measurements = _(data).get('root.children.0.children')

						function measurementsForDate (date) {
							var night     = findMeasurementForDateTime(measurements, date, '00:00')
							var morning   = findMeasurementForDateTime(measurements, date, '06:00')
							var afternoon = findMeasurementForDateTime(measurements, date, '12:00')
							var evening   = findMeasurementForDateTime(measurements, date, '18:00')

							if ( ! night || ! morning || ! afternoon || ! evening) {
								var err = 'Expected night, morning, afternoon and evening measurement.'
								log.error({ recipient, body }, err)
								return done(err)
							}

							return { night, morning, afternoon, evening }
						}

						var night, morning, afternoon, evening, text

						switch (recipient.format) {
						default:
						case 1:
							var { morning, afternoon, evening } = measurementsForDate(date)

							text = prefixWithLocation(recipient.location, [
								`${date.format('MMM D')}`,
								createTextLineFormat1('Morn', morning),
								createTextLineFormat1('Aft', afternoon),
								createTextLineFormat1('Eve', evening),
							].join('\n'))

							sendText(senderID, recipient.number, text, done)
							break
						case 2:
							var { night, morning, afternoon, evening } = measurementsForDate(tomorrow)

							text = prefixWithLocation(recipient.location, [
								`${tomorrow.format('MMM D')}`,
								createTextLineFormat2('Night', night),
								createTextLineFormat2('Morning', morning),
								createTextLineFormat2('Afternoon', afternoon),
								createTextLineFormat2('Evening', evening),
							].join('\n'))

							sendText(recipient.twilio_number, recipient.number, text, done)
							break
						}
					} catch (err) {
						done(err)
					}
				})
			}, i * sendInterval)
		})
	})

	p.done((err) => {
		if (err) return error(err)
		log.info('Done.')
	})
} catch (err) {
	error(err)
}
<|endoftext|>


<commit_before>'use strict';

/*
 * Notifications JS Consumer
 */

(function(require, module) {
  var request = require('./request');

  window.Notifications = require('./notifications')(request);

}(require, module));
<commit_msg>Improved index<commit_after>'use strict';

/*
 * Notifications JS Consumer
 */

(function(require, module) {
  var request = require('./request');

  var Notifications = require('./notifications')(request);

  if(window) {
    window.Notifications = Notifications;
  }
  if(module && module.exports) {
    module.exports = Notifications;
  }

}(require, module));
<|endoftext|>


<commit_before>// Module must be started with environment variables
//
//  accesskey="api.ai client access key"
//  subscriptionkey="api.ai subscription key"
//  slackkey="slack bot key"
//

'use strict';

const Botkit = require('botkit');

const apiai = require('apiai');
const uuid = require('node-uuid');

const http = require('http');

const Entities = require('html-entities').XmlEntities;
const decoder = new Entities();

const apiAiAccessToken = process.env.accesstoken;
const apiAiSubscriptionKey = process.env.subscriptionkey;
const slackBotKey = process.env.slackkey;

const apiAiService = apiai(apiAiAccessToken, apiAiSubscriptionKey);

var sessionIds = {};

const controller = Botkit.slackbot({
    debug: false
    //include "log: false" to disable logging
});

var bot = controller.spawn({
    token: slackBotKey
}).startRTM();

function isDefined(obj) {
    if (typeof obj == 'undefined') {
        return false;
    }

    if (!obj) {
        return false;
    }

    return obj != null;
}

controller.hears(['.*'], ['bot_message'], function (bot, message) {

    try {
        if (message.type == 'message') {
            if (message.user == bot.identity.id) {
                // message from bot can be skipped
            }
            else if (message.text.indexOf("<@U") == 0 && message.text.indexOf(bot.identity.id) == -1) {
                // skip other users direct mentions
            }
            else if (message.text.includes("Sent text to")) {
                // skip sent text confirmations from Burner
                console.log('Skipping Burner response.');
            }
            else {

                var requestText = decoder.decode(message.text);
                requestText = requestText.replace("’", "'");

                var burnerMesageRegex = /Inbound message from \+(\d*):\s(.*)/;
                var returnNumber = '';
                var smsMessage;

                // Parse the SMS message and return number out of Burner's slackbot message
                if ((smsMessage = burnerMesageRegex.exec(requestText)) !== null) {
                    returnNumber = '@' + smsMessage[1];
                    requestText = smsMessage[2];

                    console.log('returnNumber', returnNumber);
                    console.log('requestText', requestText);
                }

                var channel = message.channel;
                var messageType = message.event;
                var botId = "<@" + bot.identity.id + ">";

                console.log(messageType);

                if (requestText.indexOf(botId) > -1) {
                    requestText = requestText.replace(botId, '');
                }

                if (!(channel in sessionIds)) {
                    sessionIds[channel] = uuid.v1();
                }

                var request = apiAiService.textRequest(requestText,
                    {
                        sessionId: sessionIds[channel]
                    });

                request.on('response', function (response) {
                    console.log(response);

                    if (isDefined(response.result)) {
                        // Preface the response with the appropriate return SMS number.
                        var responseText = returnNumber + ' ' + response.result.fulfillment.speech;
                        var action = response.result.action;

                        if (isDefined(responseText)) {
                            bot.reply(message, responseText, function (err, resp) {
                                console.log(err, resp);
                            });
                        }

                    }
                });

                request.on('error', function (error) {
                    console.error(error);
                });

                request.end();
            }
        }
    } catch (err) {
        console.error(err);
    }

});

//Create a server to prevent Heroku kills the bot
var server = http.createServer(function (req, res) {
    res.end()
});

//Lets start our server
server.listen((process.env.PORT || 5000), function () {
    console.log("Server listening");
});<commit_msg>Switch to new Burner Slackbot text message syntax<commit_after>// Module must be started with environment variables
//
//  accesskey="api.ai client access key"
//  subscriptionkey="api.ai subscription key"
//  slackkey="slack bot key"
//

'use strict';

const Botkit = require('botkit');

const apiai = require('apiai');
const uuid = require('node-uuid');

const http = require('http');

const Entities = require('html-entities').XmlEntities;
const decoder = new Entities();

const apiAiAccessToken = process.env.accesstoken;
const apiAiSubscriptionKey = process.env.subscriptionkey;
const slackBotKey = process.env.slackkey;

const apiAiService = apiai(apiAiAccessToken, apiAiSubscriptionKey);

var sessionIds = {};

const controller = Botkit.slackbot({
    debug: false
    //include "log: false" to disable logging
});

var bot = controller.spawn({
    token: slackBotKey
}).startRTM();

function isDefined(obj) {
    if (typeof obj == 'undefined') {
        return false;
    }

    if (!obj) {
        return false;
    }

    return obj != null;
}

controller.hears(['.*'], ['bot_message'], function (bot, message) {

    try {
        if (message.type == 'message') {
            if (message.user == bot.identity.id) {
                // message from bot can be skipped
            }
            else if (message.text.indexOf("<@U") == 0 && message.text.indexOf(bot.identity.id) == -1) {
                // skip other users direct mentions
            }
            else if (message.text.includes("Sent text to")) {
                // skip sent text confirmations from Burner
                console.log('Skipping Burner response.');
            }
            else {

                var requestText = decoder.decode(message.text);
                requestText = requestText.replace("’", "'");

                var burnerMesageRegex = /Inbound message from \+(\d*):\s(.*)/;
                var returnNumber = '';
                var smsMessage;

                // Parse the SMS message and return number out of Burner's slackbot message
                if ((smsMessage = burnerMesageRegex.exec(requestText)) !== null) {
                    returnNumber = '@' + smsMessage[1];
                    requestText = smsMessage[2];

                    console.log('returnNumber', returnNumber);
                    console.log('requestText', requestText);
                }

                var channel = message.channel;
                var messageType = message.event;
                var botId = "<@" + bot.identity.id + ">";

                console.log(messageType);

                if (requestText.indexOf(botId) > -1) {
                    requestText = requestText.replace(botId, '');
                }

                if (!(channel in sessionIds)) {
                    sessionIds[channel] = uuid.v1();
                }

                var request = apiAiService.textRequest(requestText,
                    {
                        sessionId: sessionIds[channel]
                    });

                request.on('response', function (response) {
                    console.log(response);

                    if (isDefined(response.result)) {
                        // Preface the response with the appropriate Burner command and phone
                        // number for the response SMS message.
                        var responseText = '/burner text ' + returnNumber + ' ' + response.result.fulfillment.speech;
                        var action = response.result.action;

                        if (isDefined(responseText)) {
                            bot.reply(message, responseText, function (err, resp) {
                                console.log(err, resp);
                            });
                        }

                    }
                });

                request.on('error', function (error) {
                    console.error(error);
                });

                request.end();
            }
        }
    } catch (err) {
        console.error(err);
    }

});

//Create a server to prevent Heroku kills the bot
var server = http.createServer(function (req, res) {
    res.end()
});

//Lets start our server
server.listen((process.env.PORT || 5000), function () {
    console.log("Server listening");
});<|endoftext|>