<commit_before>var EventEmitter = require('events').EventEmitter;
var fs = require('fs');
var path = require('path');

module.exports = function walk (dir, opts, emitter, dstat) {
    if (!opts) opts = {};
    var fdir = opts._original || dir;
    opts._original = undefined;

    if (!emitter) {
        emitter = new EventEmitter;
        emitter._pending = 0;
        emitter._seen = {};
    }
    emitter._pending ++;

    if (dstat) {
        var stopped = false;
        emitter.emit('directory', fdir, dstat, function stop () {
            stopped = true;
        });
        emitter.emit('path', fdir, dstat);
        if (!stopped) fs.readdir(dir, onreaddir);
        else check()
    }
    else fs.lstat(dir, function onstat (err, stat) {
        if (err) return finish();
        emitter._seen[stat.ino] = true;

        if (stat.isSymbolicLink() && opts.followSymlinks) {
            emitter.emit('link', fdir, stat);
            fs.readlink(dir, function (err, rfile) {
                if (err) return finish();
                var file_ = path.resolve(dir, rfile);
                emitter.emit('readlink', fdir, file_);
                fs.lstat(file_, onstat);
            });
        }
        else if (stat.isSymbolicLink()) {
            emitter.emit('link', fdir, stat);
            emitter.emit('path', fdir, stat);
            finish();
        }
        else if (stat.isDirectory()) {
            var stopped = false;
            emitter.emit('directory', fdir, stat, function stop () {
                stopped = true;
            });
            emitter.emit('path', fdir, stat);
            if (!stopped) fs.readdir(dir, onreaddir);
            else check()
        }
        else {
            emitter.emit('file', fdir, stat);
            emitter.emit('path', fdir, stat);
            finish();
        }
    });

    return emitter;

    function check () {
        if (-- emitter._pending === 0) finish();
    }

    function finish () {
        emitter.emit('end');
        emitter._seen = null;
    }

    function onreaddir (err, files) {
        emitter._pending --;
        if (err) return check();

        files.forEach(function (rfile) {
            emitter._pending ++;
            var file = path.join(fdir, rfile);

            fs.lstat(file, function (err, stat) {
                if (err) check()
                else onstat(file, stat)
            });
        });
    }

    function onstat (file, stat, original) {
        if (emitter._seen[stat.ino]) return check();
        emitter._seen[stat.ino] = true;

        if (stat.isDirectory()) {
            if (original) opts._original = original;
            walk(file, opts, emitter, stat);
            check();
        }
        else if (stat.isSymbolicLink() && opts.followSymlinks) {
            emitter.emit('link', file, stat);

            fs.readlink(file, function (err, rfile) {
                if (err) return check();
                var file_ = path.resolve(path.dirname(file), rfile);

                emitter.emit('readlink', file, file_);
                fs.lstat(file_, function (err, stat_) {
                    if (err) return check();

                    emitter._pending ++;
                    onstat(file_, stat_, file);
                    check();
                });
            });
        }
        else if (stat.isSymbolicLink()) {
            emitter.emit('link', file, stat);
            emitter.emit('path', file, stat);
            check();
        }
        else {
            emitter.emit('file', file, stat);
            emitter.emit('path', file, stat);
            check();
        }
    }
};
<commit_msg>fallback to checking file on windows which doesn't have stat.ino<commit_after>var EventEmitter = require('events').EventEmitter;
var fs = require('fs');
var path = require('path');

module.exports = function walk (dir, opts, emitter, dstat) {
    if (!opts) opts = {};
    var fdir = opts._original || dir;
    opts._original = undefined;

    if (!emitter) {
        emitter = new EventEmitter;
        emitter._pending = 0;
        emitter._seen = {};
    }
    emitter._pending ++;

    if (dstat) {
        var stopped = false;
        emitter.emit('directory', fdir, dstat, function stop () {
            stopped = true;
        });
        emitter.emit('path', fdir, dstat);
        if (!stopped) fs.readdir(dir, onreaddir);
        else check()
    }
    else fs.lstat(dir, function onstat (err, stat) {
        if (err) return finish();
        emitter._seen[stat.ino || dir] = true;

        if (stat.isSymbolicLink() && opts.followSymlinks) {
            emitter.emit('link', fdir, stat);
            fs.readlink(dir, function (err, rfile) {
                if (err) return finish();
                var file_ = path.resolve(dir, rfile);
                emitter.emit('readlink', fdir, file_);
                fs.lstat(file_, onstat);
            });
        }
        else if (stat.isSymbolicLink()) {
            emitter.emit('link', fdir, stat);
            emitter.emit('path', fdir, stat);
            finish();
        }
        else if (stat.isDirectory()) {
            var stopped = false;
            emitter.emit('directory', fdir, stat, function stop () {
                stopped = true;
            });
            emitter.emit('path', fdir, stat);
            if (!stopped) fs.readdir(dir, onreaddir);
            else check()
        }
        else {
            emitter.emit('file', fdir, stat);
            emitter.emit('path', fdir, stat);
            finish();
        }
    });

    return emitter;

    function check () {
        if (-- emitter._pending === 0) finish();
    }

    function finish () {
        emitter.emit('end');
        emitter._seen = null;
    }

    function onreaddir (err, files) {
        emitter._pending --;
        if (err) return check();

        files.forEach(function (rfile) {
            emitter._pending ++;
            var file = path.join(fdir, rfile);

            fs.lstat(file, function (err, stat) {
                if (err) check()
                else onstat(file, stat)
            });
        });
    }

    function onstat (file, stat, original) {
        if (emitter._seen[stat.ino || file]) return check();
        emitter._seen[stat.ino || file] = true;

        if (stat.isDirectory()) {
            if (original) opts._original = original;
            walk(file, opts, emitter, stat);
            check();
        }
        else if (stat.isSymbolicLink() && opts.followSymlinks) {
            emitter.emit('link', file, stat);

            fs.readlink(file, function (err, rfile) {
                if (err) return check();
                var file_ = path.resolve(path.dirname(file), rfile);

                emitter.emit('readlink', file, file_);
                fs.lstat(file_, function (err, stat_) {
                    if (err) return check();

                    emitter._pending ++;
                    onstat(file_, stat_, file);
                    check();
                });
            });
        }
        else if (stat.isSymbolicLink()) {
            emitter.emit('link', file, stat);
            emitter.emit('path', file, stat);
            check();
        }
        else {
            emitter.emit('file', file, stat);
            emitter.emit('path', file, stat);
            check();
        }
    }
};
<|endoftext|>


<commit_before>'use strict';
var postcss = require('postcss');

module.exports = postcss.plugin('postcss-scopify', scopify);

function scopify(scope, options) {

  options = options || {};

  return function(root) {

     // guard statment- allow only valid scopes
     if(!isValidScope(scope)){
        throw root.error('invalid scope', { plugin: 'postcss-scopify' });
     }

    root.eachRule(function (rule) {
      if (!rule.selectors){
        return rule;
      }

      rule.selectors = rule.selectors.map(function(selector) {
        if (isScopeApplied(selector,scope)) {
          return selector;
        }

          return scope + ' ' + selector;

      });
    });
  };
}

/**
 * Determine if selector is already scoped
 *
 * @param {string} selector
 * @param {string} scope
 */
function isScopeApplied(selector,scope) {
  return selector.indexOf(scope) === 0;
}

/**
 * Determine if scope is valid
 *
 * @param {string} scope
 */
function isValidScope(scope) {
    if (scope){
        return scope.indexOf(',') ===  -1;
    }
    else{
        return true;
    }

}
<commit_msg>fixed isValidScope<commit_after>'use strict';
var postcss = require('postcss');

module.exports = postcss.plugin('postcss-scopify', scopify);

function scopify(scope, options) {

  options = options || {};

  return function(root) {

     // guard statment- allow only valid scopes
     if(!isValidScope(scope)){
        throw root.error('invalid scope', { plugin: 'postcss-scopify' });
     }

    root.eachRule(function (rule) {
      if (!rule.selectors){
        return rule;
      }

      rule.selectors = rule.selectors.map(function(selector) {
        if (isScopeApplied(selector,scope)) {
          return selector;
        }

          return scope + ' ' + selector;

      });
    });
  };
}

/**
 * Determine if selector is already scoped
 *
 * @param {string} selector
 * @param {string} scope
 */
function isScopeApplied(selector,scope) {
  return selector.indexOf(scope) === 0;
}

/**
 * Determine if scope is valid
 *
 * @param {string} scope
 */
function isValidScope(scope) {
    if (scope){
        return scope.indexOf(',') ===  -1;
    }
    else{
        return false;
    }

}
<|endoftext|>


<commit_before>const yaml = require('js-yaml');
const visitor = require('probot-visitor');
const Freeze = require('./lib/freeze');
const formatParser = require('./lib/format-parser');
const githubHelper = require('./lib/github-helper');

/* Configuration Variables */

module.exports = robot => {
  robot.on('integration_installation.added', config);
  robot.on('issue_comment', handleFreeze);
  const visit = visitor(robot, {interval: 60 * 5 * 1000}, handleThaw);
  robot.on('test.visit', async context => {
    await handleThaw(75, context.payload.repository);
  });

  async function config(context) {
    const freeze = new Freeze(context.github, await getConfig(context.github, context.payload.repository));
    context.github.issues.getLabel(context.repositories_added[0]({
      name: freeze.labelName}).catch(() => {
        return context.github.issues.createLabel(context.repositories_added[0]({
          name: freeze.config.labelName,
          color: freeze.config.labelColor
        }));
      }));
  }

  async function handleFreeze(context) {
    const freeze = new Freeze(context.github, await getConfig(context.github, context.payload.repository));

    const comment = context.payload.comment;
    freeze.config.perform = true;
    if (freeze.config.perform && !context.isBot && freeze.freezable(comment)) {
      freeze.freeze(
        context,
        freeze.propsHelper(comment.user.login, comment.body)
    );
      console.log('issue just snoozed', context.issue());
    }
  }

  async function handleThaw(installation, repository) {
    const github = await robot.auth(installation.id);
    const freeze = new Freeze(github, await getConfig(github, repository));

    github.search.issues({q:'label:' + freeze.config.labelName, repo:repository.full_name}).then(resp => {
      resp.data.items.forEach(issue => {
        github.issues.getComments(githubHelper.parseCommentURL(issue.comments_url)).then(resp => {
          return freeze.getLastFreeze(resp.data);
        }).then(lastFreezeComment => {
          if (freeze.unfreezable(lastFreezeComment)) {
            freeze.unfreeze(issue, formatParser.propFromComment(lastFreezeComment));
          }
        });
      });
    });
    console.log('visitor/thaw run complete');
  }

  async function getConfig(github, repository) {
    const owner = repository.owner.login;
    const repo = repository.name;
    const path = '.github/probot-snooze.yml';
    let config = {};

    try {
      const resp = await github.repos.getContent({owner, repo, path});
      config = Object.assign(yaml.load(Buffer.from(resp.data.content, 'base64').toString()) || {}, {perform:true});
    } catch (err) {
      console.log('error', err);
      visit.stop(repository);
    }

    return Object.assign(config, {owner, repo, logger: robot.log});
  }
};
<commit_msg>continued code cleanup<commit_after>const yaml = require('js-yaml');
const visitor = require('probot-visitor');
const Freeze = require('./lib/freeze');
const formatParser = require('./lib/format-parser');
const githubHelper = require('./lib/github-helper');

/* Configuration Variables */

module.exports = robot => {
  robot.on('integration_installation.added', installationEvent);
  robot.on('issue_comment', handleFreeze);
  const visit = visitor(robot, {interval: 60 * 5 * 1000}, handleThaw);
  robot.on('test.visit', async context => {
    await handleThaw(75, context.payload.repository);
  });

  async function installationEvent(context) {
    const config = await getConfig(context.github, context.payload.repository);

    context.github.issues.getLabel(context.repositories_added[0]({
      name: config.labelName}).catch(() => {
        return context.github.issues.createLabel(context.repositories_added[0]({
          name: config.labelName,
          color: config.labelColor
        }));
      }));
  }

  async function handleFreeze(context) {
    const config = await getConfig(context.github, context.payload.repository);
    const freeze = new Freeze(context.github, config);

    const comment = context.payload.comment;
    freeze.config.perform = true;
    if (freeze.config.perform && !context.isBot && freeze.freezable(comment)) {
      freeze.freeze(
        context,
        freeze.propsHelper(comment.user.login, comment.body)
    );
    }
  }

  async function handleThaw(installation, repository) {
    const github = await robot.auth(installation.id);
    const config = await getConfig(github, repository);
    const freeze = new Freeze(github, config);

    github.search.issues({q:'label:' + freeze.config.labelName, repo:repository.full_name}).then(resp => {
      resp.data.items.forEach(issue => {
        github.issues.getComments(githubHelper.parseCommentURL(issue.comments_url)).then(resp => {
          return freeze.getLastFreeze(resp.data);
        }).then(lastFreezeComment => {
          if (freeze.unfreezable(lastFreezeComment)) {
            freeze.unfreeze(issue, formatParser.propFromComment(lastFreezeComment));
          }
        });
      });
    });
    console.log('visitor/thaw run complete');
  }

  async function getConfig(github, repository) {
    const owner = repository.owner.login;
    const repo = repository.name;
    const path = '.github/probot-snooze.yml';
    let config = {};

    try {
      const resp = await github.repos.getContent({owner, repo, path});
      config = Object.assign(yaml.load(Buffer.from(resp.data.content, 'base64').toString()) || {}, {perform:true});
    } catch (err) {
      console.log('error', err);
      visit.stop(repository);
    }

    return Object.assign(config, {owner, repo, logger: robot.log});
  }
};
<|endoftext|>


<commit_before>'use strict';

var path = require('path');

/**
 * Return a list of loaded and required modules.
 *
 * @returns {Array}
 * @api public
 */
module.exports = function moduleLoadList() {
  var natives = process.moduleLoadList || []
    , cwd = process.cwd();

  return natives.concat(Object.keys(require.cache).map(function map(line) {
    var dependency = line.lastIndexOf('node_modules');

    line = line.split('.').shift();

    if (~dependency) line = line.slice(dependency + 13);
    else {
      line = path.relative(cwd, line);
      if (line.charAt(0) !== '.') line = './'+ line;
    }

    line = line.split('/');
    if (line[line.length - 1] === 'index') line.pop();

    return 'UserModule '+ line.join('/');
  }));
};
<commit_msg>[fix] Filter out empty UserModules it can result in:<commit_after>'use strict';

var path = require('path');

/**
 * Return a list of loaded and required modules.
 *
 * @returns {Array}
 * @api public
 */
module.exports = function moduleLoadList() {
  var natives = process.moduleLoadList || []
    , cwd = process.cwd();

  return natives.concat(Object.keys(require.cache).map(function map(line) {
    var dependency = line.lastIndexOf('node_modules');

    line = line.split('.').shift();

    if (~dependency) {
      line = line.slice(dependency + 13);
    } else {
      line = path.relative(cwd, line);
      if (line.charAt(0) !== '.') line = './'+ line;
    }

    line = line.split('/');
    if (line[line.length - 1] === 'index') line.pop();
    if (!line.length) return;

    return 'UserModule '+ line.join('/');
  })).filter(Boolean);
};
<|endoftext|>


<commit_before>/* global AFRAME, THREE */

if (typeof AFRAME === 'undefined') {
  throw new Error('Component attempted to register before AFRAME was available.');
}

require('./lib/terrainloader.js');

/**
 * Terrain model component for A-Frame.
 */
AFRAME.registerComponent('terrain-model', {
  schema: {
    DEM: {
      type: 'asset'
    },
    texture: {
      type: 'asset'
    },
    alphaMap: {
      type: 'asset'
    },
    planeHeight: {
      type: 'number'
    },
    planeWidth: {
      type: 'number'
    },
    segmentsHeight: {
      type: 'number',
      default: 199
    },
    segmentsWidth: {
      type: 'number',
      default: 199
    },
    zPosition: {
      type: 'number',
      default: 1.5
    },
    transparent: {
      type: 'boolean',
      default: false
    },
    // If true, enable wireframe
    debug: { default: false }
  },

  /**
   * Set if component needs multiple instancing.
   */
  multiple: true,

  /**
   * Called when component is attached and when component data changes.
   * Generally modifies the entity based on the data.
   */
  update: function (oldData) {
    var el = this.el;
    var data = this.data;
    var debug = data.debug;
    var transparentMaterial = data.transparent;
    var surface;

    // Texture and terrain URLs
    var terrainURL = data.DEM;
    var textureURL = data.texture;
    var alphaMapURL = data.alphaMap;

    // Utility to load the DEM data
    var terrainLoader = new THREE.TerrainLoader();

    // Create the plane geometry
    var geometry = new THREE.PlaneBufferGeometry(data.planeWidth, data.planeHeight, data.segmentsWidth, data.segmentsHeight);

    // z-scaling factor
    var zPosition = data.zPosition;

    // The terrainLoader loads the DEM file and defines a function to be called when the file is successfully downloaded.
    terrainLoader.load(terrainURL, function (data) {

      // The position attribute buffer
      var pAB = geometry.getAttribute('position');

      /**
       * Set the z-component of every vector in the position attribute buffer to the (adjusted) height value from the DEM.
       * pAB.count = the number of vertices in the plane
       */
      for (var i = 0; i < pAB.count; i++) {
        var heightValue = data[i] / 65535 * zPosition;
        pAB.setZ(i, heightValue);
      }

      // Load texture, apply maximum anisotropy
      var textureLoader = new THREE.TextureLoader();
      var texture = textureLoader.load(textureURL);
      texture.anisotropy = 16;

      // Load alphaMap
      var alphaMap = alphaMapURL==="" ? null : new THREE.TextureLoader().load(alphaMapURL);

      // Create material
      var material = new THREE.MeshLambertMaterial({
          map: texture,
          alphaMap: alphaMap,
          transparent: transparentMaterial || (alphaMap!=null)
        });

      // Create the surface mesh and register it under entity's object3DMap
      surface = new THREE.Mesh(geometry, material);
      surface.rotation.x = -90 * Math.PI / 180;
      el.setObject3D('terrain', surface);

      // Wireframe debug mode
      if (debug) {
        var wireGeometry = new THREE.WireframeGeometry(geometry);
        var wireMaterial = new THREE.LineBasicMaterial({color: 0x4caf50, linewidth: 2});
        var wireMesh = new THREE.LineSegments(wireGeometry, wireMaterial);
        surface.add(wireMesh);
      }
    });
  },

  /**
   * Called when a component is removed (e.g., via removeAttribute).
   * Generally undoes all modifications to the entity.
   */
  remove: function () {
    this.el.removeObject3D('terrain-wireframe');
    this.el.removeObject3D('terrain');
  }
});
<commit_msg>Checkpoint<commit_after>/* global AFRAME, THREE */

if (typeof AFRAME === 'undefined') {
  throw new Error('Component attempted to register before AFRAME was available.');
}

require('./lib/terrainloader.js');

/**
 * Terrain model component for A-Frame.
 */
AFRAME.registerComponent('terrain-model', {
  schema: {
    DEM: {
      type: 'asset'
    },
    planeHeight: {
      type: 'number'
    },
    planeWidth: {
      type: 'number'
    },
    segmentsHeight: {
      type: 'number',
      default: 199
    },
    segmentsWidth: {
      type: 'number',
      default: 199
    },
    zPosition: {
      type: 'number',
      default: 1.5
    },
    colorScheme: {
      type: 'string',
      default: 'viridis'
    },
    wireframe: {
      type: 'boolean',
      default: false
    }
  },

  /**
   * Set if component needs multiple instancing.
   */
  multiple: true,

  /**
   * Called when component is attached and when component data changes.
   * Generally modifies the entity based on the data.
   */
  update: function (oldData) {
    // "self" is a reference to the component
    var self = this;
    var el = self.el;
    var data = self.data;

    var terrainLoader = new THREE.TerrainLoader();

    /*
     * terrainLoader loads the DEM file and triggers a callback.
     * "heightData" is a Uint16Array containing elevation values scaled to 0-65535 (i.e full 16-bit range)
     */
    terrainLoader.load(data.DEM, function (heightData) {

      var geometry = new THREE.PlaneBufferGeometry(data.planeWidth, data.planeHeight, data.segmentsWidth, data.segmentsHeight);

      // The position attribute buffer
      var pAB = geometry.getAttribute('position');

      // Formula for size of new buffer attribute array is: numVertices * itemSize
      // https://threejs.org/docs/index.html#api/core/BufferAttribute
      var colorArray = new Uint8Array(pAB.count * 3);
      var cBA = new THREE.BufferAttribute(colorArray, 3, true);
      var colorScale = self.getColorScale(data.colorScheme);

      /**
       * Set the z-component of every vector in the position attribute buffer to the (adjusted) height value from the DEM.
       * pAB.count = the number of vertices in the plane
       * Also sets vertex color.
       */
      for (let i = 0; i < pAB.count; i++) {
        let heightValue = heightData[i] / 65535 * data.zPosition;
        pAB.setZ(i, heightValue);

        let colorValue = d3.color(colorScale(heightData[i]));
        cBA.setXYZ(i, colorValue.r, colorValue.g, colorValue.b);
      }

      geometry.addAttribute('color', cBA);

      var material = new THREE.MeshLambertMaterial({
          vertexColors: THREE.VertexColors
        });

      // Create the surface mesh and register it under entity's object3DMap
      var surface = new THREE.Mesh(geometry, material);
      surface.rotation.x = -90 * Math.PI / 180;
      el.setObject3D('terrain', surface);

      // Wireframe
      if (data.wireframe) {
        let wireGeometry = new THREE.WireframeGeometry(geometry);
        let wireMaterial = new THREE.LineBasicMaterial({color: 0x808080, linewidth: 1});
        let wireMesh = new THREE.LineSegments(wireGeometry, wireMaterial);
        wireMesh.material.opacity = 0.30;
        wireMesh.material.transparent = true;
        surface.add(wireMesh);
      }
    });
  },

  /**
   * Called when a component is removed (e.g., via removeAttribute).
   * Generally undoes all modifications to the entity.
   */
  remove: function () {
    this.el.removeObject3D('terrain');
  },

  /**
   * Returns a sequential scale with chosen interpolater
   * Defaults to Viridis if unknown colorScheme is asked for (also logs error)
   */
  getColorScale: function(colorScheme) {

    switch(colorScheme) {
      case "viridis":
        return d3.scaleSequential(d3.interpolateViridis).domain([0, 65535]);
      case "inferno":
        return d3.scaleSequential(d3.interpolateInferno).domain([0, 65535]);
      case "magma":
        return d3.scaleSequential(d3.interpolateMagma).domain([0, 65535]);
      case "plasma":
        return d3.scaleSequential(d3.interpolatePlasma).domain([0, 65535]);
      case "warm":
        return d3.scaleSequential(d3.interpolateWarm).domain([0, 65535]);
      case "cool":
        return d3.scaleSequential(d3.interpolateCool).domain([0, 65535]);
      case "rainbow":
        return d3.scaleSequential(d3.interpolateRainbow).domain([0, 65535]);
      case "cubehelix":
        return d3.scaleSequential(d3.interpolateCubehelixDefault).domain([0, 65535]);
      default:
        console.log("terrain-model error: " + colorScheme + "is not a color scheme. Default color loaded instead.");
        return d3.scaleSequential(d3.interpolateViridis).domain([0, 65535]);
    }

  }
});

/**
 * Variant of terrain model component geared towards textures.
 * Currently needs to be refractored.
 */
AFRAME.registerComponent('textured-terrain-model', {
  schema: {
    DEM: {
      type: 'asset'
    },
    texture: {
      type: 'asset'
    },
    alphaMap: {
      type: 'asset'
    },
    planeHeight: {
      type: 'number'
    },
    planeWidth: {
      type: 'number'
    },
    segmentsHeight: {
      type: 'number',
      default: 199
    },
    segmentsWidth: {
      type: 'number',
      default: 199
    },
    zPosition: {
      type: 'number',
      default: 1.5
    },
    transparent: {
      type: 'boolean',
      default: false
    },
    debug: {
      type: 'boolean',
      default: false
    }
  },

  /**
   * Set if component needs multiple instancing.
   */
  multiple: true,

  /**
   * Called when component is attached and when component data changes.
   * Generally modifies the entity based on the data.
   */
  update: function (oldData) {
    // "self" is a reference to the component
    var self = this;
    var el = self.el;
    var data = self.data;
    var debug = data.debug;
    var transparentMaterial = data.transparent;

    var terrainURL = data.DEM;
    var textureURL = data.texture;
    var alphaMapURL = data.alphaMap;

    var terrainLoader = new THREE.TerrainLoader();
    var geometry = new THREE.PlaneBufferGeometry(data.planeWidth, data.planeHeight, data.segmentsWidth, data.segmentsHeight);

    // z-scaling factor
    var zPosition = data.zPosition;

    /*
     * terrainLoader loads the DEM file and triggers a callback.
     * "heightData" is a Uint16Array containing elevation values scaled to 0-65535 (i.e full 16-bit range)
     */
    terrainLoader.load(terrainURL, function (heightData) {

      // The position attribute buffer
      var pAB = geometry.getAttribute('position');

      /**
       * Set the z-component of every vector in the position attribute buffer to the (adjusted) height value from the DEM.
       * pAB.count = the number of vertices in the plane
       * Also sets vertex color.
       */
      for (let i = 0; i < pAB.count; i++) {
        let heightValue = heightData[i] / 65535 * zPosition;
        pAB.setZ(i, heightValue);
      }

      // Load textures and alphaMap (if applicable), apply maximum anisotropy
      var textureLoader = new THREE.TextureLoader();
      var texture = (textureURL === "") ? null : textureLoader.load(textureURL);
      //texture.anisotropy = 16;
      var alphaMap = (alphaMapURL === "") ? null : textureLoader.load(alphaMapURL);

      var material = new THREE.MeshLambertMaterial({
          map: texture,
          alphaMap: alphaMap,
          transparent: transparentMaterial || (alphaMap!=null)
        });

      // Create the surface mesh and register it under entity's object3DMap
      var surface = new THREE.Mesh(geometry, material);
      surface.rotation.x = -90 * Math.PI / 180;
      el.setObject3D('terrain', surface);

      // Wireframe debug mode
      if (debug) {
        var wireGeometry = new THREE.WireframeGeometry(geometry);
        var wireMaterial = new THREE.LineBasicMaterial({color: 0x808080, linewidth: 1});
        var wireMesh = new THREE.LineSegments(wireGeometry, wireMaterial);
        wireMesh.material.opacity = 0.30;
        wireMesh.material.transparent = true;
        surface.add(wireMesh);
      }
    });
  },

  /**
   * Called when a component is removed (e.g., via removeAttribute).
   * Generally undoes all modifications to the entity.
   */
  remove: function () {
    this.el.removeObject3D('terrain-wireframe');
    this.el.removeObject3D('terrain');
  }
});

<|endoftext|>


<commit_before>var _ = require("underscore");
var twitter = require("twitter");

var express = require("express");
var bodyParser = require("body-parser");
var errorHandler = require("errorhandler");

var config;
try {
  config = require("./config");
} catch(e) {
  console.log("Failed to find local config, falling back to environment variables");
  config = {
    pusher_app_id: process.env.PUSHER_APP_ID,
    pusher_key: process.env.PUSHER_KEY,
    pusher_secret: process.env.PUSHER_SECRET,
    twitter_consumer_key: process.env.TWITTER_CONSUMER_KEY,
    twitter_consumer_secret: process.env.TWITTER_CONSUMER_SECRET,
    twitter_access_token_key: process.env.TWITTER_ACCESS_TOKEN_KEY,
    twitter_access_token_secret: process.env.TWITTER_ACCESS_TOKEN_SECRET,
    keywords: (process.env.KEYWORDS) ? process.env.KEYWORDS.split(",") : [],
  }
}

var silent = true;

var keywords = config.keywords;
var keywordStats = {};

// Capture uncaught errors
process.on("uncaughtException", function(err) {
  console.log(err);

  if (!silent) console.log("Attempting to restart stream");
  setImmediate(restartStream);
});

// --------------------------------------------------------------------
// SET UP PUSHER
// --------------------------------------------------------------------
var Pusher = require("pusher");
var pusher = new Pusher({
  appId: config.pusher_app_id,
  key: config.pusher_key,
  secret: config.pusher_secret
});

// --------------------------------------------------------------------
// SET UP EXPRESS
// --------------------------------------------------------------------

var app = express();

// Parse application/json and application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({
  extended: true
}));
app.use(bodyParser.json());

// Ping
app.get("/ping", function(req, res) {
  res.status(200).end();
});

// TODO: Provide endpoint for accessing list of active keywords
app.get("/keywords.json", function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Content-Type");

  res.json(keywords);
});

// Get stats for past 24 hours
app.get("/stats/:keyword/24hours.json", function(req, res, next) {
  if (!keywordStats[req.params.keyword]) {
    res.status(404).end();
    return;
  }

  var statsCopy = JSON.parse(JSON.stringify(keywordStats[req.params.keyword].past24.data)).reverse();

  // Pop the current minute off
  var removedStat = statsCopy.pop();

  // Reduce total to account for removed stat
  var newTotal = keywordStats[req.params.keyword].past24.total - removedStat.value;

  var output = {
    total: newTotal,
    data: statsCopy
  };

  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Content-Type");

  res.json(output);
});

// Get stats for past 24 hours - Geckoboard formatting
app.get("/stats/:keyword/24hours-geckoboard.json", function(req, res, next) {
  if (!keywordStats[req.params.keyword]) {
    res.status(404).end();
    return;
  }

  var statsCopy = JSON.parse(JSON.stringify(keywordStats[req.params.keyword].past24.data)).reverse();

  // Pop the current minute off
  var removedStat = statsCopy.pop();

  // Reduce total to account for removed stat
  var newTotal = keywordStats[req.params.keyword].past24.total - removedStat.value;

  var numbers = [];

  _.each(statsCopy, function(stat) {
    numbers.push(stat.value)
  });

  var output = {
    item: [
      {
        text: "Past 24 hours",
        value: newTotal
      },
      numbers
    ]
  };

  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Content-Type");

  res.json(output);
});

// Simple logger
app.use(function(req, res, next){
  if (!silent) console.log("%s %s", req.method, req.url);
  if (!silent) console.log(req.body);
  next();
});

// Error handler
app.use(errorHandler({
  dumpExceptions: true,
  showStack: true
}));

// Open server on specified port
if (!silent) console.log("Starting Express server");
app.listen(process.env.PORT || 5001);

// --------------------------------------------------------------------
// STATS UPDATES
// --------------------------------------------------------------------

var statsTime = new Date();

// Populate initial statistics for each keyword
_.each(keywords, function(keyword) {
  if (!keywordStats[keyword]) {
    keywordStats[keyword] = {
      past24: {
        total: 0,
        // Per-minute, with anything after 24-hours removed
        data: [{
          value: 0,
          time: statsTime.getTime()
        }]
      }
    }
  }
});

var updateStats = function() {
  var currentTime = new Date();

  if (statsTime.getMinutes() == currentTime.getMinutes()) {
    setTimeout(function() {
      updateStats();
    }, 1000);

    return;
  }

  var statsPayload = {};

  _.each(keywords, function(keyword) {
    statsPayload[keyword] = {
      time: statsTime.getTime(),
      value: keywordStats[keyword].past24.data[0].value
    };

    // Add new minute with a count of 0
    keywordStats[keyword].past24.data.unshift({
      value: 0,
      time: currentTime.getTime()
    });

    // Crop array to last 24 hours
    if (keywordStats[keyword].past24.data.length > 1440) {
      if (!silent) console.log("Cropping stats array for past 24 hours");

      // Crop
      var removed = keywordStats[keyword].past24.data.splice(1439);

      // Update total
      _.each(removed, function(value) {
        keywordStats[keyword].past24.total -= value;
      });
    }
  });

  if (!silent) console.log("Sending previous minute via Pusher");
  if (!silent) console.log(statsPayload);

  // Send stats update via Pusher
  pusher.trigger("stats", "update", statsPayload);

  statsTime = currentTime;

  setTimeout(function() {
    updateStats();
  }, 1000);
};

updateStats();

// --------------------------------------------------------------------
// SET UP TWITTER
// --------------------------------------------------------------------

var twit = new twitter({
  consumer_key: config.twitter_consumer_key,
  consumer_secret: config.twitter_consumer_secret,
  access_token_key: config.twitter_access_token_key,
  access_token_secret: config.twitter_access_token_secret
});

var twitterStream;
var streamRetryCount = 0;
var streamRetryLimit = 10;
var streamRetryDelay = 1000;

var startStream = function() {
  twit.stream("filter", {
    track: keywords.join(",")
  }, function(stream) {
    twitterStream = stream;

    twitterStream.on("data", function(data) {
      if (streamRetryCount > 0) {
        streamRetryCount = 0;
      }

      processTweet(data);
    });

    twitterStream.on("error", function(error) {
      console.log("Error");
      console.log(error);

      setImmediate(restartStream);
    });

    twitterStream.on("end", function(response) {
      console.log("Stream end");
      setImmediate(restartStream);
    });
  });
};

var restartingStream = false;
var restartStream = function() {
  if (restartingStream) {
    if (!silent) console.log("Aborting stream retry as it is already being restarted");
  }

  if (!silent) console.log("Aborting previous stream");
  if (twitterStream) {
    twitterStream.destroy();
  }

  streamRetryCount += 1;
  restartingStream = true;

  if (streamRetryCount >= streamRetryLimit) {
    if (!silent) console.log("Aborting stream retry after too many attempts");
    return;
  }

  setTimeout(function() {
    restartingStream = false;
    startStream();
  }, streamRetryDelay * (streamRetryCount * 2));
};

var processTweet = function(tweet) {
  // Look for keywords within text
  _.each(keywords, function(keyword) {
    if (tweet.text.toLowerCase().indexOf(keyword.toLowerCase()) > -1) {
      if (!silent) console.log("A tweet about " + keyword);

      // Update stats
      keywordStats[keyword].past24.data[0].value += 1;
      keywordStats[keyword].past24.total += 1;
    }
  });
};

// Start stream after short timeout to avoid triggering multi-connection errors
setTimeout(startStream, 2000);<commit_msg>refactor silent flag<commit_after>var _ = require("underscore");
var twitter = require("twitter");

var express = require("express");
var bodyParser = require("body-parser");
var errorHandler = require("errorhandler");

var config;
try {
  config = require("./config");
} catch(e) {
  console.log("Failed to find local config, falling back to environment variables");
  config = {
    pusher_app_id: process.env.PUSHER_APP_ID,
    pusher_key: process.env.PUSHER_KEY,
    pusher_secret: process.env.PUSHER_SECRET,
    twitter_consumer_key: process.env.TWITTER_CONSUMER_KEY,
    twitter_consumer_secret: process.env.TWITTER_CONSUMER_SECRET,
    twitter_access_token_key: process.env.TWITTER_ACCESS_TOKEN_KEY,
    twitter_access_token_secret: process.env.TWITTER_ACCESS_TOKEN_SECRET,
    keywords: (process.env.KEYWORDS) ? process.env.KEYWORDS.split(",") : [],
    DEBUG: process.env.DEBUG || false
  }
}

var keywords = config.keywords;
var keywordStats = {};

function log() {
  if( config.DEBUG ) {
    console.log.apply( null, arguments );
  }
}

// Capture uncaught errors
process.on("uncaughtException", function(err) {
  console.log(err);

  log("Attempting to restart stream");
  setImmediate(restartStream);
});

// --------------------------------------------------------------------
// SET UP PUSHER
// --------------------------------------------------------------------
var Pusher = require("pusher");
var pusher = new Pusher({
  appId: config.pusher_app_id,
  key: config.pusher_key,
  secret: config.pusher_secret
});

// --------------------------------------------------------------------
// SET UP EXPRESS
// --------------------------------------------------------------------

var app = express();

// Parse application/json and application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({
  extended: true
}));
app.use(bodyParser.json());

// Ping
app.get("/ping", function(req, res) {
  res.status(200).end();
});

// TODO: Provide endpoint for accessing list of active keywords
app.get("/keywords.json", function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Content-Type");

  res.json(keywords);
});

// Get stats for past 24 hours
app.get("/stats/:keyword/24hours.json", function(req, res, next) {
  if (!keywordStats[req.params.keyword]) {
    res.status(404).end();
    return;
  }

  var statsCopy = JSON.parse(JSON.stringify(keywordStats[req.params.keyword].past24.data)).reverse();

  // Pop the current minute off
  var removedStat = statsCopy.pop();

  // Reduce total to account for removed stat
  var newTotal = keywordStats[req.params.keyword].past24.total - removedStat.value;

  var output = {
    total: newTotal,
    data: statsCopy
  };

  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Content-Type");

  res.json(output);
});

// Get stats for past 24 hours - Geckoboard formatting
app.get("/stats/:keyword/24hours-geckoboard.json", function(req, res, next) {
  if (!keywordStats[req.params.keyword]) {
    res.status(404).end();
    return;
  }

  var statsCopy = JSON.parse(JSON.stringify(keywordStats[req.params.keyword].past24.data)).reverse();

  // Pop the current minute off
  var removedStat = statsCopy.pop();

  // Reduce total to account for removed stat
  var newTotal = keywordStats[req.params.keyword].past24.total - removedStat.value;

  var numbers = [];

  _.each(statsCopy, function(stat) {
    numbers.push(stat.value)
  });

  var output = {
    item: [
      {
        text: "Past 24 hours",
        value: newTotal
      },
      numbers
    ]
  };

  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Content-Type");

  res.json(output);
});

// Simple logger
app.use(function(req, res, next){
  log("%s %s", req.method, req.url);
  log(req.body);
  next();
});

// Error handler
app.use(errorHandler({
  dumpExceptions: true,
  showStack: true
}));

// Open server on specified port
log("Starting Express server");
app.listen(process.env.PORT || 5001);

// --------------------------------------------------------------------
// STATS UPDATES
// --------------------------------------------------------------------

var statsTime = new Date();

// Populate initial statistics for each keyword
_.each(keywords, function(keyword) {
  if (!keywordStats[keyword]) {
    keywordStats[keyword] = {
      past24: {
        total: 0,
        // Per-minute, with anything after 24-hours removed
        data: [{
          value: 0,
          time: statsTime.getTime()
        }]
      }
    }
  }
});

var updateStats = function() {
  var currentTime = new Date();

  if (statsTime.getMinutes() == currentTime.getMinutes()) {
    setTimeout(function() {
      updateStats();
    }, 1000);

    return;
  }

  var statsPayload = {};

  _.each(keywords, function(keyword) {
    statsPayload[keyword] = {
      time: statsTime.getTime(),
      value: keywordStats[keyword].past24.data[0].value
    };

    // Add new minute with a count of 0
    keywordStats[keyword].past24.data.unshift({
      value: 0,
      time: currentTime.getTime()
    });

    // Crop array to last 24 hours
    if (keywordStats[keyword].past24.data.length > 1440) {
      log("Cropping stats array for past 24 hours");

      // Crop
      var removed = keywordStats[keyword].past24.data.splice(1439);

      // Update total
      _.each(removed, function(value) {
        keywordStats[keyword].past24.total -= value;
      });
    }
  });

  log("Sending previous minute via Pusher");
  log(statsPayload);

  // Send stats update via Pusher
  pusher.trigger("stats", "update", statsPayload);

  statsTime = currentTime;

  setTimeout(function() {
    updateStats();
  }, 1000);
};

updateStats();

// --------------------------------------------------------------------
// SET UP TWITTER
// --------------------------------------------------------------------

var twit = new twitter({
  consumer_key: config.twitter_consumer_key,
  consumer_secret: config.twitter_consumer_secret,
  access_token_key: config.twitter_access_token_key,
  access_token_secret: config.twitter_access_token_secret
});

var twitterStream;
var streamRetryCount = 0;
var streamRetryLimit = 10;
var streamRetryDelay = 1000;

var startStream = function() {
  twit.stream("sample", {}, function(stream) {
    twitterStream = stream;

    twitterStream.on("data", function(data) {
      if (streamRetryCount > 0) {
        streamRetryCount = 0;
      }

      processTweet(data);
    });

    twitterStream.on("error", function(error) {
      console.log("Error");
      console.log(error);

      setImmediate(restartStream);
    });

    twitterStream.on("end", function(response) {
      console.log("Stream end");
      setImmediate(restartStream);
    });
  });
};

var restartingStream = false;
var restartStream = function() {
  if (restartingStream) {
    log("Aborting stream retry as it is already being restarted");
  }

  log("Aborting previous stream");
  if (twitterStream) {
    twitterStream.destroy();
  }

  streamRetryCount += 1;
  restartingStream = true;

  if (streamRetryCount >= streamRetryLimit) {
    log("Aborting stream retry after too many attempts");
    return;
  }

  setTimeout(function() {
    restartingStream = false;
    startStream();
  }, streamRetryDelay * (streamRetryCount * 2));
};

var processTweet = function(tweet) {
  // Look for keywords within text
  _.each(keywords, function(keyword) {
    if (tweet.text.toLowerCase().indexOf(keyword.toLowerCase()) > -1) {
      log("A tweet about " + keyword);

      // Update stats
      keywordStats[keyword].past24.data[0].value += 1;
      keywordStats[keyword].past24.total += 1;
    }
  });
};

// Start stream after short timeout to avoid triggering multi-connection errors
setTimeout(startStream, 2000);
<|endoftext|>


<commit_before>const _ = require('lodash');
const path = require('path');
const fs = require('fs');
const yaml = require('js-yaml');

const defaultTimeout = {
  connect: 2,
  firstByte: 5,
  betweenBytes: 2,
};

/**
 * [readFilePromise description]
 * @param  {[type]} file [description]
 * @return {[type]}      [description]
 */
function readFilePromise(file) {
  return new Promise((resolve, reject) => {
    fs.readFile(file, 'utf8', (err, data) => {
      /* istanbul ignore if */
      if (err) {
        reject(err);
      } else {
        resolve(data);
      }
    });
  });
}

/* istanbul ignore next */
function writeFilePromise(file, data) {
  return new Promise((resolve, reject) => {
    fs.writeFile(file, data, (err) => {
      if (err) {
        reject(err);
      } else {
        resolve();
      }
    });
  });
}

function sort(items) {
  const arr = _.map(items, (item) => {
    const tmp = _.extend({}, item);
    let sortWeight = 0;
    if (!item.host) {
      sortWeight += 4;
    }
    if (!item.prefix) {
      sortWeight += 2;
    }
    tmp.sortKey = `${sortWeight}-${item.name}`;
    return tmp;
  });
  return _.sortBy(arr, item => item.sortKey);
}

function getBackendConfig(directors) {
  const sortedDirectors = sort(directors);
  return readFilePromise(path.join(__dirname,
      'template/backend.tpl'))
    .then((tpl) => {
      const template = _.template(tpl);
      const arr = [];
      _.forEach(sortedDirectors, (director) => {
        _.forEach(director.backends, (backend, i) => {
          const tmp = _.extend({
            timeout: _.extend({}, defaultTimeout, director.timeout),
          }, backend);
          tmp.name = `${_.camelCase(director.name)}${i}`;
          try {
            arr.push(template(tmp));
          } catch (err) {
            /* istanbul ignore next */
            console.error(err);
          }
        });
      });
      return arr.join('\n');
    });
}

function getInitConfig(directors) {
  const sortedDirectors = sort(directors);
  return readFilePromise(path.join(__dirname, 'template/init.tpl'))
    .then((tpl) => {
      const template = _.template(tpl);
      const arr = [];
      _.forEach(sortedDirectors, (director) => {
        const name = _.camelCase(director.name);
        const type = director.type || 'round_robin';
        arr.push(`new ${name} = directors.${type}();`);
        _.forEach(director.backends, (server, i) => {
          if (type === 'random' || type === 'hash') {
            arr.push(`${name}.add_backend(${name + i}, ${server.weight || 1});`);
          } else {
            arr.push(`${name}.add_backend(${name + i});`);
          }
        });
      });
      _.forEach(arr, (tmp, i) => {
        arr[i] = `  ${tmp}`;
      });
      return template({
        directors: arr.join('\n'),
      });
    });
}

function getBackendSelectConfig(directors) {
  const sortedDirectors = sort(directors);
  const result = [];
  let defaultDirector;
  _.forEach(sortedDirectors, (director) => {
    const arr = [];
    /* istanbul ignore else */
    if (director.host) {
      arr.push(`req.http.host == "${director.host}"`);
    }
    /* istanbul ignore else */
    if (director.prefix) {
      arr.push(`req.url ~ "^${director.prefix}"`);
    }
    const condition = arr.join(' && ');
    if (condition) {
      result.push({
        name: director.name,
        condition,
        type: director.type,
        hashKey: director.hashKey,
      });
    } else {
      defaultDirector = director;
    }
  });

  const getBackendHint = (director) => {
    if (director.type === 'hash') {
      const hashKey = director.hashKey || 'req.url';
      return `set req.backend_hint = ${_.camelCase(director.name)}.backend(${hashKey});`;
    }
    return `set req.backend_hint = ${_.camelCase(director.name)}.backend();`;
  };

  const arr = [];
  if (defaultDirector) {
    arr.push(getBackendHint(defaultDirector));
  }
  _.forEach(result, (item, i) => {
    if (i === 0) {
      arr.push(`if (${item.condition}) {`);
    } else {
      arr.push(`} elsif (${item.condition}) {`);
    }
    arr.push(`  ${getBackendHint(item)}`);
  });
  /* istanbul ignore else */
  if (arr.length) {
    if (arr.length > 1) {
      arr.push('}');
    }
    _.forEach(arr, (tmp, i) => {
      arr[i] = `  ${tmp}`;
    });
  }
  return arr.join('\n');
}

/**
 * [getConfig description]
 * @param  {[type]} serverList [description]
 * @return {[type]}            [description]
 */
function getConfig(directors) {
  const data = {};
  return getBackendConfig(directors).then((config) => {
    data.backendConfig = config;
    return getInitConfig(directors);
  }).then((config) => {
    data.initConfig = config;
    data.selectConfig = getBackendSelectConfig(directors);
    return data;
  });
}

function getPassRules(urls) {
  const rules = ['req.http.Cache-Control == "no-cache"'];
  _.forEach(urls, url => rules.push(`req.url ~ "${url}"`));
  return rules.join(' || ');
}

function getHash(hashConfig) {
  const arr = [];
  _.forEach(hashConfig, (item) => {
    if (_.isString(item)) {
      arr.push(`hash_data(${item});`);
      return;
    }
    const total = item.length;
    const tmpArr = [];
    _.forEach(item, (subItem, index) => {
      const hashStr = `  hash_data(${subItem});`;
      if (index === 0) {
        tmpArr.push(`if (${subItem}) {`);
        tmpArr.push(hashStr);
      } else if (index === total - 1) {
        tmpArr.push(`} else {`);
        tmpArr.push(hashStr);
        tmpArr.push('}');
      } else {
        tmpArr.push(`} elsif (${subItem}) {`);
        tmpArr.push(hashStr);
      }
    });
    arr.push(...tmpArr);
  });
  return _.map(arr, (item) => `  ${item}`).join('\n');
}

/**
 * [getVcl description]
 * @param  {[type]} config [description]
 * @return {[type]}        [description]
 */
function getVcl(conf) {
  const config = _.extend({
    version: new Date().toISOString(),
    timeout: defaultTimeout,
    urlPassList: ['cache-control=no-cache'],
    hash: [
      'req.url',
      [
        'req.http.host',
        'server.ip',
      ],
    ],
    hisForPassTTL: 120,
  }, conf);
  /* istanbul ignore if */
  if (!config.directors || !config.name) {
    throw new Error('directors, name can not be null');
  }
  if (!config.directors.length) {
    throw new Error('directors can not be empty');
  }
  _.forEach(config.directors, (item) => {
    if (!item.timeout) {
      /* eslint no-param-reassign:0 */
      item.timeout = config.timeout;
    }
    if (item.type === 'shard') {
      throw new Error('shard director is not support');
    }
  });
  const cloneConfig = _.extend({
    stale: 3,
    varnish: '5',
    hashConfig: getHash(config.hash),
    passRules: getPassRules(config.urlPassList),
  }, config);
  return getConfig(cloneConfig.directors).then((data) => {
    _.extend(cloneConfig, data);
    return readFilePromise(path.join(__dirname, 'template/varnish.tpl'));
  }).then(tpl => _.template(tpl)(cloneConfig));
}

function getVclFromFile(file) {
  const extname = path.extname(file);
  return readFilePromise(file)
    .then((data) => {
      const json = extname === '.yml' ? yaml.safeLoad(data) : JSON.parse(data);
      return getVcl(json);
    });
}

exports.getBackendConfig = getBackendConfig;
exports.getInitConfig = getInitConfig;
exports.getBackendSelectConfig = getBackendSelectConfig;
exports.getConfig = getConfig;
exports.getVcl = getVcl;
exports.getVclFromFile = getVclFromFile;
exports.writeVclToFile = writeFilePromise;
<commit_msg>eslint<commit_after>const _ = require('lodash');
const path = require('path');
const fs = require('fs');
const yaml = require('js-yaml');

const defaultTimeout = {
  connect: 2,
  firstByte: 5,
  betweenBytes: 2,
};

/**
 * [readFilePromise description]
 * @param  {[type]} file [description]
 * @return {[type]}      [description]
 */
function readFilePromise(file) {
  return new Promise((resolve, reject) => {
    fs.readFile(file, 'utf8', (err, data) => {
      /* istanbul ignore if */
      if (err) {
        reject(err);
      } else {
        resolve(data);
      }
    });
  });
}

/* istanbul ignore next */
function writeFilePromise(file, data) {
  return new Promise((resolve, reject) => {
    fs.writeFile(file, data, (err) => {
      if (err) {
        reject(err);
      } else {
        resolve();
      }
    });
  });
}

function sort(items) {
  const arr = _.map(items, (item) => {
    const tmp = _.extend({}, item);
    let sortWeight = 0;
    if (!item.host) {
      sortWeight += 4;
    }
    if (!item.prefix) {
      sortWeight += 2;
    }
    tmp.sortKey = `${sortWeight}-${item.name}`;
    return tmp;
  });
  return _.sortBy(arr, item => item.sortKey);
}

function getBackendConfig(directors) {
  const sortedDirectors = sort(directors);
  return readFilePromise(path.join(__dirname,
      'template/backend.tpl'))
    .then((tpl) => {
      const template = _.template(tpl);
      const arr = [];
      _.forEach(sortedDirectors, (director) => {
        _.forEach(director.backends, (backend, i) => {
          const tmp = _.extend({
            timeout: _.extend({}, defaultTimeout, director.timeout),
          }, backend);
          tmp.name = `${_.camelCase(director.name)}${i}`;
          try {
            arr.push(template(tmp));
          } catch (err) {
            /* istanbul ignore next */
            console.error(err);
          }
        });
      });
      return arr.join('\n');
    });
}

function getInitConfig(directors) {
  const sortedDirectors = sort(directors);
  return readFilePromise(path.join(__dirname, 'template/init.tpl'))
    .then((tpl) => {
      const template = _.template(tpl);
      const arr = [];
      _.forEach(sortedDirectors, (director) => {
        const name = _.camelCase(director.name);
        const type = director.type || 'round_robin';
        arr.push(`new ${name} = directors.${type}();`);
        _.forEach(director.backends, (server, i) => {
          if (type === 'random' || type === 'hash') {
            arr.push(`${name}.add_backend(${name + i}, ${server.weight || 1});`);
          } else {
            arr.push(`${name}.add_backend(${name + i});`);
          }
        });
      });
      _.forEach(arr, (tmp, i) => {
        arr[i] = `  ${tmp}`;
      });
      return template({
        directors: arr.join('\n'),
      });
    });
}

function getBackendSelectConfig(directors) {
  const sortedDirectors = sort(directors);
  const result = [];
  let defaultDirector;
  _.forEach(sortedDirectors, (director) => {
    const arr = [];
    /* istanbul ignore else */
    if (director.host) {
      arr.push(`req.http.host == "${director.host}"`);
    }
    /* istanbul ignore else */
    if (director.prefix) {
      arr.push(`req.url ~ "^${director.prefix}"`);
    }
    const condition = arr.join(' && ');
    if (condition) {
      result.push({
        name: director.name,
        condition,
        type: director.type,
        hashKey: director.hashKey,
      });
    } else {
      defaultDirector = director;
    }
  });

  const getBackendHint = (director) => {
    if (director.type === 'hash') {
      const hashKey = director.hashKey || 'req.url';
      return `set req.backend_hint = ${_.camelCase(director.name)}.backend(${hashKey});`;
    }
    return `set req.backend_hint = ${_.camelCase(director.name)}.backend();`;
  };

  const arr = [];
  if (defaultDirector) {
    arr.push(getBackendHint(defaultDirector));
  }
  _.forEach(result, (item, i) => {
    if (i === 0) {
      arr.push(`if (${item.condition}) {`);
    } else {
      arr.push(`} elsif (${item.condition}) {`);
    }
    arr.push(`  ${getBackendHint(item)}`);
  });
  /* istanbul ignore else */
  if (arr.length) {
    if (arr.length > 1) {
      arr.push('}');
    }
    _.forEach(arr, (tmp, i) => {
      arr[i] = `  ${tmp}`;
    });
  }
  return arr.join('\n');
}

/**
 * [getConfig description]
 * @param  {[type]} serverList [description]
 * @return {[type]}            [description]
 */
function getConfig(directors) {
  const data = {};
  return getBackendConfig(directors).then((config) => {
    data.backendConfig = config;
    return getInitConfig(directors);
  }).then((config) => {
    data.initConfig = config;
    data.selectConfig = getBackendSelectConfig(directors);
    return data;
  });
}

function getPassRules(urls) {
  const rules = ['req.http.Cache-Control == "no-cache"'];
  _.forEach(urls, url => rules.push(`req.url ~ "${url}"`));
  return rules.join(' || ');
}

function getHash(hashConfig) {
  const arr = [];
  _.forEach(hashConfig, (item) => {
    if (_.isString(item)) {
      arr.push(`hash_data(${item});`);
      return;
    }
    const total = item.length;
    const tmpArr = [];
    _.forEach(item, (subItem, index) => {
      const hashStr = `  hash_data(${subItem});`;
      if (index === 0) {
        tmpArr.push(`if (${subItem}) {`);
        tmpArr.push(hashStr);
      } else if (index === total - 1) {
        tmpArr.push('} else {');
        tmpArr.push(hashStr);
        tmpArr.push('}');
      } else {
        tmpArr.push(`} elsif (${subItem}) {`);
        tmpArr.push(hashStr);
      }
    });
    arr.push(...tmpArr);
  });
  return _.map(arr, item => `  ${item}`).join('\n');
}

/**
 * [getVcl description]
 * @param  {[type]} config [description]
 * @return {[type]}        [description]
 */
function getVcl(conf) {
  const config = _.extend({
    version: new Date().toISOString(),
    timeout: defaultTimeout,
    urlPassList: ['cache-control=no-cache'],
    hash: [
      'req.url',
      [
        'req.http.host',
        'server.ip',
      ],
    ],
    hisForPassTTL: 120,
  }, conf);
  /* istanbul ignore if */
  if (!config.directors || !config.name) {
    throw new Error('directors, name can not be null');
  }
  if (!config.directors.length) {
    throw new Error('directors can not be empty');
  }
  _.forEach(config.directors, (item) => {
    if (!item.timeout) {
      /* eslint no-param-reassign:0 */
      item.timeout = config.timeout;
    }
    if (item.type === 'shard') {
      throw new Error('shard director is not support');
    }
  });
  const cloneConfig = _.extend({
    stale: 3,
    varnish: '5',
    hashConfig: getHash(config.hash),
    passRules: getPassRules(config.urlPassList),
  }, config);
  return getConfig(cloneConfig.directors).then((data) => {
    _.extend(cloneConfig, data);
    return readFilePromise(path.join(__dirname, 'template/varnish.tpl'));
  }).then(tpl => _.template(tpl)(cloneConfig));
}

function getVclFromFile(file) {
  const extname = path.extname(file);
  return readFilePromise(file)
    .then((data) => {
      const json = extname === '.yml' ? yaml.safeLoad(data) : JSON.parse(data);
      return getVcl(json);
    });
}

exports.getBackendConfig = getBackendConfig;
exports.getInitConfig = getInitConfig;
exports.getBackendSelectConfig = getBackendSelectConfig;
exports.getConfig = getConfig;
exports.getVcl = getVcl;
exports.getVclFromFile = getVclFromFile;
exports.writeVclToFile = writeFilePromise;
<|endoftext|>


<commit_before>const fetch = require('node-fetch')

class FBMessenger {
  constructor ({token, notificationType = 'REGULAR'}) {
    this.token = token
    this.notificationType = notificationType
  }

  async sendTextMessage ({id, text, ...rest}) {
    const data = {
      text
    }
    return this.sendMessage({id, data, ...rest})
  }

  async sendAudioMessage ({id, url, ...rest}) {
    const data = {
      attachment: {
        type: 'audio',
        payload: {
          url
        }
      }
    }
    return this.sendMessage({id, data, ...rest})
  }

  async sendVideoMessage ({id, url, ...rest}) {
    const data = {
      attachment: {
        type: 'video',
        payload: {
          url
        }
      }
    }
    return this.sendMessage({id, data, ...rest})
  }

  async sendImageMessage ({id, url, ...rest}) {
    const data = {
      attachment: {
        type: 'image',
        payload: {
          url
        }
      }
    }
    return this.sendMessage({id, data, ...rest})
  }

  async sendFileMessage ({id, url, ...rest}) {
    const data = {
      attachment: {
        type: 'file',
        payload: {
          url
        }
      }
    }
    return this.sendMessage({id, data, ...rest})
  }

  // START TEMPLATES

  async sendQuickRepliesMessage ({id, attachment, quickReplies, ...rest}) {
    const attachmentType = typeof attachment === 'string' ? 'text' : 'attachment'
    const attachmentObject = typeof attachment === 'string' ? attachment : {
      type: 'template',
      payload: {
        template_type: 'generic',
        elements: attachment
      }
    }
    const data = {
      [attachmentType]: attachmentObject,
      quick_replies: quickReplies
    }
    return this.sendMessage({id, data, ...rest})
  }

  async sendButtonsMessage ({id, text, buttons, ...rest}) {
    const data = {
      attachment: {
        type: 'template',
        payload: {
          template_type: 'button',
          text,
          buttons
        }
      }
    }
    return this.sendMessage({id, data, ...rest})
  }

  async sendGenericMessage ({id, elements, ...rest}) {
    const data = {
      attachment: {
        type: 'template',
        payload: {
          template_type: 'generic',
          elements
        }
      }
    }
    return this.sendMessage({id, data, ...rest})
  }

  async sendListMessage ({id, elements, buttons = [], topElementStyle = 'large', ...rest}) {
    const data = {
      attachment: {
        type: 'template',
        payload: {
          template_type: 'list',
          top_element_style: topElementStyle,
          elements,
          buttons
        }
      }
    }
    return this.sendMessage({id, data, ...rest})
  }

  async sendMediaMessage ({id, elements, ...rest}) {
    const data = {
      attachment: {
        type: 'template',
        payload: {
          template_type: 'media',
          elements
        }
      }
    }
    return this.sendMessage({id, data, ...rest})
  }

  async sendOpenGraphMessage ({id, elements, ...rest}) {
    const data = {
      attachment: {
        type: 'template',
        payload: {
          template_type: 'open_graph',
          elements
        }
      }
    }
    return this.sendMessage({id, data, ...rest})
  }

  async sendReceiptMessage ({id, payload, ...rest}) {
    const data = {
      attachment: {
        type: 'template',
        payload: {
          ...payload,
          template_type: 'receipt'
        }
      }
    }
    return this.sendMessage({id, data, ...rest})
  }

  // END TEMPLATES

  async sendAction ({id, action}) {
    return this.sendMessage({id, data: action})
  }

  async sendMessage ({id, data, ...rest}) {
    const body = {
      recipient: {
        id
      }
    }

    if (typeof data === 'string') {
      body.sender_action = data
    } else {
      body.message = data
      body.notification_type = rest.notificationType || this.notificationType
    }

    return (await fetch(`https://graph.facebook.com/v2.6/me/messages?access_token=${rest.token || this.token}`,
      {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(body)
      })).json()
  }

  // GET PROFILE

  async getProfile ({id, ...rest}) {
    return (await fetch(`https://graph.facebook.com/v2.6/${id}?fields=first_name,last_name,profile_pic,locale,timezone,gender&access_token=${rest.token || this.token}`,
      {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json'
        }
      })).json()
  }

  // START THREAD SETTINGS

  async setWelcomeMessage ({pageId, message, ...rest}) {
    if (typeof message === 'string') {
      message = {
        text: message
      }
    } else {
      message = {
        attachment: {
          type: 'template',
          payload: message
        }
      }
    }
    const body = {
      setting_type: 'call_to_actions',
      thread_state: 'new_thread',
      call_to_actions: [{
        message: message
      }]
    }
    this.sendThreadSettingsMessage({pageId, body, ...rest})
  }

  async setGreetingText ({pageId, message, ...rest}) {
    const body = {
      setting_type: 'greeting',
      greeting: {
        text: message
      }
    }
    return this.sendThreadSettingsMessage({pageId, body, ...rest})
  }

  async setPersistentMenu ({pageId, menuItems, ...rest}) {
    const body = {
      setting_type: 'call_to_actions',
      thread_state: 'existing_thread',
      call_to_actions: menuItems
    }
    return this.sendThreadSettingsMessage({pageId, body, ...rest})
  }

  async setDomainWhitelist ({pageId, domains, ...rest}) {
    const body = {
      setting_type: `domain_whitelisting`,
      whitelisted_domains: domains,
      domain_action_type: `add`
    }
    return this.sendThreadSettingsMessage({pageId, body, ...rest})
  }

  async sendThreadSettingsMessage ({pageId, body, ...rest}) {
    return (await fetch(`https://graph.facebook.com/v2.6/${pageId}/thread_settings?${rest.token || this.token}`,
      {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(body)
      })).json()
  }

  // END THREAD SETTINGS
}

module.exports = FBMessenger
<commit_msg>Support messages tags<commit_after>const fetch = require('node-fetch')

class FBMessenger {
  constructor ({token, notificationType = 'REGULAR'}) {
    this.token = token
    this.notificationType = notificationType
  }

  async sendTextMessage ({id, text, ...rest}) {
    const data = {
      text
    }
    return this.sendMessage({id, data, ...rest})
  }

  async sendAudioMessage ({id, url, ...rest}) {
    const data = {
      attachment: {
        type: 'audio',
        payload: {
          url
        }
      }
    }
    return this.sendMessage({id, data, ...rest})
  }

  async sendVideoMessage ({id, url, ...rest}) {
    const data = {
      attachment: {
        type: 'video',
        payload: {
          url
        }
      }
    }
    return this.sendMessage({id, data, ...rest})
  }

  async sendImageMessage ({id, url, ...rest}) {
    const data = {
      attachment: {
        type: 'image',
        payload: {
          url
        }
      }
    }
    return this.sendMessage({id, data, ...rest})
  }

  async sendFileMessage ({id, url, ...rest}) {
    const data = {
      attachment: {
        type: 'file',
        payload: {
          url
        }
      }
    }
    return this.sendMessage({id, data, ...rest})
  }

  // START TEMPLATES

  async sendQuickRepliesMessage ({id, attachment, quickReplies, ...rest}) {
    const attachmentType = typeof attachment === 'string' ? 'text' : 'attachment'
    const attachmentObject = typeof attachment === 'string' ? attachment : {
      type: 'template',
      payload: {
        template_type: 'generic',
        elements: attachment
      }
    }
    const data = {
      [attachmentType]: attachmentObject,
      quick_replies: quickReplies
    }
    return this.sendMessage({id, data, ...rest})
  }

  async sendButtonsMessage ({id, text, buttons, ...rest}) {
    const data = {
      attachment: {
        type: 'template',
        payload: {
          template_type: 'button',
          text,
          buttons
        }
      }
    }
    return this.sendMessage({id, data, ...rest})
  }

  async sendGenericMessage ({id, elements, ...rest}) {
    const data = {
      attachment: {
        type: 'template',
        payload: {
          template_type: 'generic',
          elements
        }
      }
    }
    return this.sendMessage({id, data, ...rest})
  }

  async sendListMessage ({id, elements, buttons = [], topElementStyle = 'large', ...rest}) {
    const data = {
      attachment: {
        type: 'template',
        payload: {
          template_type: 'list',
          top_element_style: topElementStyle,
          elements,
          buttons
        }
      }
    }
    return this.sendMessage({id, data, ...rest})
  }

  async sendMediaMessage ({id, elements, ...rest}) {
    const data = {
      attachment: {
        type: 'template',
        payload: {
          template_type: 'media',
          elements
        }
      }
    }
    return this.sendMessage({id, data, ...rest})
  }

  async sendOpenGraphMessage ({id, elements, ...rest}) {
    const data = {
      attachment: {
        type: 'template',
        payload: {
          template_type: 'open_graph',
          elements
        }
      }
    }
    return this.sendMessage({id, data, ...rest})
  }

  async sendReceiptMessage ({id, payload, ...rest}) {
    const data = {
      attachment: {
        type: 'template',
        payload: {
          ...payload,
          template_type: 'receipt'
        }
      }
    }
    return this.sendMessage({id, data, ...rest})
  }

  // END TEMPLATES

  async sendAction ({id, action}) {
    return this.sendMessage({id, data: action})
  }

  async sendMessage ({id, data, ...rest}) {
    const body = {
      recipient: {
        id
      }
    }

    if (typeof data === 'string') {
      body.sender_action = data
    } else {
      body.message = data

      const notificationType = rest.notificationType || this.notificationType
      if (notificationType !== 'REGULAR') { // Only include it if not default
        body.notification_type = notificationType
      }
    }

    if (rest.tag) { // https://developers.facebook.com/docs/messenger-platform/send-messages/message-tags
      body.messaging_type = 'MESSAGE_TAG'
      body.tag = rest.tag
    }

    return (await fetch(`https://graph.facebook.com/v2.6/me/messages?access_token=${rest.token || this.token}`,
      {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(body)
      })).json()
  }

  // GET PROFILE

  async getProfile ({id, ...rest}) {
    return (await fetch(`https://graph.facebook.com/v2.6/${id}?fields=first_name,last_name,profile_pic,locale,timezone,gender&access_token=${rest.token || this.token}`,
      {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json'
        }
      })).json()
  }

  // START THREAD SETTINGS

  async setWelcomeMessage ({pageId, message, ...rest}) {
    if (typeof message === 'string') {
      message = {
        text: message
      }
    } else {
      message = {
        attachment: {
          type: 'template',
          payload: message
        }
      }
    }
    const body = {
      setting_type: 'call_to_actions',
      thread_state: 'new_thread',
      call_to_actions: [{
        message: message
      }]
    }
    this.sendThreadSettingsMessage({pageId, body, ...rest})
  }

  async setGreetingText ({pageId, message, ...rest}) {
    const body = {
      setting_type: 'greeting',
      greeting: {
        text: message
      }
    }
    return this.sendThreadSettingsMessage({pageId, body, ...rest})
  }

  async setPersistentMenu ({pageId, menuItems, ...rest}) {
    const body = {
      setting_type: 'call_to_actions',
      thread_state: 'existing_thread',
      call_to_actions: menuItems
    }
    return this.sendThreadSettingsMessage({pageId, body, ...rest})
  }

  async setDomainWhitelist ({pageId, domains, ...rest}) {
    const body = {
      setting_type: `domain_whitelisting`,
      whitelisted_domains: domains,
      domain_action_type: `add`
    }
    return this.sendThreadSettingsMessage({pageId, body, ...rest})
  }

  async sendThreadSettingsMessage ({pageId, body, ...rest}) {
    return (await fetch(`https://graph.facebook.com/v2.6/${pageId}/thread_settings?${rest.token || this.token}`,
      {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(body)
      })).json()
  }

  // END THREAD SETTINGS
}

module.exports = FBMessenger
<|endoftext|>


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

var exec = function(cmd, args, cb) {
	var stdout = '';
	var stderr = '';
	cmd = spawn(cmd, args);
	cmd.stdout.on('data', function(data) {
		stdout = stdout + data;
	});
	cmd.stderr.on('data', function(data) {
		stderr = stderr + data;
	});
	cmd.on('close', function(code) {
		cb(code, stdout, stderr);
	});
};

var office = {
	spreadsheets: ['xls', 'xlsx', 'ods'],
	documents: ['doc', 'docx', 'odt'],
	xlsParse: function(file, callback) {
		exec('xlhtml', ['-xml', file], function(code, stdout, stderr) {
			if (stderr) { console.error(stderr); }
			if (code) {
				callback(code);
			} else {
				callback(null, xmlParser.toJson(stdout, {object: true}).excel_workbook);
			}
		});
	},
	spreadsheetParse: function(filename, options, cb) {
		var self = this;
		if (options.ext !== 'xls') {
			var tempname = temp.path({prefix: 'node-office-'});
			exec('unoconv', ['-o', tempname, '--format=xls', filename], function(error, stdout, stderr) {
				if (stderr) { console.error(stderr); }
				if (!error) {
					var tempfile = path.join(tempname, path.basename(filename, path.extname(filename))+'.xls');
					self.xlsParse(tempfile, function(err, data) {
						fs.unlink(tempfile, function(e) {
							if (e) { console.error(e); }
							fs.rmdir(tempname, function(e) {
								if (e) { console.error(e); }
								cb(err, data);
							});
						});
					});
				} else { cb(error); }
			});
		} else { self.xlsParse(filename, cb); }
	},
	documentParse: function(filename, options, cb) {
		var self = this;
		options.format = options.format || 'html';
		if (options.img) {
			if (!options.path) {
				options.path = temp.path({prefix: 'node-office-'});
			}
		}
		if (options.path) {
			exec('unoconv', ['--outputpath='+options.path, '--format='+options.format, filename], function(error, stdout, stderr) {
				if (stderr) { console.error(stderr); }
				if (!error) {
					cb(null, path.join(options.path, path.basename(filename, path.extname(filename))+'.html'));
				} else { cb(error); }
			});
		} else {
			exec('unoconv', ['--stdout', '--format='+options.format, filename], function(error, stdout, stderr) {
				if (stderr) { console.error(stderr); }
				if (!error) {
					cb(null, stdout);
				} else { cb(error); }
			});
		}
	},
	getType: function(filename, cb) {
		// проверка по расширению
		var self = this;
		fs.exists(filename, function(exists) {
			if (!exists) {
				cb(new Error('file does not exist'));
			} else {
				var ext = path.extname(filename).toLowerCase().slice(1);
				if (self.spreadsheets.indexOf(ext) !== -1) {
					cb(null, 'spreadsheet', ext);
				} else if (self.documents.indexOf(ext) !== -1) {
					cb(null, 'document');
				} else {
					// TODO проверка по mime-type
					cb(new Error('wrong file format'));
				}
			}
		});
	},
	parse: function(filename, options, cb) {
		var self = this;
		if (!cb && typeof(options) === 'function') { cb = options; options = { }; }
		self.getType(filename, function(err, type, ext) {
			options.ext = ext;
			if (!err) {
				if (type === 'spreadsheet') {
					self.spreadsheetParse(filename, options, function(err, data) {
						cb(err, data);
					});
				} else if (type === 'document') {
					self.documentParse(filename, options, function(err, data) {
						cb(err, data);
					});
				} else {
					cb(new Error('wrong file format'));
				}
			} else { cb(err); }
		});
	}
};

module.exports = office;
<commit_msg>Update index.js<commit_after>var fs = require('fs');
var path = require('path');
var xmlParser = require('xml2json');
var temp = require('temp');
var spawn = require('child_process').spawn;

var exec = function(cmd, args, cb) {
	var stdout = '';
	var stderr = '';
	cmd = spawn(cmd, args);
	cmd.stdout.on('data', function(data) {
		stdout = stdout + data;
	});
	cmd.stderr.on('data', function(data) {
		stderr = stderr + data;
	});
	cmd.on('close', function(code) {
		cb(code, stdout, stderr);
	});
};

var office = {
	spreadsheets: ['xls', 'xlsx', 'ods'],
	documents: ['doc', 'docx', 'odt'],
	xlsParse: function(file, callback) {
		exec('xlhtml', ['-xml', file], function(code, stdout, stderr) {
			if (stderr) { console.error(stderr); }
			if (code) {
				callback(code);
			} else {
				callback(null, xmlParser.toJson(stdout, {object: true, sanitize:false}).excel_workbook);
			}
		});
	},
	spreadsheetParse: function(filename, options, cb) {
		var self = this;
		if (options.ext !== 'xls') {
			var tempname = temp.path({prefix: 'node-office-'});
			exec('unoconv', ['-o', tempname, '--format=xls', filename], function(error, stdout, stderr) {
				if (stderr) { console.error(stderr); }
				if (!error) {
					var tempfile = path.join(tempname, path.basename(filename, path.extname(filename))+'.xls');
					self.xlsParse(tempfile, function(err, data) {
						fs.unlink(tempfile, function(e) {
							if (e) { console.error(e); }
							fs.rmdir(tempname, function(e) {
								if (e) { console.error(e); }
								cb(err, data);
							});
						});
					});
				} else { cb(error); }
			});
		} else { self.xlsParse(filename, cb); }
	},
	documentParse: function(filename, options, cb) {
		var self = this;
		options.format = options.format || 'html';
		if (options.img) {
			if (!options.path) {
				options.path = temp.path({prefix: 'node-office-'});
			}
		}
		if (options.path) {
			exec('unoconv', ['--outputpath='+options.path, '--format='+options.format, filename], function(error, stdout, stderr) {
				if (stderr) { console.error(stderr); }
				if (!error) {
					cb(null, path.join(options.path, path.basename(filename, path.extname(filename))+'.html'));
				} else { cb(error); }
			});
		} else {
			exec('unoconv', ['--stdout', '--format='+options.format, filename], function(error, stdout, stderr) {
				if (stderr) { console.error(stderr); }
				if (!error) {
					cb(null, stdout);
				} else { cb(error); }
			});
		}
	},
	getType: function(filename, cb) {
		// проверка по расширению
		var self = this;
		fs.exists(filename, function(exists) {
			if (!exists) {
				cb(new Error('file does not exist'));
			} else {
				var ext = path.extname(filename).toLowerCase().slice(1);
				if (self.spreadsheets.indexOf(ext) !== -1) {
					cb(null, 'spreadsheet', ext);
				} else if (self.documents.indexOf(ext) !== -1) {
					cb(null, 'document');
				} else {
					// TODO проверка по mime-type
					cb(new Error('wrong file format'));
				}
			}
		});
	},
	parse: function(filename, options, cb) {
		var self = this;
		if (!cb && typeof(options) === 'function') { cb = options; options = { }; }
		self.getType(filename, function(err, type, ext) {
			options.ext = ext;
			if (!err) {
				if (type === 'spreadsheet') {
					self.spreadsheetParse(filename, options, function(err, data) {
						cb(err, data);
					});
				} else if (type === 'document') {
					self.documentParse(filename, options, function(err, data) {
						cb(err, data);
					});
				} else {
					cb(new Error('wrong file format'));
				}
			} else { cb(err); }
		});
	}
};

module.exports = office;
<|endoftext|>


<commit_before>module.exports = function removeRoute(app, path) {
    var found, route, stack, idx;

    found = findRoute(app, path);
    route = found.route;
    stack = found.stack;

    if (!route) return false;

    idx = stack.indexOf(route);
    stack.splice(idx, 1);
    return true;
};

module.exports.findRoute = findRoute;

function findRoute(app, path) {
    var route, stack;

    stack = app._router.stack;

    function _findRoute(path) {
        stack.forEach(function(layer) {
            if (!layer) return;
            if (layer && !layer.match(path)) return;
            if (['query', 'expressInit'].indexOf(layer.name) != -1) return;
            if (layer.name == 'router') {
                stack = layer.handle.stack;
                _findRoute(trimPrefix(path, layer.path));
            } else {
                route = layer;
            }
        });
    }

    _findRoute(path, stack);

    if (!route) return null;
    return {route: route, stack: stack};
}

function trimPrefix(path, prefix) {
    // This assumes prefix is already at the start of path.
    return path.substr(prefix.length);
}
<commit_msg>Fixing non-existing routes issue<commit_after>module.exports = function removeRoute(app, path) {
    var found, route, stack, idx;

    found = findRoute(app, path);

    if (!found) return false;

    route = found.route;
    stack = found.stack;

    if (!route) return false;

    idx = stack.indexOf(route);
    stack.splice(idx, 1);
    return true;
};

module.exports.findRoute = findRoute;

function findRoute(app, path) {
    var route, stack;

    stack = app._router.stack;

    function _findRoute(path) {
        stack.forEach(function(layer) {
            if (!layer) return;
            if (layer && !layer.match(path)) return;
            if (['query', 'expressInit'].indexOf(layer.name) != -1) return;
            if (layer.name == 'router') {
                stack = layer.handle.stack;
                _findRoute(trimPrefix(path, layer.path));
            } else {
                route = layer;
            }
        });
    }

    _findRoute(path, stack);

    if (!route) return null;
    return {route: route, stack: stack};
}

function trimPrefix(path, prefix) {
    // This assumes prefix is already at the start of path.
    return path.substr(prefix.length);
}
<|endoftext|>


<commit_before>

exports.decode = function (codec) {
  var buffer = null, offset = 0, ended = null

  function parse (cb) {
    var val, bytes = 0
    if(!buffer || offset >= buffer.length)
      return false

    val = codec.decode(buffer, offset)
    bytes = codec.decode.bytes

    if(bytes !== 0) {
      offset += bytes
      if(offset === buffer.length) {
        buffer = null
        offset = 0
      }
    }
    else {
      if(ended) return cb(new Error('Unexpected End of Stream'))
      return false
    }
    cb(null, val)
    return true
  }

  return function (read) {
    return function (abort, cb) {
      if(abort) return read(abort, cb)
      if(parse(cb)) return
      if(ended) return cb(ended)

      read(null, function next (end, data) {
        if(end) {
          ended = end
          return buffer !== null ? parse(cb) : cb(ended)
        }
        if(!buffer) {
          buffer = data
          offset = 0
        }
        else {
          buffer = Buffer.concat([
            offset > 0 ? buffer.slice(offset) : buffer,
            data
          ])
          offset = 0
        }

        if(!parse(cb)) read(null, next)
      })

    }
  }
}

exports.encode = function (codec) {
  return function (read) {
    return function (abort, cb) {
      read(abort, function (end, data) {
        if(end) cb(end)
        else    cb(null, codec.encode(data))
      })
    }
  }
}
<commit_msg>also wrap duplex streams<commit_after>
exports.decode = function (codec) {
  var buffer = null, offset = 0, ended = null

  function parse (cb) {
    var val, bytes = 0
    if(!buffer || offset >= buffer.length)
      return false

    val = codec.decode(buffer, offset)
    bytes = codec.decode.bytes

    if(bytes !== 0) {
      offset += bytes
      if(offset === buffer.length) {
        buffer = null
        offset = 0
      }
    }
    else {
      if(ended) return cb(new Error('Unexpected End of Stream'))
      return false
    }
    cb(null, val)
    return true
  }

  return function (read) {
    return function (abort, cb) {
      if(abort) return read(abort, cb)
      if(parse(cb)) return
      if(ended) return cb(ended)

      read(null, function next (end, data) {
        if(end) {
          ended = end
          return buffer !== null ? parse(cb) : cb(ended)
        }
        if(!buffer) {
          buffer = data
          offset = 0
        }
        else {
          buffer = Buffer.concat([
            offset > 0 ? buffer.slice(offset) : buffer,
            data
          ])
          offset = 0
        }

        if(!parse(cb)) read(null, next)
      })

    }
  }
}

exports.encode = function (codec) {
  return function (read) {
    return function (abort, cb) {
      read(abort, function (end, data) {
        if(end) cb(end)
        else    cb(null, codec.encode(data))
      })
    }
  }
}

exports.duplex = function (stream, codec) {
  return {
    source: pull(stream.source, exports.encode(codec)),
    sink: pull(exports.decode(codec), stream.sink))
  }
}

<|endoftext|>


<commit_before>/* global Blob File */

/*
 * Module requirements.
 */

var isArray = require('isarray');

var toString = Object.prototype.toString;
var withNativeBlob = typeof global.Blob === 'function' || toString.call(global.Blob) === '[object BlobConstructor]';
var withNativeFile = typeof global.File === 'function' || toString.call(global.File) === '[object FileConstructor]';

/**
 * Module exports.
 */

module.exports = hasBinary;

/**
 * Checks for binary data.
 *
 * Supports Buffer, ArrayBuffer, Blob and File.
 *
 * @param {Object} anything
 * @api public
 */

function hasBinary (obj) {
  if (!obj || typeof obj !== 'object') {
    return false;
  }

  if (isArray(obj)) {
    for (var i = 0, l = obj.length; i < l; i++) {
      if (hasBinary(obj[i])) {
        return true;
      }
    }
    return false;
  }

  if ((typeof global.Buffer === 'function' && global.Buffer.isBuffer && global.Buffer.isBuffer(obj)) ||
     (typeof global.ArrayBuffer === 'function' && obj instanceof ArrayBuffer) ||
     (withNativeBlob && obj instanceof Blob) ||
     (withNativeFile && obj instanceof File)
    ) {
    return true;
  }

  // see: https://github.com/Automattic/has-binary/pull/4
  if (obj.toJSON && typeof obj.toJSON === 'function' && arguments.length === 1) {
    return hasBinary(obj.toJSON(), true);
  }

  for (var key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key) && hasBinary(obj[key])) {
      return true;
    }
  }

  return false;
}
<commit_msg>fix: avoid use of global (#4)<commit_after>/* global Blob File */

/*
 * Module requirements.
 */

var isArray = require('isarray');

var toString = Object.prototype.toString;
var withNativeBlob = typeof Blob === 'function' ||
                        typeof Blob !== 'undefined' && toString.call(Blob) === '[object BlobConstructor]';
var withNativeFile = typeof File === 'function' ||
                        typeof File !== 'undefined' && toString.call(File) === '[object FileConstructor]';

/**
 * Module exports.
 */

module.exports = hasBinary;

/**
 * Checks for binary data.
 *
 * Supports Buffer, ArrayBuffer, Blob and File.
 *
 * @param {Object} anything
 * @api public
 */

function hasBinary (obj) {
  if (!obj || typeof obj !== 'object') {
    return false;
  }

  if (isArray(obj)) {
    for (var i = 0, l = obj.length; i < l; i++) {
      if (hasBinary(obj[i])) {
        return true;
      }
    }
    return false;
  }

  if ((typeof Buffer === 'function' && Buffer.isBuffer && Buffer.isBuffer(obj)) ||
    (typeof ArrayBuffer === 'function' && obj instanceof ArrayBuffer) ||
    (withNativeBlob && obj instanceof Blob) ||
    (withNativeFile && obj instanceof File)
  ) {
    return true;
  }

  // see: https://github.com/Automattic/has-binary/pull/4
  if (obj.toJSON && typeof obj.toJSON === 'function' && arguments.length === 1) {
    return hasBinary(obj.toJSON(), true);
  }

  for (var key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key) && hasBinary(obj[key])) {
      return true;
    }
  }

  return false;
}
<|endoftext|>


<commit_before>'use strict';

var express = require('express');
var bodyParser = require('body-parser');
var gizoogle = require('gizoogle');
var morgan = require('morgan');
var config = require('./config');

var app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(morgan('dev'));

app.all('/translate', function(req, res, next) {
    var text = req.body.text || req.query.text;
    if (!text) {
        res.json({ text: 'You sent an empty text' });
    }

    gizoogle.string(text, function(error, translated) {
        if (error) return next(error);

        res.json({ text: '*' + translated + '*' });
    });
});

app.listen(config.PORT, config.HOST, function() {
    console.info('App started on http://' + config.HOST + ':' + config.PORT);
});
<commit_msg>Added response_type back<commit_after>'use strict';

var express = require('express');
var bodyParser = require('body-parser');
var gizoogle = require('gizoogle');
var morgan = require('morgan');
var config = require('./config');

var app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(morgan('dev'));

app.all('/translate', function(req, res, next) {
    var text = req.body.text || req.query.text;
    if (!text) {
        res.json({ text: 'You sent an empty text' });
    }

    gizoogle.string(text, function(error, translated) {
        if (error) return next(error);

        res.json({ text: translated, response_type: 'in_channel' });
    });
});

app.listen(config.PORT, config.HOST, function() {
    console.info('App started on http://' + config.HOST + ':' + config.PORT);
});
<|endoftext|>


<commit_before>'use strict';

var _ = require('lodash');
var util = require('util');
var qs = require('querystring');
var request = require('request');
var through = require('through');
var JSONStream = require('JSONStream');
var Readable = require('stream').Readable;

function Stream(options) {
  if (!(this instanceof Stream)) {
    return new Stream(options);
  }

  Readable.call(this, { highWaterMark: 1, objectMode : true });

  this._request = null;
  this._symbols = [];
  this._options = _.defaults({}, options, {
    frequency: 60000,
    endpoint: 'https://query.yahooapis.com/v1/public/yql',
  });
};

util.inherits(Stream, Readable);

Stream.prototype.watch = function(symbol) {
  this._symbols.push(symbol.toUpperCase());
  this._schedule({ immediate: true });
};

Stream.prototype._url = function() {
  var symbols = this._symbols.map(function(s) {
    return JSON.stringify(s);
  });
  var yql = util.format(
    'select * from yahoo.finance.quotes ' +
    'where symbol in (%s)', symbols);
  var query = qs.stringify({
    q: yql,
    format: 'json',
    env: 'store://datatables.org/alltableswithkeys',
    callback: '',
  });
  return util.format('%s?%s', this._options.endpoint, query);
};

Stream.prototype._standardize = function(quote) {
  var standardized = { _quote: quote };
  return _.reduce(quote, function(obj, value, key) {
    if (/^[+-]?[\d\.]+$/.test(value)) { value = parseFloat(value); }
    else if (/^[+-]?[\d\.]+%$/.test(value)) { value = parseFloat(value) / 100.0; }
    obj[_.camelCase(key)] = value;
    return obj;
  }, standardized);
};

Stream.prototype._canRun = function() {
  return this._request === null && // only allow one request
    this._symbols.length !== 0; // only run when symbols are present
};

Stream.prototype._run = function() {
  if (!this._canRun()) {
    throw new Error('Cannot run when _canRun returns false.');
  }

  var self = this;
  var emitError = this._error.bind(this);
  var endpoint = this._options.endpoint;
  var stream = this._request = request({
    url: this._url(),
  })
  .on('error', emitError)
  .pipe(JSONStream.parse())
  .on('error', emitError);

  stream.on('data', function(data) {
    _.flatten([data.query.results.quote]).forEach(function(quote) {
      if (!self.push(self._standardize(quote))) {
        self._running = false;
      }
    });
  });

  stream.on('end', function() {
    self._request = null;
    self._schedule();
  });
};

Stream.prototype._schedule = function(options) {
  var opts = _.defaults({}, options);

  // if immediate flag is given or was previously given, we ensure that it
  // sticks until the next successful run occurs. we do this by storing an
  // instance variable to track it across scheduling requests. either the
  // option flag or the instance variable being set indicates that both should
  // be set.
  if (this._immediate || opts.immediate) {
    this._immediate = opts.immediate = true;
  }

  // remove any existing timer
  clearTimeout(this._timer);

  var self = this;
  var timeout = opts.immediate ? 0 : this._options.frequency;
  var run = function() {
    if (self._canRun()) {
      self._run();
      self._immediate = false; // run started, clear immediate flag
    }
  };

  // schedule the timer only if we're actually running
  if (this._running) {
    this._timer = setTimeout(run, timeout);
  }
};

Stream.prototype._error = function(e) {
  this.emit('error', e);
  this.close();
};

Stream.prototype._read = function(size) {
  // mark this as running & schedule a timer to actually run. if this wasn't
  // already running, then we schedule the run for immediate execution.
  var wasRunning = this._running;
  this._running = true;
  this._schedule({ immediate: !wasRunning });
};

Stream.prototype.close = function() {
  var self = this;
  var close = function() {
    self._running = false;
    self._schedule();
    self.push(null);
  };

  if (this._request) { this._request.on('end', close); }
  else { close(); }
};

module.exports = Stream;
<commit_msg>A few style fixes.<commit_after>'use strict';

var _ = require('lodash');
var util = require('util');
var qs = require('querystring');
var request = require('request');
var JSONStream = require('JSONStream');
var Readable = require('stream').Readable;

function Stream(options) {
  if (!(this instanceof Stream)) {
    return new Stream(options);
  }

  Readable.call(this, { highWaterMark: 1, objectMode : true });

  this._request = null;
  this._symbols = [];
  this._options = _.defaults({}, options, {
    frequency: 60000,
    endpoint: 'https://query.yahooapis.com/v1/public/yql',
  });
}

util.inherits(Stream, Readable);

Stream.prototype.watch = function(symbol) {
  this._symbols.push(symbol.toUpperCase());
  this._schedule({ immediate: true });
};

Stream.prototype._url = function() {
  var symbols = this._symbols.map(function(s) {
    return JSON.stringify(s);
  });
  var yql = util.format(
    'select * from yahoo.finance.quotes ' +
    'where symbol in (%s)', symbols);
  var query = qs.stringify({
    q: yql,
    format: 'json',
    env: 'store://datatables.org/alltableswithkeys',
    callback: '',
  });
  return util.format('%s?%s', this._options.endpoint, query);
};

Stream.prototype._standardize = function(quote) {
  var standardized = { _quote: quote };
  return _.reduce(quote, function(obj, value, key) {
    if (/^[+-]?[\d\.]+$/.test(value)) { value = parseFloat(value); }
    else if (/^[+-]?[\d\.]+%$/.test(value)) { value = parseFloat(value) / 100.0; }
    obj[_.camelCase(key)] = value;
    return obj;
  }, standardized);
};

Stream.prototype._canRun = function() {
  return this._request === null && // only allow one request
    this._symbols.length !== 0; // only run when symbols are present
};

Stream.prototype._run = function() {
  if (!this._canRun()) {
    throw new Error('Cannot run when _canRun returns false.');
  }

  var self = this;
  var emitError = this._error.bind(this);
  var stream = this._request = request({
    url: this._url(),
  })
  .on('error', emitError)
  .pipe(JSONStream.parse())
  .on('error', emitError);

  stream.on('data', function(data) {
    _.flatten([data.query.results.quote]).forEach(function(quote) {
      if (!self.push(self._standardize(quote))) {
        self._running = false;
      }
    });
  });

  stream.on('end', function() {
    self._request = null;
    self._schedule();
  });
};

Stream.prototype._schedule = function(options) {
  var opts = _.defaults({}, options);

  // if immediate flag is given or was previously given, we ensure that it
  // sticks until the next successful run occurs. we do this by storing an
  // instance variable to track it across scheduling requests. either the
  // option flag or the instance variable being set indicates that both should
  // be set.
  if (this._immediate || opts.immediate) {
    this._immediate = opts.immediate = true;
  }

  // remove any existing timer
  clearTimeout(this._timer);

  var self = this;
  var timeout = opts.immediate ? 0 : this._options.frequency;
  var run = function() {
    if (self._canRun()) {
      self._run();
      self._immediate = false; // run started, clear immediate flag
    }
  };

  // schedule the timer only if we're actually running
  if (this._running) {
    this._timer = setTimeout(run, timeout);
  }
};

Stream.prototype._error = function(e) {
  this.emit('error', e);
  this.close();
};

Stream.prototype._read = function(/*size*/) {
  // mark this as running & schedule a timer to actually run. if this wasn't
  // already running, then we schedule the run for immediate execution.
  var wasRunning = this._running;
  this._running = true;
  this._schedule({ immediate: !wasRunning });
};

Stream.prototype.close = function() {
  var self = this;
  var close = function() {
    self._running = false;
    self._schedule();
    self.push(null);
  };

  if (this._request) { this._request.on('end', close); }
  else { close(); }
};

module.exports = Stream;
<|endoftext|>