<commit_before>'use strict';
var uuid, Service, Characteristic, StreamController;

var crypto = require('crypto');
var fs = require('fs');
var ip = require('ip');
var spawn = require('child_process').spawn;
var drive = require('./drive').drive;

module.exports = {
  FFMPEG: FFMPEG
};

function FFMPEG(hap, cameraConfig, log, videoProcessor) {
  uuid = hap.uuid;
  Service = hap.Service;
  Characteristic = hap.Characteristic;
  StreamController = hap.StreamController;
  this.log = log;

  var ffmpegOpt = cameraConfig.videoConfig;
  this.name = cameraConfig.name;
  this.vcodec = ffmpegOpt.vcodec;
  this.videoProcessor = videoProcessor || 'ffmpeg';
  this.audio = ffmpegOpt.audio;
  this.acodec = ffmpegOpt.acodec;
  this.packetsize = ffmpegOpt.packetSize
  this.fps = ffmpegOpt.maxFPS || 10;
  this.maxBitrate = ffmpegOpt.maxBitrate || 300;
  this.debug = ffmpegOpt.debug;

  if (!ffmpegOpt.source) {
    throw new Error("Missing source for camera.");
  }

  this.ffmpegSource = ffmpegOpt.source;
  this.ffmpegImageSource = ffmpegOpt.stillImageSource;

  this.services = [];
  this.streamControllers = [];

  this.pendingSessions = {};
  this.ongoingSessions = {};

  this.uploader = cameraConfig.uploader || false;
  if ( this.uploader )
    { this.drive = new drive(); }

  var numberOfStreams = ffmpegOpt.maxStreams || 2;
  var videoResolutions = [];

  this.maxWidth = ffmpegOpt.maxWidth || 1280;
  this.maxHeight = ffmpegOpt.maxHeight || 720;
  var maxFPS = (this.fps > 30) ? 30 : this.fps;

  if (this.maxWidth >= 320) {
    if (this.maxHeight >= 240) {
      videoResolutions.push([320, 240, maxFPS]);
      if (maxFPS > 15) {
        videoResolutions.push([320, 240, 15]);
      }
    }

    if (this.maxHeight >= 180) {
      videoResolutions.push([320, 180, maxFPS]);
      if (maxFPS > 15) {
        videoResolutions.push([320, 180, 15]);
      }
    }
  }

  if (this.maxWidth >= 480) {
    if (this.maxHeight >= 360) {
      videoResolutions.push([480, 360, maxFPS]);
    }

    if (this.maxHeight >= 270) {
      videoResolutions.push([480, 270, maxFPS]);
    }
  }

  if (this.maxWidth >= 640) {
    if (this.maxHeight >= 480) {
      videoResolutions.push([640, 480, maxFPS]);
    }

    if (this.maxHeight >= 360) {
      videoResolutions.push([640, 360, maxFPS]);
    }
  }

  if (this.maxWidth >= 1280) {
    if (this.maxHeight >= 960) {
      videoResolutions.push([1280, 960, maxFPS]);
    }

    if (this.maxHeight >= 720) {
      videoResolutions.push([1280, 720, maxFPS]);
    }
  }

  if (this.maxWidth >= 1920) {
    if (this.maxHeight >= 1080) {
      videoResolutions.push([1920, 1080, maxFPS]);
    }
  }

  let options = {
    proxy: false, // Requires RTP/RTCP MUX Proxy
    srtp: true, // Supports SRTP AES_CM_128_HMAC_SHA1_80 encryption
    video: {
      resolutions: videoResolutions,
      codec: {
        profiles: [0, 1, 2], // Enum, please refer StreamController.VideoCodecParamProfileIDTypes
        levels: [0, 1, 2] // Enum, please refer StreamController.VideoCodecParamLevelTypes
      }
    },
    audio: {
      codecs: [
        {
          type: "OPUS", // Audio Codec
          samplerate: 24 // 8, 16, 24 KHz
        },
        {
          type: "AAC-eld",
          samplerate: 16
        }
      ]
    }
  }

  this.createCameraControlService();
  this._createStreamControllers(numberOfStreams, options);
}

FFMPEG.prototype.handleCloseConnection = function(connectionID) {
  this.streamControllers.forEach(function(controller) {
    controller.handleCloseConnection(connectionID);
  });
}

FFMPEG.prototype.handleSnapshotRequest = function(request, callback) {
  let resolution = request.width + 'x' + request.height;
  var imageSource = this.ffmpegImageSource !== undefined ? this.ffmpegImageSource : this.ffmpegSource;
  let ffmpeg = spawn(this.videoProcessor, (imageSource + ' -t 1 -s '+ resolution + ' -f image2 -').split(' '), {env: process.env});
  var imageBuffer = Buffer(0);
  this.log("Snapshot from " + this.name + " at " + resolution);
  if(this.debug) console.log('ffmpeg '+imageSource + ' -t 1 -s '+ resolution + ' -f image2 -');
  ffmpeg.stdout.on('data', function(data) {
    imageBuffer = Buffer.concat([imageBuffer, data]);
  });
  ffmpeg.on('close', function(code) {
    if ( this.uploader )
      { this.drive.storePicture(this.name,imageBuffer); }
    callback(undefined, imageBuffer);
  }.bind(this));
}

FFMPEG.prototype.prepareStream = function(request, callback) {
  var sessionInfo = {};

  let sessionID = request["sessionID"];
  let targetAddress = request["targetAddress"];

  sessionInfo["address"] = targetAddress;

  var response = {};

  let videoInfo = request["video"];
  if (videoInfo) {
    let targetPort = videoInfo["port"];
    let srtp_key = videoInfo["srtp_key"];
    let srtp_salt = videoInfo["srtp_salt"];

    // SSRC is a 32 bit integer that is unique per stream
    let ssrcSource = crypto.randomBytes(4);
    ssrcSource[0] = 0;
    let ssrc = ssrcSource.readInt32BE(0, true);

    let videoResp = {
      port: targetPort,
      ssrc: ssrc,
      srtp_key: srtp_key,
      srtp_salt: srtp_salt
    };

    response["video"] = videoResp;

    sessionInfo["video_port"] = targetPort;
    sessionInfo["video_srtp"] = Buffer.concat([srtp_key, srtp_salt]);
    sessionInfo["video_ssrc"] = ssrc;
  }

  let audioInfo = request["audio"];
  if (audioInfo) {
    let targetPort = audioInfo["port"];
    let srtp_key = audioInfo["srtp_key"];
    let srtp_salt = audioInfo["srtp_salt"];

    // SSRC is a 32 bit integer that is unique per stream
    let ssrcSource = crypto.randomBytes(4);
    ssrcSource[0] = 0;
    let ssrc = ssrcSource.readInt32BE(0, true);

    let audioResp = {
      port: targetPort,
      ssrc: ssrc,
      srtp_key: srtp_key,
      srtp_salt: srtp_salt
    };

    response["audio"] = audioResp;

    sessionInfo["audio_port"] = targetPort;
    sessionInfo["audio_srtp"] = Buffer.concat([srtp_key, srtp_salt]);
    sessionInfo["audio_ssrc"] = ssrc;
  }

  let currentAddress = ip.address();
  var addressResp = {
    address: currentAddress
  };

  if (ip.isV4Format(currentAddress)) {
    addressResp["type"] = "v4";
  } else {
    addressResp["type"] = "v6";
  }

  response["address"] = addressResp;
  this.pendingSessions[uuid.unparse(sessionID)] = sessionInfo;

  callback(response);
}

FFMPEG.prototype.handleStreamRequest = function(request) {
  var sessionID = request["sessionID"];
  var requestType = request["type"];
  if (sessionID) {
    let sessionIdentifier = uuid.unparse(sessionID);

    if (requestType == "start") {
      var sessionInfo = this.pendingSessions[sessionIdentifier];
      if (sessionInfo) {
        var width = 1280;
        var height = 720;
        var fps = this.fps || 30;
        var vbitrate = this.maxBitrate;
        var abitrate = 32;
        var asamplerate = 16;
        var vcodec = this.vcodec || 'libx264';
        var acodec = this.acodec || 'libfdk_aac';
        var packetsize = this.packetsize || 1316; // 188 376

        let videoInfo = request["video"];
        if (videoInfo) {
          width = videoInfo["width"];
          height = videoInfo["height"];

          let expectedFPS = videoInfo["fps"];
          if (expectedFPS < fps) {
            fps = expectedFPS;
          }
          if(videoInfo["max_bit_rate"] < vbitrate) {
            vbitrate = videoInfo["max_bit_rate"];
          }
        }

        let audioInfo = request["audio"];
        if (audioInfo) {
          abitrate = audioInfo["max_bit_rate"];
          asamplerate = audioInfo["sample_rate"];
        }

        let targetAddress = sessionInfo["address"];
        let targetVideoPort = sessionInfo["video_port"];
        let videoKey = sessionInfo["video_srtp"];
        let videoSsrc = sessionInfo["video_ssrc"];
        let targetAudioPort = sessionInfo["audio_port"];
        let audioKey = sessionInfo["audio_srtp"];
        let audioSsrc = sessionInfo["audio_ssrc"];

        let ffmpegCommand = this.ffmpegSource + ' -map 0:0' +
          ' -vcodec ' + vcodec +
          ' -pix_fmt yuv420p' +
          ' -r ' + fps +
          ' -f rawvideo -tune zerolatency' +
          ' -vf scale=' + width + ':' + height +
          ' -b:v ' + vbitrate + 'k' +
          ' -bufsize ' + vbitrate + 'k' +
          ' -payload_type 99' +
          ' -ssrc ' + videoSsrc +
          ' -f rtp' +
          ' -srtp_out_suite AES_CM_128_HMAC_SHA1_80' +
          ' -srtp_out_params ' + videoKey.toString('base64') +
          ' srtp://' + targetAddress + ':' + targetVideoPort +
          '?rtcpport=' + targetVideoPort +
          '&localrtcpport=' + targetVideoPort +
          '&pkt_size=' + packetsize;

        if(this.audio){
          ffmpegCommand+= ' -map 0:1' +
            ' -acodec ' + acodec +
            ' -profile:a aac_eld' +
            ' -flags +global_header' +
            ' -f null' +
            ' -ar ' + asamplerate + 'k' +
            ' -b:a ' + abitrate + 'k' +
            ' -bufsize ' + abitrate + 'k' +
            ' -ac 1' +
            ' -payload_type 110' +
            ' -ssrc ' + audioSsrc +
            ' -f rtp' +
            ' -srtp_out_suite AES_CM_128_HMAC_SHA1_80' +
            ' -srtp_out_params ' + audioKey.toString('base64') +
            ' srtp://' + targetAddress + ':' + targetAudioPort +
            '?rtcpport=' + targetAudioPort +
            '&localrtcpport=' + targetAudioPort +
            '&pkt_size=' + packetsize;
        }

        let ffmpeg = spawn(this.videoProcessor, ffmpegCommand.split(' '), {env: process.env});
        this.log("Start streaming video from " + this.name + " with " + width + "x" + height + "@" + vbitrate + "kBit");
        if(this.debug){
          console.log("ffmpeg " + ffmpegCommand);
          ffmpeg.stderr.on('data', function(data) {
            console.log(data.toString());
          });
        }
        let self = this;
        ffmpeg.on('close', (code) => {
          if(code == null || code == 0 || code == 255){
            self.log("Stopped streaming");
          } else {
            self.log("ERROR: FFmpeg exited with code " + code);
            for(var i=0; i < self.streamControllers.length; i++){
              var controller = self.streamControllers[i];
              if(controller.sessionIdentifier === sessionID){
                controller.forceStop();
              }
            }
          }
        });
        this.ongoingSessions[sessionIdentifier] = ffmpeg;
      }

      delete this.pendingSessions[sessionIdentifier];
    } else if (requestType == "stop") {
      var ffmpegProcess = this.ongoingSessions[sessionIdentifier];
      if (ffmpegProcess) {
        ffmpegProcess.kill('SIGTERM');
      }
      delete this.ongoingSessions[sessionIdentifier];
    }
  }
}

FFMPEG.prototype.createCameraControlService = function() {
  var controlService = new Service.CameraControl();

  this.services.push(controlService);

  if(this.audio){
    var microphoneService = new Service.Microphone();
    this.services.push(microphoneService);
  }
}

// Private

FFMPEG.prototype._createStreamControllers = function(maxStreams, options) {
  let self = this;

  for (var i = 0; i < maxStreams; i++) {
    var streamController = new StreamController(i, options, self);

    self.services.push(streamController.service);
    self.streamControllers.push(streamController);
  }
}
<commit_msg>Allow passing additional command line options to ffmpeg. (#165)<commit_after>'use strict';
var uuid, Service, Characteristic, StreamController;

var crypto = require('crypto');
var fs = require('fs');
var ip = require('ip');
var spawn = require('child_process').spawn;
var drive = require('./drive').drive;

module.exports = {
  FFMPEG: FFMPEG
};

function FFMPEG(hap, cameraConfig, log, videoProcessor) {
  uuid = hap.uuid;
  Service = hap.Service;
  Characteristic = hap.Characteristic;
  StreamController = hap.StreamController;
  this.log = log;

  var ffmpegOpt = cameraConfig.videoConfig;
  this.name = cameraConfig.name;
  this.vcodec = ffmpegOpt.vcodec;
  this.videoProcessor = videoProcessor || 'ffmpeg';
  this.audio = ffmpegOpt.audio;
  this.acodec = ffmpegOpt.acodec;
  this.packetsize = ffmpegOpt.packetSize
  this.fps = ffmpegOpt.maxFPS || 10;
  this.maxBitrate = ffmpegOpt.maxBitrate || 300;
  this.debug = ffmpegOpt.debug;
  this.additionalCommandline = ffmpegOpt.additionalCommandline || '-tune zerolatency';

  if (!ffmpegOpt.source) {
    throw new Error("Missing source for camera.");
  }

  this.ffmpegSource = ffmpegOpt.source;
  this.ffmpegImageSource = ffmpegOpt.stillImageSource;

  this.services = [];
  this.streamControllers = [];

  this.pendingSessions = {};
  this.ongoingSessions = {};

  this.uploader = cameraConfig.uploader || false;
  if ( this.uploader )
    { this.drive = new drive(); }

  var numberOfStreams = ffmpegOpt.maxStreams || 2;
  var videoResolutions = [];

  this.maxWidth = ffmpegOpt.maxWidth || 1280;
  this.maxHeight = ffmpegOpt.maxHeight || 720;
  var maxFPS = (this.fps > 30) ? 30 : this.fps;

  if (this.maxWidth >= 320) {
    if (this.maxHeight >= 240) {
      videoResolutions.push([320, 240, maxFPS]);
      if (maxFPS > 15) {
        videoResolutions.push([320, 240, 15]);
      }
    }

    if (this.maxHeight >= 180) {
      videoResolutions.push([320, 180, maxFPS]);
      if (maxFPS > 15) {
        videoResolutions.push([320, 180, 15]);
      }
    }
  }

  if (this.maxWidth >= 480) {
    if (this.maxHeight >= 360) {
      videoResolutions.push([480, 360, maxFPS]);
    }

    if (this.maxHeight >= 270) {
      videoResolutions.push([480, 270, maxFPS]);
    }
  }

  if (this.maxWidth >= 640) {
    if (this.maxHeight >= 480) {
      videoResolutions.push([640, 480, maxFPS]);
    }

    if (this.maxHeight >= 360) {
      videoResolutions.push([640, 360, maxFPS]);
    }
  }

  if (this.maxWidth >= 1280) {
    if (this.maxHeight >= 960) {
      videoResolutions.push([1280, 960, maxFPS]);
    }

    if (this.maxHeight >= 720) {
      videoResolutions.push([1280, 720, maxFPS]);
    }
  }

  if (this.maxWidth >= 1920) {
    if (this.maxHeight >= 1080) {
      videoResolutions.push([1920, 1080, maxFPS]);
    }
  }

  let options = {
    proxy: false, // Requires RTP/RTCP MUX Proxy
    srtp: true, // Supports SRTP AES_CM_128_HMAC_SHA1_80 encryption
    video: {
      resolutions: videoResolutions,
      codec: {
        profiles: [0, 1, 2], // Enum, please refer StreamController.VideoCodecParamProfileIDTypes
        levels: [0, 1, 2] // Enum, please refer StreamController.VideoCodecParamLevelTypes
      }
    },
    audio: {
      codecs: [
        {
          type: "OPUS", // Audio Codec
          samplerate: 24 // 8, 16, 24 KHz
        },
        {
          type: "AAC-eld",
          samplerate: 16
        }
      ]
    }
  }

  this.createCameraControlService();
  this._createStreamControllers(numberOfStreams, options);
}

FFMPEG.prototype.handleCloseConnection = function(connectionID) {
  this.streamControllers.forEach(function(controller) {
    controller.handleCloseConnection(connectionID);
  });
}

FFMPEG.prototype.handleSnapshotRequest = function(request, callback) {
  let resolution = request.width + 'x' + request.height;
  var imageSource = this.ffmpegImageSource !== undefined ? this.ffmpegImageSource : this.ffmpegSource;
  let ffmpeg = spawn(this.videoProcessor, (imageSource + ' -t 1 -s '+ resolution + ' -f image2 -').split(' '), {env: process.env});
  var imageBuffer = Buffer(0);
  this.log("Snapshot from " + this.name + " at " + resolution);
  if(this.debug) console.log('ffmpeg '+imageSource + ' -t 1 -s '+ resolution + ' -f image2 -');
  ffmpeg.stdout.on('data', function(data) {
    imageBuffer = Buffer.concat([imageBuffer, data]);
  });
  ffmpeg.on('close', function(code) {
    if ( this.uploader )
      { this.drive.storePicture(this.name,imageBuffer); }
    callback(undefined, imageBuffer);
  }.bind(this));
}

FFMPEG.prototype.prepareStream = function(request, callback) {
  var sessionInfo = {};

  let sessionID = request["sessionID"];
  let targetAddress = request["targetAddress"];

  sessionInfo["address"] = targetAddress;

  var response = {};

  let videoInfo = request["video"];
  if (videoInfo) {
    let targetPort = videoInfo["port"];
    let srtp_key = videoInfo["srtp_key"];
    let srtp_salt = videoInfo["srtp_salt"];

    // SSRC is a 32 bit integer that is unique per stream
    let ssrcSource = crypto.randomBytes(4);
    ssrcSource[0] = 0;
    let ssrc = ssrcSource.readInt32BE(0, true);

    let videoResp = {
      port: targetPort,
      ssrc: ssrc,
      srtp_key: srtp_key,
      srtp_salt: srtp_salt
    };

    response["video"] = videoResp;

    sessionInfo["video_port"] = targetPort;
    sessionInfo["video_srtp"] = Buffer.concat([srtp_key, srtp_salt]);
    sessionInfo["video_ssrc"] = ssrc;
  }

  let audioInfo = request["audio"];
  if (audioInfo) {
    let targetPort = audioInfo["port"];
    let srtp_key = audioInfo["srtp_key"];
    let srtp_salt = audioInfo["srtp_salt"];

    // SSRC is a 32 bit integer that is unique per stream
    let ssrcSource = crypto.randomBytes(4);
    ssrcSource[0] = 0;
    let ssrc = ssrcSource.readInt32BE(0, true);

    let audioResp = {
      port: targetPort,
      ssrc: ssrc,
      srtp_key: srtp_key,
      srtp_salt: srtp_salt
    };

    response["audio"] = audioResp;

    sessionInfo["audio_port"] = targetPort;
    sessionInfo["audio_srtp"] = Buffer.concat([srtp_key, srtp_salt]);
    sessionInfo["audio_ssrc"] = ssrc;
  }

  let currentAddress = ip.address();
  var addressResp = {
    address: currentAddress
  };

  if (ip.isV4Format(currentAddress)) {
    addressResp["type"] = "v4";
  } else {
    addressResp["type"] = "v6";
  }

  response["address"] = addressResp;
  this.pendingSessions[uuid.unparse(sessionID)] = sessionInfo;

  callback(response);
}

FFMPEG.prototype.handleStreamRequest = function(request) {
  var sessionID = request["sessionID"];
  var requestType = request["type"];
  if (sessionID) {
    let sessionIdentifier = uuid.unparse(sessionID);

    if (requestType == "start") {
      var sessionInfo = this.pendingSessions[sessionIdentifier];
      if (sessionInfo) {
        var width = 1280;
        var height = 720;
        var fps = this.fps || 30;
        var vbitrate = this.maxBitrate;
        var abitrate = 32;
        var asamplerate = 16;
        var vcodec = this.vcodec || 'libx264';
        var acodec = this.acodec || 'libfdk_aac';
        var packetsize = this.packetsize || 1316; // 188 376
        var additionalCommandline = this.additionalCommandline ;

        let videoInfo = request["video"];
        if (videoInfo) {
          width = videoInfo["width"];
          height = videoInfo["height"];

          let expectedFPS = videoInfo["fps"];
          if (expectedFPS < fps) {
            fps = expectedFPS;
          }
          if(videoInfo["max_bit_rate"] < vbitrate) {
            vbitrate = videoInfo["max_bit_rate"];
          }
        }

        let audioInfo = request["audio"];
        if (audioInfo) {
          abitrate = audioInfo["max_bit_rate"];
          asamplerate = audioInfo["sample_rate"];
        }

        let targetAddress = sessionInfo["address"];
        let targetVideoPort = sessionInfo["video_port"];
        let videoKey = sessionInfo["video_srtp"];
        let videoSsrc = sessionInfo["video_ssrc"];
        let targetAudioPort = sessionInfo["audio_port"];
        let audioKey = sessionInfo["audio_srtp"];
        let audioSsrc = sessionInfo["audio_ssrc"];

        let ffmpegCommand = this.ffmpegSource + ' -map 0:0' +
          ' -vcodec ' + vcodec +
          ' -pix_fmt yuv420p' +
          ' -r ' + fps +
          ' -f rawvideo' +
          ' ' + additionalCommandline +
          ' -vf scale=' + width + ':' + height +
          ' -b:v ' + vbitrate + 'k' +
          ' -bufsize ' + vbitrate+ 'k' +
          ' -maxrate '+ vbitrate + 'k' +
          ' -payload_type 99' +
          ' -ssrc ' + videoSsrc +
          ' -f rtp' +
          ' -srtp_out_suite AES_CM_128_HMAC_SHA1_80' +
          ' -srtp_out_params ' + videoKey.toString('base64') +
          ' srtp://' + targetAddress + ':' + targetVideoPort +
          '?rtcpport=' + targetVideoPort +
          '&localrtcpport=' + targetVideoPort +
          '&pkt_size=' + packetsize;

        if(this.audio){
          ffmpegCommand+= ' -map 0:1' +
            ' -acodec ' + acodec +
            ' -profile:a aac_eld' +
            ' -flags +global_header' +
            ' -f null' +
            ' -ar ' + asamplerate + 'k' +
            ' -b:a ' + abitrate + 'k' +
            ' -bufsize ' + abitrate + 'k' +
            ' -ac 1' +
            ' -payload_type 110' +
            ' -ssrc ' + audioSsrc +
            ' -f rtp' +
            ' -srtp_out_suite AES_CM_128_HMAC_SHA1_80' +
            ' -srtp_out_params ' + audioKey.toString('base64') +
            ' srtp://' + targetAddress + ':' + targetAudioPort +
            '?rtcpport=' + targetAudioPort +
            '&localrtcpport=' + targetAudioPort +
            '&pkt_size=' + packetsize;
        }

        let ffmpeg = spawn(this.videoProcessor, ffmpegCommand.split(' '), {env: process.env});
        this.log("Start streaming video from " + this.name + " with " + width + "x" + height + "@" + vbitrate + "kBit");
        if(this.debug){
          console.log("ffmpeg " + ffmpegCommand);
        }

        // Always setup hook on stderr.
        // Without this streaming stops within one to two minutes.
        ffmpeg.stderr.on('data', function(data) {
          // Do not log to the console if debugging is turned off
          if(this.debug){
            console.log(data.toString());
          }
        });
        let self = this;
        ffmpeg.on('close', (code) => {
          if(code == null || code == 0 || code == 255){
            self.log("Stopped streaming");
          } else {
            self.log("ERROR: FFmpeg exited with code " + code);
            for(var i=0; i < self.streamControllers.length; i++){
              var controller = self.streamControllers[i];
              if(controller.sessionIdentifier === sessionID){
                controller.forceStop();
              }
            }
          }
        });
        this.ongoingSessions[sessionIdentifier] = ffmpeg;
      }

      delete this.pendingSessions[sessionIdentifier];
    } else if (requestType == "stop") {
      var ffmpegProcess = this.ongoingSessions[sessionIdentifier];
      if (ffmpegProcess) {
        ffmpegProcess.kill('SIGTERM');
      }
      delete this.ongoingSessions[sessionIdentifier];
    }
  }
}

FFMPEG.prototype.createCameraControlService = function() {
  var controlService = new Service.CameraControl();

  this.services.push(controlService);

  if(this.audio){
    var microphoneService = new Service.Microphone();
    this.services.push(microphoneService);
  }
}

// Private

FFMPEG.prototype._createStreamControllers = function(maxStreams, options) {
  let self = this;

  for (var i = 0; i < maxStreams; i++) {
    var streamController = new StreamController(i, options, self);

    self.services.push(streamController.service);
    self.streamControllers.push(streamController);
  }
}
<|endoftext|>


<commit_before>var express = require('express');
var path = require('path');
var fs = require('fs');
var http = require('http');
var https = require('https');
var socks = require('sockx');
var EventEmitter = require('events').EventEmitter;
var util = require('./util');
var logger = require('./util/logger');
var rules = require('./rules');
var setupHttps = require('./https').setup;
var httpsUtil = require('./https/ca');
var rulesUtil = require('./rules/util');
var initDataServer = require('./util/data-server');
var initLogServer = require('./util/log-server');
var pluginMgr = require('./plugins');
var config = require('./config');
var loadService = require('./service');
var initSocketMgr = require('./socket-mgr');
var tunnelProxy = require('./tunnel');
var upgradeProxy = require('./upgrade');
var ca = require('./https/ca');

function handleClientError(err, socket) {
  if (!socket.writable) {
    return socket.destroy(err);
  }
  var errCode = err && err.code;
  var statusCode = errCode === 'HPE_HEADER_OVERFLOW' ? 431 : 400;
  var stack = util.getErrorStack('clientError: Bad request' + (errCode ? ' (' + errCode + ')' : ''));
  socket.end('HTTP/1.1 ' + statusCode + ' Bad Request\r\n\r\n' + stack);
}

function proxy(callback) {
  var app = express();
  var server = http.createServer();
  var proxyEvents = new EventEmitter();
  var middlewares = ['./init', '../biz']
    .concat(require('./inspectors'))
    .concat(config.middlewares)
    .concat(require('./handlers'));
  server.timeout = 0;
  proxyEvents.config = config;
  proxyEvents.server = server;
  app.logger = logger;
  middlewares.forEach(function(mw) {
    mw && app.use((typeof mw == 'string' ? require(mw) : mw).bind(proxyEvents));
  });
  server.on('clientError', handleClientError);
  initSocketMgr(proxyEvents);
  setupHttps(server, proxyEvents);
  exportInterfaces(proxyEvents);
  tunnelProxy(server, proxyEvents);
  upgradeProxy(server);
  initDataServer(proxyEvents);
  initLogServer(proxyEvents);
  var properties = rulesUtil.properties;
  if (config.disableAllRules) {
    properties.set('disabledAllRules', true);
  } else if (config.disableAllRules === false) {
    properties.set('disabledAllRules', false);
  }
  if (config.disableAllPlugins) {
    properties.set('disabledAllPlugins', true);
  } else if (config.disableAllPlugins === false) {
    properties.set('disabledAllPlugins', false);
  }
  if (config.allowMultipleChoice) {
    properties.set('allowMultipleChoice', true);
  } else if (config.allowMultipleChoice === false) {
    properties.set('allowMultipleChoice', false);
  }
  rulesUtil.addValues(config.values, config.replaceExistValue);
  rulesUtil.addRules(config.rules, config.replaceExistRule);
  config.debug && rules.disableDnsCache();
  var count = 2;
  var execCallback = function() {
    if (--count === 0 && typeof callback === 'function') {
      callback.call(server, proxyEvents);
    }
  };
  util.getBoundIp(function(host) {
    util.checkPort(!config.INADDR_ANY && !host && config.port, function() {
      server.listen(config.port, host, execCallback);
    });
  });
  var createNormalServer = function(port, httpModule, opts) {
    if (!port) {
      return;
    }
    ++count;
    var optionServer = httpModule.createServer(opts);
    var isHttps = !!opts;
    proxyEvents[opts ? 'httpsServer' : 'httpServer'] = optionServer;
    optionServer.on('request', function(req, res) {
      req.isHttps = isHttps;
      app.handle(req, res);
    });
    optionServer.isHttps = isHttps;
    tunnelProxy(optionServer, proxyEvents);
    upgradeProxy(optionServer);
    optionServer.on('clientError', handleClientError);
    util.getBoundIp(function(host) {
      util.checkPort(!config.INADDR_ANY && !host && port, function() {
        optionServer.listen(port, host, execCallback);
      });
    });
  };
  createNormalServer(config.httpPort, http);
  createNormalServer(config.httpsPort, https, ca.SNI_OPTIONS);
  if (config.socksPort) {
    ++count;
    var boundHost;
    var socksServer = socks.createServer(function(info, accept, deny) {
      var dstPort = info.dstPort;
      var connPath = info.dstAddr + ':' + dstPort;
      var headers = { host: connPath };
      if (dstPort != 80 && dstPort != 443) {
        headers['x-whistle-policy'] = 'tunnel';
      }
      var client = http.request({
        method: 'CONNECT',
        agent: false,
        path: connPath,
        host: boundHost,
        port: config.port,
        rejectUnauthorized: false,
        headers: headers
      });
      client.on('error', deny);
      client.on('connect', function(res, socket) {
        socket.on('error', deny);
        if (res.statusCode != 200) {
          return deny();
        }
        var reqSock = accept(true);
        if (reqSock) {
          reqSock.pipe(socket).pipe(reqSock);
        }
      });
      client.end();
    });
    proxyEvents.socksServer = socksServer;
    util.getBoundIp(function(host) {
      boundHost = host || '127.0.0.1';
      util.checkPort(!config.INADDR_ANY && !host && config.socksPort, function() {
        socksServer.listen(config.socksPort, host, execCallback);
      });
      socksServer.useAuth(socks.auth.None());
    });
  }
  require('../biz/init')(proxyEvents, function(){
    server.on('request', app);
    execCallback();
  });
  pluginMgr.initProxy(proxyEvents);
  return proxyEvents;
}

function exportInterfaces(obj) {
  obj.rules = rules;
  obj.util = util;
  obj.rulesUtil = rulesUtil;
  obj.httpsUtil = httpsUtil;
  obj.pluginMgr = pluginMgr;
  obj.logger = logger;
  obj.loadService = loadService;
  obj.setAuth = config.setAuth;
  obj.socketMgr = initSocketMgr;
  return obj;
}

process.on('uncaughtException', function(err){
  var stack = util.getErrorStack(err);
  fs.writeFileSync(path.join(process.cwd(), config.name + '.log'), '\r\n' + stack + '\r\n', {flag: 'a'});
  /*eslint no-console: "off"*/
  console.error(stack);
  process.exit(1);
});

module.exports = exportInterfaces(proxy);
<commit_msg>refactor: server timeout<commit_after>var express = require('express');
var path = require('path');
var fs = require('fs');
var http = require('http');
var https = require('https');
var socks = require('sockx');
var EventEmitter = require('events').EventEmitter;
var util = require('./util');
var logger = require('./util/logger');
var rules = require('./rules');
var setupHttps = require('./https').setup;
var httpsUtil = require('./https/ca');
var rulesUtil = require('./rules/util');
var initDataServer = require('./util/data-server');
var initLogServer = require('./util/log-server');
var pluginMgr = require('./plugins');
var config = require('./config');
var loadService = require('./service');
var initSocketMgr = require('./socket-mgr');
var tunnelProxy = require('./tunnel');
var upgradeProxy = require('./upgrade');
var ca = require('./https/ca');

function handleClientError(err, socket) {
  if (!socket.writable) {
    return socket.destroy(err);
  }
  var errCode = err && err.code;
  var statusCode = errCode === 'HPE_HEADER_OVERFLOW' ? 431 : 400;
  var stack = util.getErrorStack('clientError: Bad request' + (errCode ? ' (' + errCode + ')' : ''));
  socket.end('HTTP/1.1 ' + statusCode + ' Bad Request\r\n\r\n' + stack);
}

function proxy(callback) {
  var app = express();
  var server = http.createServer();
  var proxyEvents = new EventEmitter();
  var middlewares = ['./init', '../biz']
    .concat(require('./inspectors'))
    .concat(config.middlewares)
    .concat(require('./handlers'));
  server.timeout = 1000 * 60 * (config.strict ? 3 : 60);
  proxyEvents.config = config;
  proxyEvents.server = server;
  app.logger = logger;
  middlewares.forEach(function(mw) {
    mw && app.use((typeof mw == 'string' ? require(mw) : mw).bind(proxyEvents));
  });
  server.on('clientError', handleClientError);
  initSocketMgr(proxyEvents);
  setupHttps(server, proxyEvents);
  exportInterfaces(proxyEvents);
  tunnelProxy(server, proxyEvents);
  upgradeProxy(server);
  initDataServer(proxyEvents);
  initLogServer(proxyEvents);
  var properties = rulesUtil.properties;
  if (config.disableAllRules) {
    properties.set('disabledAllRules', true);
  } else if (config.disableAllRules === false) {
    properties.set('disabledAllRules', false);
  }
  if (config.disableAllPlugins) {
    properties.set('disabledAllPlugins', true);
  } else if (config.disableAllPlugins === false) {
    properties.set('disabledAllPlugins', false);
  }
  if (config.allowMultipleChoice) {
    properties.set('allowMultipleChoice', true);
  } else if (config.allowMultipleChoice === false) {
    properties.set('allowMultipleChoice', false);
  }
  rulesUtil.addValues(config.values, config.replaceExistValue);
  rulesUtil.addRules(config.rules, config.replaceExistRule);
  config.debug && rules.disableDnsCache();
  var count = 2;
  var execCallback = function() {
    if (--count === 0 && typeof callback === 'function') {
      callback.call(server, proxyEvents);
    }
  };
  util.getBoundIp(function(host) {
    util.checkPort(!config.INADDR_ANY && !host && config.port, function() {
      server.listen(config.port, host, execCallback);
    });
  });
  var createNormalServer = function(port, httpModule, opts) {
    if (!port) {
      return;
    }
    ++count;
    var optionServer = httpModule.createServer(opts);
    var isHttps = !!opts;
    proxyEvents[opts ? 'httpsServer' : 'httpServer'] = optionServer;
    optionServer.on('request', function(req, res) {
      req.isHttps = isHttps;
      app.handle(req, res);
    });
    optionServer.isHttps = isHttps;
    tunnelProxy(optionServer, proxyEvents);
    upgradeProxy(optionServer);
    optionServer.on('clientError', handleClientError);
    util.getBoundIp(function(host) {
      util.checkPort(!config.INADDR_ANY && !host && port, function() {
        optionServer.listen(port, host, execCallback);
      });
    });
  };
  createNormalServer(config.httpPort, http);
  createNormalServer(config.httpsPort, https, ca.SNI_OPTIONS);
  if (config.socksPort) {
    ++count;
    var boundHost;
    var socksServer = socks.createServer(function(info, accept, deny) {
      var dstPort = info.dstPort;
      var connPath = info.dstAddr + ':' + dstPort;
      var headers = { host: connPath };
      if (dstPort != 80 && dstPort != 443) {
        headers['x-whistle-policy'] = 'tunnel';
      }
      var client = http.request({
        method: 'CONNECT',
        agent: false,
        path: connPath,
        host: boundHost,
        port: config.port,
        rejectUnauthorized: false,
        headers: headers
      });
      client.on('error', deny);
      client.on('connect', function(res, socket) {
        socket.on('error', deny);
        if (res.statusCode != 200) {
          return deny();
        }
        var reqSock = accept(true);
        if (reqSock) {
          reqSock.pipe(socket).pipe(reqSock);
        }
      });
      client.end();
    });
    proxyEvents.socksServer = socksServer;
    util.getBoundIp(function(host) {
      boundHost = host || '127.0.0.1';
      util.checkPort(!config.INADDR_ANY && !host && config.socksPort, function() {
        socksServer.listen(config.socksPort, host, execCallback);
      });
      socksServer.useAuth(socks.auth.None());
    });
  }
  require('../biz/init')(proxyEvents, function(){
    server.on('request', app);
    execCallback();
  });
  pluginMgr.initProxy(proxyEvents);
  return proxyEvents;
}

function exportInterfaces(obj) {
  obj.rules = rules;
  obj.util = util;
  obj.rulesUtil = rulesUtil;
  obj.httpsUtil = httpsUtil;
  obj.pluginMgr = pluginMgr;
  obj.logger = logger;
  obj.loadService = loadService;
  obj.setAuth = config.setAuth;
  obj.socketMgr = initSocketMgr;
  return obj;
}

process.on('uncaughtException', function(err){
  var stack = util.getErrorStack(err);
  fs.writeFileSync(path.join(process.cwd(), config.name + '.log'), '\r\n' + stack + '\r\n', {flag: 'a'});
  /*eslint no-console: "off"*/
  console.error(stack);
  process.exit(1);
});

module.exports = exportInterfaces(proxy);
<|endoftext|>


<commit_before>var $ = require('jquery');

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

var Enemy = require("./enemies.js");
var Bluecifer = require('./bluecifer');

var bluecifer = new Bluecifer (150, 150, 50, 41);

$('#game-over').css('visibility', 'visible');

var themeSong = document.getElementById("theme-song");

var enemy = new Enemy();
var enemy2 = new Enemy();
var enemy3 = new Enemy();

function drawAirport () {
  var image = new Image();
  image.src = "IMGS/dia-photo.jpg";
  ctx.drawImage(image, 150, 340, 30, 30);
  var airport = {};
  airport.x = 150;
  airport.y = 340;
  console.log(airport.y);
  return this;
}

function newEnemy () {
  enemy.draw(ctx);
  // collision(enemy, bluecifer);
  enemy.moveLeftRandom();
}

function newEnemy2 () {
  enemy2.draw(ctx);
  // collision(enemy2, bluecifer);
  setTimeout(function() {
    enemy2.moveLeftRandom();
    return enemy2;
  }, 3000);
}

function newEnemy3 () {
  enemy3.draw(ctx);
  // collision(enemy3, bluecifer);
  setTimeout(function() {
    enemy3.moveLeftRandom();
    return enemy3;
  }, 6000);
}

function collision(a, b) {
  if (((a.y + a.height) < (b.y)) || (a.y > (b.y + b.height)) || ((a.x + a.width) < b.x) || (a.x > (b.x + b.width))) {
  //if there is no collision
  }
  else {
    themeSong.pause();
    $('#game-over').css('visibility', 'visible');
    resetGame();
  }
}

function repeat () {
  setTimeout(function() {
    requestAnimationFrame(repeat);
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    bluecifer.draw(ctx);
    bluecifer.gravity();
    newEnemy();
    newEnemy2();
    newEnemy3();
    detectFloorCollision();
  }, 1000 / 50);
    keepScore();
} //end of big repeat function

$(document).on("click", function () {
  themeSong.play();
  $('#game-over').css('visibility', 'hidden');
  repeat();
});

var scoreCounter = 0;

function keepScore() {
    var currentScore = scoreCounter++;
    if (currentScore <= 100){
   $('#game-score').text("000" + currentScore);
 }else if (currentScore <= 1000){
  $('#game-score').text("00" + currentScore);
}else if (currentScore <= 10000){
  $('#game-score').text("0" + currentScore);
  drawAirport();
}else{
  $('#game-score').text(currentScore);
  }
}

function detectFloorCollision () {
  if (bluecifer.y > 350) {
    themeSong.pause();
    resetGame();
    bluecifer.y = 300;
  }
}

$(document).on("keydown", function (key) {
  if (key.which === 32) {
    if ($('#game-over').css('visibility', 'hidden')) {
      bluecifer.moveUp();
      detectCeilingCollision();
    }
    else {
      resetGame();
    }
  } //end of if statement for space bar
  else if (key.which === 13) {
    themeSong.pause();
  } // end of if statement for enter key
}); //end of entire function

function detectCeilingCollision () {
  if (bluecifer.y < 0) {
    bluecifer.y = bluecifer.y + 20;
  }
}

function resetGame () {
  alert("Game over! Your score was " + scoreCounter);
  location.reload();
  $('#game-over').css('visibility', 'hidden');
  repeat();
}
<commit_msg>got collision detection for airport<commit_after>var $ = require('jquery');

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

var Enemy = require("./enemies.js");
var Bluecifer = require('./bluecifer');

var bluecifer = new Bluecifer (150, 150, 50, 41);

$('#game-over').css('visibility', 'visible');

var themeSong = document.getElementById("theme-song");

var enemy = new Enemy();
var enemy2 = new Enemy();
var enemy3 = new Enemy();

function drawAirport () {
  var image = new Image();
  image.src = "IMGS/dia-photo.jpg";
  ctx.drawImage(image, 150, 340, 30, 30);
  var airport = {};
  airport.x = 150;
  airport.y = 340;
  airportCollision(airport, bluecifer);
  return this;
}

function newEnemy () {
  enemy.draw(ctx);
  // collision(enemy, bluecifer);
  enemy.moveLeftRandom();
}

function newEnemy2 () {
  enemy2.draw(ctx);
  // collision(enemy2, bluecifer);
  setTimeout(function() {
    enemy2.moveLeftRandom();
    return enemy2;
  }, 3000);
}

function newEnemy3 () {
  enemy3.draw(ctx);
  // collision(enemy3, bluecifer);
  setTimeout(function() {
    enemy3.moveLeftRandom();
    return enemy3;
  }, 6000);
}

function collision(a, b) {
  if (((a.y + a.height) < (b.y)) || (a.y > (b.y + b.height)) || ((a.x + a.width) < b.x) || (a.x > (b.x + b.width))) {
  //if there is no collision
  }
  else {
    themeSong.pause();
    $('#game-over').css('visibility', 'visible');
    resetGame();
  }
} //end of collision function

function airportCollision (a, b) {
  if (((a.y + a.height) < (b.y)) || (a.y > (b.y + b.height)) || ((a.x + a.width) < b.x) || (a.x > (b.x + b.width))) {
  //if there is no collision
  }
  else {
    themeSong.pause();
    alert("hi");
  }
} //end of airportCollision function

function repeat () {
  setTimeout(function() {
    requestAnimationFrame(repeat);
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    bluecifer.draw(ctx);
    bluecifer.gravity();
    newEnemy();
    newEnemy2();
    newEnemy3();
    detectFloorCollision();
  }, 1000 / 50);
    keepScore();
} //end of big repeat function

$(document).on("click", function () {
  themeSong.play();
  $('#game-over').css('visibility', 'hidden');
  repeat();
});

var scoreCounter = 0;

function keepScore() {
    var currentScore = scoreCounter++;
    if (currentScore <= 100){
   $('#game-score').text("000" + currentScore);
 }else if (currentScore <= 1000){
  $('#game-score').text("00" + currentScore);
}else if (currentScore <= 10000){
  $('#game-score').text("0" + currentScore);
  drawAirport();
}else{
  $('#game-score').text(currentScore);
  }
}

function detectFloorCollision () {
  if (bluecifer.y > 350) {
    themeSong.pause();
    resetGame();
    bluecifer.y = 300;
  }
}

$(document).on("keydown", function (key) {
  if (key.which === 32) {
    if ($('#game-over').css('visibility', 'hidden')) {
      bluecifer.moveUp();
      detectCeilingCollision();
    }
    else {
      resetGame();
    }
  } //end of if statement for space bar
  else if (key.which === 13) {
    themeSong.pause();
  } // end of if statement for enter key
}); //end of entire function

function detectCeilingCollision () {
  if (bluecifer.y < 0) {
    bluecifer.y = bluecifer.y + 20;
  }
}

function resetGame () {
  alert("Game over! Your score was " + scoreCounter);
  location.reload();
  $('#game-over').css('visibility', 'hidden');
  repeat();
}
<|endoftext|>


<commit_before><commit_msg>Added param data<commit_after><|endoftext|>


<commit_before>'use strict'

let	name       = require('./package.json').moduleName,
    gulp       = require('gulp'),
    browserify = require('browserify'),
    babelify   = require('babelify'),
    source     = require('vinyl-source-stream'),
    buffer     = require('vinyl-buffer'),
    plugins    = require('gulp-load-plugins')()

const catchError = function(err) {

	console.log(err.toString())
	this.emit('end')

}

const scripts = function() {

	let bify = browserify({
		entries    : './src/scripts/main.js',
		standalone : name
	})

	let transformer = babelify.configure({
		presets: ['es2015']
	})

	bify.transform(transformer)
	    .bundle()
	    .on('error', catchError)
	    .pipe(source(name + '.min.js'))
	    .pipe(buffer())
	    .pipe(plugins.uglify())
	    .on('error', catchError)
	    .pipe(gulp.dest('./dist'))

}

const styles = function() {

	gulp.src('./src/styles/main.scss')
	    .pipe(plugins.sass())
	    .on('error', catchError)
	    .pipe(plugins.rename(function(path) { path.basename = name + '.min' }))
	    .pipe(plugins.autoprefixer('last 2 version', '> 1%'))
	    .pipe(plugins.minifyCss())
	    .pipe(gulp.dest('./dist'))

}

const watch = function() {

	gulp.watch('./src/styles/**/*.scss', ['styles'])
	gulp.watch('./src/scripts/**/*.js', ['scripts'])

}

gulp.task('scripts', scripts)
gulp.task('styles', styles)
gulp.task('default', ['styles', 'scripts'])
gulp.task('watch', ['default'], watch)<commit_msg>Use arrow function to rename the path<commit_after>'use strict'

let	name       = require('./package.json').moduleName,
    gulp       = require('gulp'),
    browserify = require('browserify'),
    babelify   = require('babelify'),
    source     = require('vinyl-source-stream'),
    buffer     = require('vinyl-buffer'),
    plugins    = require('gulp-load-plugins')()

const catchError = function(err) {

	console.log(err.toString())
	this.emit('end')

}

const scripts = function() {

	let bify = browserify({
		entries    : './src/scripts/main.js',
		standalone : name
	})

	let transformer = babelify.configure({
		presets: ['es2015']
	})

	bify.transform(transformer)
	    .bundle()
	    .on('error', catchError)
	    .pipe(source(name + '.min.js'))
	    .pipe(buffer())
	    .pipe(plugins.uglify())
	    .on('error', catchError)
	    .pipe(gulp.dest('./dist'))

}

const styles = function() {

	gulp.src('./src/styles/main.scss')
	    .pipe(plugins.sass())
	    .on('error', catchError)
	    .pipe(plugins.rename((path) => path.basename = name + '.min'))
	    .pipe(plugins.autoprefixer('last 2 version', '> 1%'))
	    .pipe(plugins.minifyCss())
	    .pipe(gulp.dest('./dist'))

}

const watch = function() {

	gulp.watch('./src/styles/**/*.scss', ['styles'])
	gulp.watch('./src/scripts/**/*.js', ['scripts'])

}

gulp.task('scripts', scripts)
gulp.task('styles', styles)
gulp.task('default', ['styles', 'scripts'])
gulp.task('watch', ['default'], watch)<|endoftext|>


<commit_before>// Dependencies
var CliGraph = require("cli-graph");

// Configurations
CliGraph.defaults.marks = {
    hAxis: " "
  , vAxis: " "
  , center: " "
  , point: "."
  , rightArrow: " "
  , topArrow: " "
  , background: " "
};

/**
 * CliCircle
 * Creates a new instance of `CliCircle`.
 *
 * @name CliCircle
 * @function
 * @param {Number} radius The radius value.
 * @param {String} chr The character used for drawing the circle (default: `"."`).
 * @return {CliCircle} The `CliCircle` instance containing:
 *
 *  - `radius` (Number): The circle radius.
 *  - `diameter` (Number): The circle diameter.
 *  - `chr` (String): The point character.
 *  - `graph` (CliGraph): The graph instance.
 *
 */
function CliCircle(radius, chr) {
    if (this.constructor !== CliCircle) {
        return new CliCircle(radius);
    }

    // r ^ 2 = x ^ 2 + y ^ 2
    // y ^ 2 = r ^ 2 - x ^ 2
    // y = sqrt( r ^ 2 - x ^ 2)
    this.radius = radius;
    var diameter = this.diameter = radius * 2;
    this.chr = chr || CliGraph.defaults.marks.point;
    this.graph = new CliGraph({
        height: radius * 2
      , width: radius * 2
      , marks: {
            point: this.chr
        }
    }).setFunctionX(function (x) {
        return Math.sqrt(radius * radius - x * x)
    }).setFunctionX(function (x) {
        return - Math.sqrt(radius * radius - x * x)
    }).setFunctionY(function (y) {
        return Math.sqrt(radius * radius - y * y)
    }).setFunctionY(function (y) {
        return - Math.sqrt(radius * radius - y * y)
    });
}

/**
 * toString
 * Stringifies a circle.
 *
 * @name toString
 * @function
 * @return {String} The stringified circle.
 */
CliCircle.prototype.toString = function () {
    return this.graph.toString();
};

module.exports = CliCircle;
<commit_msg>Fixed the height and width of the graph.<commit_after>// Dependencies
var CliGraph = require("cli-graph")
  , Ul = require("ul")
  ;

// Configurations
CliGraph.defaults.marks = {
    hAxis: " "
  , vAxis: " "
  , center: " "
  , point: "."
  , rightArrow: " "
  , topArrow: " "
  , background: " "
};

/**
 * CliCircle
 * Creates a new instance of `CliCircle`.
 *
 * @name CliCircle
 * @function
 * @param {Number} radius The radius value.
 * @param {String} chr The character used for drawing the circle (default: `"."`).
 * @param {Object} opts Options passed to the `CliGraph` constructor.
 * @return {CliCircle} The `CliCircle` instance containing:
 *
 *  - `radius` (Number): The circle radius.
 *  - `diameter` (Number): The circle diameter.
 *  - `chr` (String): The point character.
 *  - `graph` (CliGraph): The graph instance.
 *
 */
function CliCircle(radius, chr, opts) {
    if (this.constructor !== CliCircle) {
        return new CliCircle(radius);
    }

    // r ^ 2 = x ^ 2 + y ^ 2
    // y ^ 2 = r ^ 2 - x ^ 2
    // y = sqrt( r ^ 2 - x ^ 2)
    this.radius = radius;
    var diameter = this.diameter = radius * 2;
    this.chr = chr || CliGraph.defaults.marks.point;
    this.graph = new CliGraph(Ul.merge(opts, {
        height: radius * 2 + 2
      , width: radius * 2 + 1
      , marks: {
            point: this.chr
        }
    })).setFunctionX(function (x) {
        return Math.sqrt(radius * radius - x * x)
    }).setFunctionX(function (x) {
        return - Math.sqrt(radius * radius - x * x)
    }).setFunctionY(function (y) {
        return Math.sqrt(radius * radius - y * y)
    }).setFunctionY(function (y) {
        return - Math.sqrt(radius * radius - y * y)
    });
}

/**
 * toString
 * Stringifies a circle.
 *
 * @name toString
 * @function
 * @return {String} The stringified circle.
 */
CliCircle.prototype.toString = function () {
    return this.graph.toString();
};

module.exports = CliCircle;
<|endoftext|>


<commit_before>'use strict'

var Transform = require('stream').Transform
var util = require('util')

exports = module.exports = function(opts) {
  return new Decoder(opts)
}
exports.decode = exports

var Decoder = exports.Decoder = function(opts) {
  this.opts = util._extend({
    lengthSize: 4,
    maxSize: 0,
    unbuffered: false
  }, opts)

  this.getLength = this.opts.getLength || createGetLengthMethod(this.opts.lengthSize)
  this.buffer = null
  this.frameLength = -1
  this.framePos = 0

  Transform.call(this, opts)
}

util.inherits(Decoder, Transform)

Decoder.prototype._transform = function(chunk, enc, cont) {
  while (chunk.length > 0) {
    var start = this.opts.lengthSize

    if (this.buffer) {
      chunk = Buffer.concat([this.buffer, chunk])
      this.buffer = null
    }

    if (this.frameLength < 0) {
      if (chunk.length < this.opts.lengthSize) {
        this.buffer = chunk
        return cont()
      }

      this.frameLength = this.getLength(chunk)

      if (this.frameLength < 0) {
        return cont(new Error('Message length is less than zero'))
      }

      // prevent denial-of-service attacks
      if (this.opts.maxSize > 0 && this.frameLength > this.opts.maxSize) {
        return cont(new Error('Message is larger than the allowed maximum of ' + this.opts.maxSize))
      }
    } else if (this.opts.unbuffered) {
      start = 0
    }

    var end = start + this.frameLength - this.framePos

    if (this.opts.unbuffered) {
      end = Math.min(end, chunk.length)
    } else if (chunk.length < end) {
      this.buffer = chunk
      return cont()
    }

    var buf = chunk.slice(start, end)

    buf.framePos = this.framePos
    buf.frameLength = this.frameLength

    this.framePos += end - start
    buf.frameEnd = this.framePos === this.frameLength

    if (buf.frameEnd) {
      this.frameLength = -1
      this.framePos = 0
    }

    this.push(buf)

    if (chunk.length > end) {
      chunk = chunk.slice(end)
    } else {
      return cont()
    }
  }
}

exports.encode = function(opts) {
  return new Encoder(opts)
}

var Encoder = exports.Encoder = function(opts) {
  this.opts = util._extend({ lengthSize: 4 }, opts)

  this.setLength = this.opts.setLength || createSetLengthMethod(this.opts.lengthSize)

  Transform.call(this)
}

util.inherits(Encoder, Transform)

Encoder.prototype._transform = function(message, enc, cont) {
  var length = new Buffer(this.opts.lengthSize)
  this.setLength(length, message.length)
  this.push(Buffer.concat([length, message]))
  cont()
}

// backwards compatibility
exports.prefix = exports.encode
exports.FrameStream = Decoder
exports.LengthPrefixStream = Encoder

function createGetLengthMethod(lengthSize) {
  switch (lengthSize) {
    case 1:
      return function(buffer) {
        return buffer.readInt8(0)
      }
    case 2:
      return function(buffer) {
        return buffer.readInt16BE(0)
      }
    case 4:
      return function(buffer) {
        return buffer.readInt32BE(0)
      }
    default:
      throw new Error('Invalid frame length size')
  }
}

function createSetLengthMethod(lengthSize) {
  switch (lengthSize) {
    case 1:
      return function(buffer, value) {
        return buffer.writeInt8(value, 0)
      }
    case 2:
      return function(buffer, value) {
        return buffer.writeInt16BE(value, 0)
      }
    case 4:
      return function(buffer, value) {
        return buffer.writeInt32BE(value, 0)
      }
    default:
      throw new Error('Invalid frame length size')
  }
}
<commit_msg>Add method for pushing encoded frame data so it can be overriden if required (e.g. to push each buffer separately to save Buffer.concat if you know you've corked the stream to which Encoder is being piped)<commit_after>'use strict'

var Transform = require('stream').Transform
var util = require('util')

exports = module.exports = function(opts) {
  return new Decoder(opts)
}
exports.decode = exports

var Decoder = exports.Decoder = function(opts) {
  this.opts = util._extend({
    lengthSize: 4,
    maxSize: 0,
    unbuffered: false
  }, opts)

  this.getLength = this.opts.getLength || createGetLengthMethod(this.opts.lengthSize)
  this.buffer = null
  this.frameLength = -1
  this.framePos = 0

  Transform.call(this, opts)
}

util.inherits(Decoder, Transform)

Decoder.prototype._transform = function(chunk, enc, cont) {
  while (chunk.length > 0) {
    var start = this.opts.lengthSize

    if (this.buffer) {
      chunk = Buffer.concat([this.buffer, chunk])
      this.buffer = null
    }

    if (this.frameLength < 0) {
      if (chunk.length < this.opts.lengthSize) {
        this.buffer = chunk
        return cont()
      }

      this.frameLength = this.getLength(chunk)

      if (this.frameLength < 0) {
        return cont(new Error('Message length is less than zero'))
      }

      // prevent denial-of-service attacks
      if (this.opts.maxSize > 0 && this.frameLength > this.opts.maxSize) {
        return cont(new Error('Message is larger than the allowed maximum of ' + this.opts.maxSize))
      }
    } else if (this.opts.unbuffered) {
      start = 0
    }

    var end = start + this.frameLength - this.framePos

    if (this.opts.unbuffered) {
      end = Math.min(end, chunk.length)
    } else if (chunk.length < end) {
      this.buffer = chunk
      return cont()
    }

    var buf = chunk.slice(start, end)

    buf.framePos = this.framePos
    buf.frameLength = this.frameLength

    this.framePos += end - start
    buf.frameEnd = this.framePos === this.frameLength

    if (buf.frameEnd) {
      this.frameLength = -1
      this.framePos = 0
    }

    this.push(buf)

    if (chunk.length > end) {
      chunk = chunk.slice(end)
    } else {
      return cont()
    }
  }
}

exports.encode = function(opts) {
  return new Encoder(opts)
}

var Encoder = exports.Encoder = function(opts) {
  this.opts = util._extend({ lengthSize: 4 }, opts)

  this.setLength = this.opts.setLength || createSetLengthMethod(this.opts.lengthSize)

  Transform.call(this)
}

util.inherits(Encoder, Transform)

Encoder.prototype._transform = function(message, enc, cont) {
  var length = new Buffer(this.opts.lengthSize)
  this.setLength(length, message.length)
  this._pushFrameData([length, message])
  cont()
}

Encoder.prototype._pushFrameData = function(bufs) {
  this.push(Buffer.concat(bufs))
}

// backwards compatibility
exports.prefix = exports.encode
exports.FrameStream = Decoder
exports.LengthPrefixStream = Encoder

function createGetLengthMethod(lengthSize) {
  switch (lengthSize) {
    case 1:
      return function(buffer) {
        return buffer.readInt8(0)
      }
    case 2:
      return function(buffer) {
        return buffer.readInt16BE(0)
      }
    case 4:
      return function(buffer) {
        return buffer.readInt32BE(0)
      }
    default:
      throw new Error('Invalid frame length size')
  }
}

function createSetLengthMethod(lengthSize) {
  switch (lengthSize) {
    case 1:
      return function(buffer, value) {
        return buffer.writeInt8(value, 0)
      }
    case 2:
      return function(buffer, value) {
        return buffer.writeInt16BE(value, 0)
      }
    case 4:
      return function(buffer, value) {
        return buffer.writeInt32BE(value, 0)
      }
    default:
      throw new Error('Invalid frame length size')
  }
}
<|endoftext|>


<commit_before>'use strict';

var fs = require('fs');
var shellExec = require('child_process').exec;
var MailParser = require("mailparser").MailParser;
var Encoder = require('node-html-encoder').Encoder;
var Cluestr = require('cluestr');
var async = require('async');

/**
 * HYDRATING FUNCTION
 *
 * @param {string} path Path of the specified file
 * @param {string} document to hydrate
 * @param {function} cb Callback, first parameter, is the error if any, then the processed data
 */

var reg = new RegExp("(<([^>]+)>)", "g");
var reg_space = new RegExp("  ", "g");

function exists(item){
  return item ? item : '';
}

module.exports = function(path, document, cb) {
  if(!document.metadatas) {
    document.metadatas = {};
  }
  if(!document.datas) {
    document.datas = {};
  }

  var mailparser = new MailParser();
  var encoder = new Encoder('entity');
  mailparser.on("end", function(mail_object){
    document.document_type = "email";

    document.metadatas.to = [];
    (mail_object.to || []).forEach(function(item){
      document.metadatas.to.push(item);
    });
    document.metadatas.cc = [];
    (mail_object.cc || []).forEach(function(item){
      document.metadatas.cc.push(item);
    });
    document.metadatas.bcc = [];
    (mail_object.bcc || []).forEach(function(item){
      document.metadatas.bcc.push(item);
    });
    document.metadatas.from = exists(mail_object.from);
    document.metadatas.subject = exists(mail_object.subject);

    if (mail_object.html) {
      document.datas.html = encoder.htmlDecode(mail_object.html).trim();
    }

    if (mail_object.text) {
      document.metadatas.text = mail_object.text;
    }
    else if (document.datas.html) {
      document.metadatas.text = document.datas.html.replace(reg, " ");
      document.metadatas.text = document.metadatas.text.replace(reg_space, " ");
    }

    var cluestr = new Cluestr();
    cluestr.setAccessToken(document.access_token);

    document.metadatas.text = document.metadatas.text.trim();
    async.each((mail_object.attachments || []), function(attachment, cb){
      var docAttachment = {};
      docAttachment.identifier = document.identifier + "/" +attachment.fileName;
        // File to send
      var fileConfig = {
        file: attachment.content,
        filename: attachment.fileName,
        knownLength: attachment.length
      };
      console.log(docAttachment);
      cluestr.sendDocumentAndFile(docAttachment, fileConfig, function(err, docAttachment) {
        console.log("&&&&&&&&&&&&&&&&&&&&&", err);
        console.log("&&&&&&&&&&&&&&&&&&&&&", docAttachment);
        cb();
      });
    }, function(err){
      cb(err, document);
    });
  });

  fs.createReadStream(path).pipe(mailparser);
};<commit_msg>remove prints<commit_after>'use strict';

var fs = require('fs');
var shellExec = require('child_process').exec;
var MailParser = require("mailparser").MailParser;
var Encoder = require('node-html-encoder').Encoder;
var Cluestr = require('cluestr');
var async = require('async');

/**
 * HYDRATING FUNCTION
 *
 * @param {string} path Path of the specified file
 * @param {string} document to hydrate
 * @param {function} cb Callback, first parameter, is the error if any, then the processed data
 */

var reg = new RegExp("(<([^>]+)>)", "g");
var reg_space = new RegExp("  ", "g");

function exists(item){
  return item ? item : '';
}

module.exports = function(path, document, cb) {
  if(!document.metadatas) {
    document.metadatas = {};
  }
  if(!document.datas) {
    document.datas = {};
  }

  var mailparser = new MailParser();
  var encoder = new Encoder('entity');
  mailparser.on("end", function(mail_object){
    document.document_type = "email";

    document.metadatas.to = [];
    (mail_object.to || []).forEach(function(item){
      document.metadatas.to.push(item);
    });
    document.metadatas.cc = [];
    (mail_object.cc || []).forEach(function(item){
      document.metadatas.cc.push(item);
    });
    document.metadatas.bcc = [];
    (mail_object.bcc || []).forEach(function(item){
      document.metadatas.bcc.push(item);
    });
    document.metadatas.from = exists(mail_object.from);
    document.metadatas.subject = exists(mail_object.subject);

    if (mail_object.html) {
      document.datas.html = encoder.htmlDecode(mail_object.html).trim();
    }

    if (mail_object.text) {
      document.metadatas.text = mail_object.text;
    }
    else if (document.datas.html) {
      document.metadatas.text = document.datas.html.replace(reg, " ");
      document.metadatas.text = document.metadatas.text.replace(reg_space, " ");
    }

    var cluestr = new Cluestr();
    cluestr.setAccessToken(document.access_token);

    document.metadatas.text = document.metadatas.text.trim();
    async.each((mail_object.attachments || []), function(attachment, cb){
      var docAttachment = {};
      docAttachment.identifier = document.identifier + "/" +attachment.fileName;
        // File to send
      var fileConfig = {
        file: attachment.content,
        filename: attachment.fileName,
        knownLength: attachment.length
      };
      console.log(docAttachment);
      cluestr.sendDocumentAndFile(docAttachment, fileConfig, function(err, docAttachment) {
        cb();
      });
    }, function(err){
      cb(err, document);
    });
  });

  fs.createReadStream(path).pipe(mailparser);
};<|endoftext|>


<commit_before>var async = require('async');
var gulp = require('gulp-help')(require('gulp'));
var plugins = require('gulp-load-plugins')();
var path = require('path');
var runSequence = require('run-sequence');
var fs = require('fs-extra');

var exec = require('child_process').exec;

var APP_FILES_GLOB = [
	'./**/*',
	'!./gulpfile.js',
	'!./build{,/**}',
	'!./node_modules{,/**}',
	'!./bower_components{,/**}'
];

var ROOT_APPLICATIONS_PATH = '/Applications';
var USER_APPLICATIONS_PATH = path.join(process.env.HOME, ROOT_APPLICATIONS_PATH);

var APP_NAME = 'Github Pulls';
var APP_NAME_FULL = APP_NAME + '.app';

var BASE_PATH = __dirname;
var BUILD_DIR = path.join(BASE_PATH, 'build');

var BUILD_APP_DIR = path.join(BUILD_DIR, 'app_files');
var BUILD_APP_PATH = path.join(BUILD_DIR, 'releases', 'osx64', APP_NAME_FULL);

var BASE_FILES_GLOB = BUILD_APP_DIR + '/*';
var FILES_GLOB = BASE_FILES_GLOB + '*/*';

var getAppPath = function(cb) {
	async.detectSeries(
		[USER_APPLICATIONS_PATH, ROOT_APPLICATIONS_PATH],
		fs.exists,
		function(result) {
			cb(path.join(result, APP_NAME_FULL));
		}
	);
};

function installNpmModules(callback) {
	exec(
		'npm install --production --loglevel error',
		{
			cwd: BUILD_APP_DIR
		},
		function(err, stdout, stderr) {
			if (err) {
				callback(err);
			}
			else {
				console.log(stdout || stderr);

				callback();
			}
		}
	);
}

function installBowerComponents(callback) {
	exec(
		'bower install --loglevel=error',
		{
			cwd: BUILD_APP_DIR
		},
		function(err, stdout, stderr) {
			if (err) {
				callback(err);
			}
			else {
				console.log(stdout || stderr);

				callback();
			}
		}
	);
}

gulp.task(
	'copy-files',
	function() {
		return gulp.src(APP_FILES_GLOB)
		.pipe(plugins.debug())
		.pipe(gulp.dest(BUILD_APP_DIR));
	}
);

gulp.task(
	'install-deps',
	function(done) {
		async.series(
			[installNpmModules, installBowerComponents],
			done
		);
	}
);

gulp.task(
	'build:app',
	function(done) {
		var NwBuilder = require('nw-builder');

		var nw = new NwBuilder(
			{
				files: FILES_GLOB,
				platforms: ['osx64'],
				appName: APP_NAME,
				buildDir: BUILD_DIR,
				buildType: function() {
					return 'releases';
				},
				cacheDir: path.join(BUILD_DIR, 'cache'),
				macIcns: path.join(BUILD_DIR, 'app.icns'),
				version: '0.12.2'
			}
		);

		nw.on('log',  console.log);

		nw.build().then(
			function() {
				console.log('build success');
				done();
			}
		).catch(
			function (error) {
				console.error(error);
				done(error);
			}
		);
	}
);

gulp.task('build', function(done) {
	return runSequence('copy-files', 'install-deps', 'build:app', done);
});

gulp.task(
	'build:copy',
	function(done) {
		getAppPath(
			function(destination) {
				async.series(
					[
						fs.remove.bind(fs, destination),
						fs.rename.bind(fs, BUILD_APP_PATH, destination),
						fs.remove.bind(fs, BUILD_APP_DIR)
					],
					function(err, results) {
						if (err) {
							console.log('Could not copy %s to %s', BUILD_APP_PATH, destination);
							return done(err);
						}

						done();
					}
				);
			}
		);
	}
);

var appExists = function(destination) {
	var exists = fs.existsSync(destination);

	if (!exists) {
		console.log('App hasn\'t been installed. Run "gulp build" first.');
	}

	return exists;
};

gulp.task(
	'build:update',
	function(done) {
		getAppPath(
			function(destination) {
				if (!appExists(destination)) {
					return;
				}

				var deployedPath = path.join(destination, 'Contents/Resources/app.nw');

				gulp.src(APP_FILES_GLOB)
				.pipe(plugins.newer(deployedPath))
				// .pipe(plugins.debug())
				.pipe(gulp.dest(deployedPath));

				done();
			}
		);
	}
);

gulp.task(
	'build:watch',
	function(done) {
		getAppPath(
			function(destination) {
				if (!appExists(destination)) {
					return;
				}

				var filesGlob = [].concat(APP_FILES_GLOB);

				filesGlob.push('!./css/*');

				gulp.watch(
					filesGlob,
					['scss', 'build:update']
				);
			}
		);
	}
);

gulp.task(
	'scss',
	function() {
		gulp.src('./scss/*.scss')
		.pipe(plugins.sass())
		.pipe(gulp.dest('./css'));
	}
);

gulp.task(
	'build:install',
	function(done) {
		return runSequence('build', 'build:copy', done)
	}
);<commit_msg>Add ability to update the node_modules directory (contains a ton of files, so don't want it to be part of the watch task)<commit_after>var async = require('async');
var gulp = require('gulp-help')(require('gulp'));
var plugins = require('gulp-load-plugins')();
var path = require('path');
var runSequence = require('run-sequence');
var fs = require('fs-extra');

var exec = require('child_process').exec;

var APP_FILES_GLOB = [
	'./**/*',
	'!./gulpfile.js',
	'!./build{,/**}',
	'!./node_modules{,/**}',
	'!./bower_components{,/**}'
];

var ROOT_APPLICATIONS_PATH = '/Applications';
var USER_APPLICATIONS_PATH = path.join(process.env.HOME, ROOT_APPLICATIONS_PATH);

var APP_NAME = 'Github Pulls';
var APP_NAME_FULL = APP_NAME + '.app';

var BASE_PATH = __dirname;
var BUILD_DIR = path.join(BASE_PATH, 'build');

var BUILD_APP_DIR = path.join(BUILD_DIR, 'app_files');
var BUILD_APP_PATH = path.join(BUILD_DIR, 'releases', 'osx64', APP_NAME_FULL);

var BASE_FILES_GLOB = BUILD_APP_DIR + '/*';
var FILES_GLOB = BASE_FILES_GLOB + '*/*';

var getAppPath = function(cb) {
	async.detectSeries(
		[USER_APPLICATIONS_PATH, ROOT_APPLICATIONS_PATH],
		fs.exists,
		function(result) {
			cb(path.join(result, APP_NAME_FULL));
		}
	);
};

function installNpmModules(callback) {
	exec(
		'npm install --production --loglevel error',
		{
			cwd: BUILD_APP_DIR
		},
		function(err, stdout, stderr) {
			if (err) {
				callback(err);
			}
			else {
				console.log(stdout || stderr);

				callback();
			}
		}
	);
}

function installBowerComponents(callback) {
	exec(
		'bower install --loglevel=error',
		{
			cwd: BUILD_APP_DIR
		},
		function(err, stdout, stderr) {
			if (err) {
				callback(err);
			}
			else {
				console.log(stdout || stderr);

				callback();
			}
		}
	);
}

gulp.task(
	'copy-files',
	function() {
		return gulp.src(APP_FILES_GLOB)
		.pipe(plugins.debug())
		.pipe(gulp.dest(BUILD_APP_DIR));
	}
);

gulp.task(
	'install-deps',
	function(done) {
		async.series(
			[installNpmModules, installBowerComponents],
			done
		);
	}
);

gulp.task(
	'build:app',
	function(done) {
		var NwBuilder = require('nw-builder');

		var nw = new NwBuilder(
			{
				files: FILES_GLOB,
				platforms: ['osx64'],
				appName: APP_NAME,
				buildDir: BUILD_DIR,
				buildType: function() {
					return 'releases';
				},
				cacheDir: path.join(BUILD_DIR, 'cache'),
				macIcns: path.join(BUILD_DIR, 'app.icns'),
				version: '0.12.2'
			}
		);

		nw.on('log',  console.log);

		nw.build().then(
			function() {
				console.log('build success');
				done();
			}
		).catch(
			function (error) {
				console.error(error);
				done(error);
			}
		);
	}
);

gulp.task('build', function(done) {
	return runSequence('copy-files', 'install-deps', 'build:app', done);
});

gulp.task(
	'build:copy',
	function(done) {
		getAppPath(
			function(destination) {
				async.series(
					[
						fs.remove.bind(fs, destination),
						fs.rename.bind(fs, BUILD_APP_PATH, destination),
						fs.remove.bind(fs, BUILD_APP_DIR)
					],
					function(err, results) {
						if (err) {
							console.log('Could not copy %s to %s', BUILD_APP_PATH, destination);
							return done(err);
						}

						done();
					}
				);
			}
		);
	}
);

var appExists = function(destination) {
	var exists = fs.existsSync(destination);

	if (!exists) {
		console.log('App hasn\'t been installed. Run "gulp build" first.');
	}

	return exists;
};

gulp.task(
	'build:update',
	function(done) {
		getAppPath(
			function(destination) {
				if (!appExists(destination)) {
					return;
				}

				var deployedPath = path.join(destination, 'Contents/Resources/app.nw');

				gulp.src(APP_FILES_GLOB)
				.pipe(plugins.newer(deployedPath))
				// .pipe(plugins.debug())
				.pipe(gulp.dest(deployedPath));

				done();
			}
		);
	}
);

gulp.task(
	'build:update-modules',
	function(done) {
		getAppPath(
			function(destination) {
				if (!appExists(destination)) {
					return;
				}

				var deployedPath = path.join(destination, 'Contents/Resources/app.nw');

				gulp.src('./node_modules{,/**}')
				.pipe(plugins.newer(deployedPath))
				.pipe(plugins.debug())
				.pipe(gulp.dest(deployedPath));

				done();
			}
		);
	}
);

gulp.task(
	'build:watch',
	function(done) {
		getAppPath(
			function(destination) {
				if (!appExists(destination)) {
					return;
				}

				var filesGlob = [].concat(APP_FILES_GLOB);

				filesGlob.push('!./css/*');

				gulp.watch(
					filesGlob,
					['scss', 'build:update']
				);
			}
		);
	}
);

gulp.task(
	'scss',
	function() {
		gulp.src('./scss/*.scss')
		.pipe(plugins.sass())
		.pipe(gulp.dest('./css'));
	}
);

gulp.task(
	'build:install',
	function(done) {
		return runSequence('build', 'build:copy', done)
	}
);<|endoftext|>


<commit_before>// Dependencies
var request = require('request');

// Includes
var _login = require('./util/login.js'),
  _getSession = require('./util/getSession.js'),
  _getCurrentUser = require('./util/getCurrentUser.js'),
  _setRank = require('./setRank.js'),
  _getRoles = require('./util/getRoles.js'),
  _getToken = require('./util/getToken.js'),
  _message = require('./message.js');

// Vars
var _jar = request.jar(); // Default cookie jar

// Define
function makeCallbackArray(options,success,failure,always) {
  return {success: options.success || success, failure: options.failure || failure, always: options.always || options.callback || always};
}

function login(options,password,jar,success,failure,always) {
  var callbacks = makeCallbackArray(options,success,failure,always);
  if (typeof options == 'object') {
    var j = options.jar;
    return _login((j ? j : _jar),options.username,options.password,callbacks);
  } else if (typeof options == 'string')
    return _login((jar ? jar : _jar),options,password,callbacks);
}

function getSession(options) {
  if (options && options.hasOwnProperty('jar'))
    return _getSession(options.jar);
  else
    return _getSession(options || _jar);
}

function getCurrentUser(options,jar,success,failure,always) {
  var callbacks = makeCallbackArray(options,success,failure,always);
  if (typeof options == 'object') {
    var j = options.jar;
    return _getCurrentUser((j ? j : _jar), options.option, callbacks);
  } else
    return _getCurrentUser((jar ? jar : _jar), options, callbacks);
}

function getRoles(options,rank,success,failure,always) {
  var callbacks = makeCallbackArray(options,success,failure,always);
  if (typeof options == 'object')
    return _getRoles(options.group, options.rank, callbacks);
  else
    return _getRoles(options, rank, callbacks);
}

function getToken(options,jar,callback,failure) {
  var callbacks = {failure: options.failure || failure};
  if (typeof options == 'object') {
    var j = options.jar;
    return _getToken((j ? j : _jar), options.url, callback, callbacks);
  } else
    return _getToken((jar ? jar : _jar), options, callback, callbacks);
}

function setRank(options,target,roleset,token,jar,success,failure,always) {
  var callbacks = makeCallbackArray(options,success,failure,always);
  if (typeof options == 'object') {
    var j = options.jar;
    return _setRank((j ? j : _jar), options.group, options.target, options.roleset, options.token, callbacks);
  } else
    return _setRank((jar ? jar : _jar), options, target, roleset, token, callbacks);
}

function setRankBuffer(options) {
  if (options.rank) {
    getRoles(options.group,options.rank,function(role) {
      options.roleset = role;
      setRank(options);
    },options.failure,options.always);
  } else
    setRank.apply(undefined, arguments);
}

function message(options,subject,body,token,jar,success,failure,always) {
  var callbacks = makeCallbackArray(options,success,failure,always);
  if (typeof options == 'object') {
    var j = options.jar;
    return _message((j ? j : _jar), options.recipient, options.subject, options.body, options.token, callbacks);
  } else
    return _message((jar ? jar : _jar), options, subject, body, token, callbacks);
}

// Export
module.exports = {
  getJar: function() {
    return _jar;
  },
  login: login,
  getSession: getSession,
  getCurrentUser: getCurrentUser,
  setRank: setRankBuffer,
  getRoles: getRoles,
  getToken: getToken,
  message: message
};
<commit_msg>New format<commit_after>// Dependencies
var request = require('request');

// Includes
var login = require('./util/login.js'),
  getSession = require('./util/getSession.js'),
  getCurrentUser = require('./util/getCurrentUser.js'),
  setRank = require('./setRank.js'),
  getRoles = require('./util/getRoles.js'),
  getToken = require('./util/getToken.js'),
  message = require('./message.js');

// Vars
var _jar = request.jar(); // Default cookie jar

// Define
function makeCallbackArray(options,success,failure,always) {
  return {success: options.success || success, failure: options.failure || failure, always: options.always || options.callback || always};
}

module.exports.login = function(options,password,jar,success,failure,always) {
  var callbacks = makeCallbackArray(options,success,failure,always);
  if (typeof options == 'object') {
    var j = options.jar;
    return login((j ? j : _jar),options.username,options.password,callbacks);
  } else if (typeof options == 'string')
    return login((jar ? jar : _jar),options,password,callbacks);
};

module.exports.getSession = function(options) {
  if (options && options.hasOwnProperty('jar'))
    return getSession(options.jar);
  else
    return getSession(options || _jar);
};

module.exports.getCurrentUser = function(options,jar,success,failure,always) {
  var callbacks = makeCallbackArray(options,success,failure,always);
  if (typeof options == 'object') {
    var j = options.jar;
    return getCurrentUser((j ? j : _jar), options.option, callbacks);
  } else
    return getCurrentUser((jar ? jar : _jar), options, callbacks);
};

module.exports.getRoles = function(options,rank,success,failure,always) {
  var callbacks = makeCallbackArray(options,success,failure,always);
  if (typeof options == 'object')
    return getRoles(options.group, options.rank, callbacks);
  else
    return getRoles(options, rank, callbacks);
};

module.exports.getToken = function(options,jar,callback,failure) {
  var callbacks = {failure: options.failure || failure};
  if (typeof options == 'object') {
    var j = options.jar;
    return getToken((j ? j : _jar), options.url, callback, callbacks);
  } else
    return getToken((jar ? jar : _jar), options, callback, callbacks);
};

function setRankMain(options,target,roleset,token,jar,success,failure,always) {
  var callbacks = makeCallbackArray(options,success,failure,always);
  if (typeof options == 'object') {
    var j = options.jar;
    return setRank((j ? j : _jar), options.group, options.target, options.roleset, options.token, callbacks);
  } else
    return setRank((jar ? jar : _jar), options, target, roleset, token, callbacks);
}

module.exports.setRank = function(options) {
  if (options.rank) {
    getRoles(options.group,options.rank,function(role) {
      options.roleset = role;
      setRankMain(options);
    },options.failure,options.always);
  } else
    setRankMain.apply(undefined, arguments);
};

module.exports.message = function(options,subject,body,token,jar,success,failure,always) {
  var callbacks = makeCallbackArray(options,success,failure,always);
  if (typeof options == 'object') {
    var j = options.jar;
    return message((j ? j : _jar), options.recipient, options.subject, options.body, options.token, callbacks);
  } else
    return message((jar ? jar : _jar), options, subject, body, token, callbacks);
};

// Export
module.exports.getJar = function() {
    return _jar;
};
<|endoftext|>


<commit_before>var path = require('path');

var request = require('request');
var debug   = require('debug')('orchestrate');
var arg     = require('fn-arg');

var packagefile = require('./../package.json');

module.exports = Orchestrate;

function Orchestrate(token) {
    if(!(this instanceof Orchestrate)) {
        return new Orchestrate(token);
    }

    if(!token) {
        throw new Error('invalid token');
    }

    this.version = packagefile.version;
    this.token   = token;

    this.orchestrate_verion = 0;
    this.orchestrate_url    = 'https://api.orchestrate.io/';

    debug('#init', this);

    return this;
}

Orchestrate.prototype._request = function(url, opt, callback) {
    var self = this;

    opt = opt || {};

    opt.url = self.orchestrate_url + path.join('v' + self.orchestrate_verion, url || '/');

    opt.json = true;

    opt.auth = {
        user: self.token
    };

    opt.headers = {
        'User-Agent': 'orchestrate-native v' + self.version
    };

    debug('#_request', opt);

    request(opt, callback);
};

Orchestrate.prototype._handleParams = function(args) {
    debug('#_handleParams');

    var collection = args[0];
    var key        = args[1];
    var opt        = args[2];
    var callback   = args[3];

    switch(args.length) {
        case 2:
            callback = key;
            key = '';
            opt = {};
            break;

        case 3:
            if(typeof key === 'object') {
                callback = opt;
                opt = key;
                key = '';
            } else {
                callback = opt;
                opt = {};
            }
            break;

        default:
            break;
    }

    if(!collection || ['number', 'string'].indexOf(typeof key) === -1) {
        throw new Error('invalid params');
    }

    //to string
    collection = collection + '';
    key        = key + '';

    return {
        collection: collection,
        key:        key,
        opt:        opt,
        callback:   callback
    };
};

Orchestrate.prototype._makeUri = function(collection, key, suffix) {
    var self = this;

    debug('#_makeUri');

    return path.join(collection, key, suffix || '');
};

Orchestrate.prototype.ping = function(callback) {
    var self = this;

    debug('#ping');

    self._request(null, {
        method: 'HEAD'
    }, function(err, res, body) {
        if(err) {
            debug('#ping error', err);
            return callback(err);
        }

        if(res.statusCode !== 200) {
            debug('#ping error', res.headers);
            return callback('unauthorized', res.headers);
        }

        debug('#ping success');

        return callback(null, res.headers);
    });
};

Orchestrate.prototype.get = function(collection, key, opt, callback) {
    var self = this;

    debug('#get');

    /////////////////// optional params handler /////////////////
    var args = arg({
        2: ['collection', 'callback'],
        3: ['collection', 'key', 'callback'],
        4: ['collection', 'key', 'opt', 'callback']
    });

    if(!args) {
        throw new Error('invalid params');
    }

    collection = args.collection;
    key        = args.key;
    opt        = args.opt;
    callback   = args.callback;

    switch(Object.keys(args).length) {
        case 2:
            if(typeof args.collection === 'object') {
                collection = args.collection.collection;
                key        = args.collection.key;
                opt        = args.collection.opt;
                callback   = args.callback;
            }
            break;

        case 3:
            if(typeof args.key === 'object') {
                collection = args.collection;
                key        = null;
                opt        = args.key;
                callback   = args.callback;
            }
            break;

        default:
            break;
    }

    collection = collection ? collection + '' : collection;
    key        = key ? key + '' : '';
    opt        = opt ? opt : {};
    /////////////////// optional params handler /////////////////

    if(!collection || !callback) {
        throw new Error('invalid params');
    }

    var uri = self._makeUri(collection, key);

    self._request(uri, {
        qs: opt
    }, function(err, res, body) {
        if(err) {
            debug('#get error', err);
            return callback(err);
        }

        if(res.statusCode !== 200) {
            debug('#get error', body, res.headers);
            return callback(body, res.headers);
        }

        debug('#get success');

        return callback(null, body, res.headers);
    });
};

Orchestrate.prototype.post = function(collection, data, callback) {
    var self = this;

    debug('#post');

    /////////////////// optional params handler /////////////////
    var args = arg({
        2: ['collection', 'callback'],
        3: ['collection', 'data', 'callback']
    });

    if(!args) {
        throw new Error('invalid params');
    }

    collection = args.collection;
    data       = args.data;
    callback   = args.callback;

    switch(Object.keys(args).length) {
        case 2:
            if(typeof args.collection === 'object') {
                collection = args.collection.collection;
                data       = args.collection.data;
                callback   = args.callback;
            }
            break;

        default:
            break;
    }

    collection = collection ? collection + '' : collection;
    data       = data ? data : {};
    /////////////////// optional params handler /////////////////

    if(!collection) {
        throw new Error('invalid params');
    }

    var uri = collection;

    self._request(uri, {
        method: 'POST',
        body: data
    }, function(err, res, body) {
        if(err) {
            debug('#post error', err);
            return callback(err);
        }

        if(res.statusCode !== 201) {
            debug('#post error', body, res.headers);
            return callback(body, res.headers);
        }

        debug('#post success');

        return callback(null, res.headers);
    });
};

Orchestrate.prototype.put = function(collection, key, data, callback) {
    var self = this;

    debug('#put');

    /////////////////// optional params handler /////////////////
    var args = arg({
        2: ['collection', 'callback'],
        3: ['collection', 'key', 'callback'],
        4: ['collection', 'key', 'data', 'callback']
    });

    if(!args) {
        throw new Error('invalid params');
    }

    collection = args.collection;
    key        = args.key;
    data       = args.data;
    callback   = args.callback;

    switch(Object.keys(args).length) {
        case 2:
            if(typeof args.collection === 'object') {
                collection = args.collection.collection;
                key        = args.collection.key;
                data       = args.collection.data;
                callback   = args.callback;
            }
            break;

        case 3:
            if(typeof args.key === 'object') {
                collection = args.collection;
                key        = null;
                data       = args.key;
                callback   = args.callback;
            }
            break;

        default:
            break;
    }

    collection = collection ? collection + '' : collection;
    key        = key ? key + '' : key;
    data       = data ? data : {};
    /////////////////// optional params handler /////////////////

    if(!collection || !key) {
        throw new Error('invalid params');
    }

    var uri = path.join(collection, key);

    self._request(uri, {
        method: 'PUT',
        body: data
    }, function(err, res, body) {
        if(err) {
            debug('#put error', err);
            return callback(err);
        }

        if(res.statusCode !== 201) {
            debug('#put error', body || res.statusCode, res.headers);
            return callback(body || res.statusCode, res.headers);
        }

        debug('#put success');

        return callback(null, res.headers);
    });
};

Orchestrate.prototype.del = function(collection, key, opt, callback) {
    var self = this;

    debug('#del');

    /////////////////// optional params handler /////////////////
    var args = arg({
        2: ['collection', 'callback'],
        3: ['collection', 'key', 'callback'],
        4: ['collection', 'key', 'opt', 'callback']
    });

    if(!args) {
        throw new Error('invalid params');
    }

    collection = args.collection;
    key        = args.key;
    opt        = args.opt;
    callback   = args.callback;

    switch(Object.keys(args).length) {
        case 2:
            if(typeof args.collection === 'object') {
                collection = args.collection.collection;
                key        = args.collection.key;
                opt        = args.collection.opt;
                callback   = args.callback;
            }
            break;

        case 3:
            if(typeof args.key === 'object') {
                collection = args.collection;
                key        = null;
                opt        = args.key;
                callback   = args.callback;
            }
            break;

        default:
            break;
    }

    collection = collection ? collection + '' : collection;
    key        = key ? key + '' : '';
    opt        = opt ? opt : {};
    /////////////////// optional params handler /////////////////

    if(!collection) {
        throw new Error('invalid params');
    }

    var uri = path.join(collection, key);

    self._request(uri, {
        method: 'DELETE',
        qs: opt
    }, function(err, res, body) {
        if(err) {
            debug('#del error', err);
            return callback(err);
        }

        if(res.statusCode !== 204) {
            debug('#del error', body, res.headers);
            return callback(body, res.headers);
        }

        debug('#del success');

        return callback(null, res.headers);
    });
};<commit_msg>remove #_handleParams<commit_after>var path = require('path');

var request = require('request');
var debug   = require('debug')('orchestrate');
var arg     = require('fn-arg');

var packagefile = require('./../package.json');

module.exports = Orchestrate;

function Orchestrate(token) {
    if(!(this instanceof Orchestrate)) {
        return new Orchestrate(token);
    }

    if(!token) {
        throw new Error('invalid token');
    }

    this.version = packagefile.version;
    this.token   = token;

    this.orchestrate_verion = 0;
    this.orchestrate_url    = 'https://api.orchestrate.io/';

    debug('#init', this);

    return this;
}

Orchestrate.prototype._request = function(url, opt, callback) {
    var self = this;

    opt = opt || {};

    opt.url = self.orchestrate_url + path.join('v' + self.orchestrate_verion, url || '/');

    opt.json = true;

    opt.auth = {
        user: self.token
    };

    opt.headers = {
        'User-Agent': 'orchestrate-native v' + self.version
    };

    debug('#_request', opt);

    request(opt, callback);
};

Orchestrate.prototype._makeUri = function(collection, key, suffix) {
    var self = this;

    debug('#_makeUri');

    return path.join(collection, key, suffix || '');
};

Orchestrate.prototype.ping = function(callback) {
    var self = this;

    debug('#ping');

    self._request(null, {
        method: 'HEAD'
    }, function(err, res, body) {
        if(err) {
            debug('#ping error', err);
            return callback(err);
        }

        if(res.statusCode !== 200) {
            debug('#ping error', res.headers);
            return callback('unauthorized', res.headers);
        }

        debug('#ping success');

        return callback(null, res.headers);
    });
};

Orchestrate.prototype.get = function(collection, key, opt, callback) {
    var self = this;

    debug('#get');

    /////////////////// optional params handler /////////////////
    var args = arg({
        2: ['collection', 'callback'],
        3: ['collection', 'key', 'callback'],
        4: ['collection', 'key', 'opt', 'callback']
    });

    if(!args) {
        throw new Error('invalid params');
    }

    collection = args.collection;
    key        = args.key;
    opt        = args.opt;
    callback   = args.callback;

    switch(Object.keys(args).length) {
        case 2:
            if(typeof args.collection === 'object') {
                collection = args.collection.collection;
                key        = args.collection.key;
                opt        = args.collection.opt;
                callback   = args.callback;
            }
            break;

        case 3:
            if(typeof args.key === 'object') {
                collection = args.collection;
                key        = null;
                opt        = args.key;
                callback   = args.callback;
            }
            break;

        default:
            break;
    }

    collection = collection ? collection + '' : collection;
    key        = key ? key + '' : '';
    opt        = opt ? opt : {};
    /////////////////// optional params handler /////////////////

    if(!collection || !callback) {
        throw new Error('invalid params');
    }

    var uri = self._makeUri(collection, key);

    self._request(uri, {
        qs: opt
    }, function(err, res, body) {
        if(err) {
            debug('#get error', err);
            return callback(err);
        }

        if(res.statusCode !== 200) {
            debug('#get error', body, res.headers);
            return callback(body, res.headers);
        }

        debug('#get success');

        return callback(null, body, res.headers);
    });
};

Orchestrate.prototype.post = function(collection, data, callback) {
    var self = this;

    debug('#post');

    /////////////////// optional params handler /////////////////
    var args = arg({
        2: ['collection', 'callback'],
        3: ['collection', 'data', 'callback']
    });

    if(!args) {
        throw new Error('invalid params');
    }

    collection = args.collection;
    data       = args.data;
    callback   = args.callback;

    switch(Object.keys(args).length) {
        case 2:
            if(typeof args.collection === 'object') {
                collection = args.collection.collection;
                data       = args.collection.data;
                callback   = args.callback;
            }
            break;

        default:
            break;
    }

    collection = collection ? collection + '' : collection;
    data       = data ? data : {};
    /////////////////// optional params handler /////////////////

    if(!collection) {
        throw new Error('invalid params');
    }

    var uri = collection;

    self._request(uri, {
        method: 'POST',
        body: data
    }, function(err, res, body) {
        if(err) {
            debug('#post error', err);
            return callback(err);
        }

        if(res.statusCode !== 201) {
            debug('#post error', body, res.headers);
            return callback(body, res.headers);
        }

        debug('#post success');

        return callback(null, res.headers);
    });
};

Orchestrate.prototype.put = function(collection, key, data, callback) {
    var self = this;

    debug('#put');

    /////////////////// optional params handler /////////////////
    var args = arg({
        2: ['collection', 'callback'],
        3: ['collection', 'key', 'callback'],
        4: ['collection', 'key', 'data', 'callback']
    });

    if(!args) {
        throw new Error('invalid params');
    }

    collection = args.collection;
    key        = args.key;
    data       = args.data;
    callback   = args.callback;

    switch(Object.keys(args).length) {
        case 2:
            if(typeof args.collection === 'object') {
                collection = args.collection.collection;
                key        = args.collection.key;
                data       = args.collection.data;
                callback   = args.callback;
            }
            break;

        case 3:
            if(typeof args.key === 'object') {
                collection = args.collection;
                key        = null;
                data       = args.key;
                callback   = args.callback;
            }
            break;

        default:
            break;
    }

    collection = collection ? collection + '' : collection;
    key        = key ? key + '' : key;
    data       = data ? data : {};
    /////////////////// optional params handler /////////////////

    if(!collection || !key) {
        throw new Error('invalid params');
    }

    var uri = path.join(collection, key);

    self._request(uri, {
        method: 'PUT',
        body: data
    }, function(err, res, body) {
        if(err) {
            debug('#put error', err);
            return callback(err);
        }

        if(res.statusCode !== 201) {
            debug('#put error', body || res.statusCode, res.headers);
            return callback(body || res.statusCode, res.headers);
        }

        debug('#put success');

        return callback(null, res.headers);
    });
};

Orchestrate.prototype.del = function(collection, key, opt, callback) {
    var self = this;

    debug('#del');

    /////////////////// optional params handler /////////////////
    var args = arg({
        2: ['collection', 'callback'],
        3: ['collection', 'key', 'callback'],
        4: ['collection', 'key', 'opt', 'callback']
    });

    if(!args) {
        throw new Error('invalid params');
    }

    collection = args.collection;
    key        = args.key;
    opt        = args.opt;
    callback   = args.callback;

    switch(Object.keys(args).length) {
        case 2:
            if(typeof args.collection === 'object') {
                collection = args.collection.collection;
                key        = args.collection.key;
                opt        = args.collection.opt;
                callback   = args.callback;
            }
            break;

        case 3:
            if(typeof args.key === 'object') {
                collection = args.collection;
                key        = null;
                opt        = args.key;
                callback   = args.callback;
            }
            break;

        default:
            break;
    }

    collection = collection ? collection + '' : collection;
    key        = key ? key + '' : '';
    opt        = opt ? opt : {};
    /////////////////// optional params handler /////////////////

    if(!collection) {
        throw new Error('invalid params');
    }

    var uri = path.join(collection, key);

    self._request(uri, {
        method: 'DELETE',
        qs: opt
    }, function(err, res, body) {
        if(err) {
            debug('#del error', err);
            return callback(err);
        }

        if(res.statusCode !== 204) {
            debug('#del error', body, res.headers);
            return callback(body, res.headers);
        }

        debug('#del success');

        return callback(null, res.headers);
    });
};<|endoftext|>


<commit_before>module.exports = function () {
 var exports = {}

 exports.initialize = function (init) {
  var success = (typeof init.success != "undefined") ? init.success : function () {}
  var error   = (typeof init.error   != "undefined") ? init.error   : function () {}
  cordova.exec (success, error, "GooglePlayServices", "tryConnect", [])
 }

 exports.getPlayerId = function (init) {
  var success = (typeof init.success != "undefined") ? init.success : function () {}
  var error   = (typeof init.error   != "undefined") ? init.error   : function () {}
  cordova.exec (success, error, "GooglePlayServices", "getPlayerId", [])
 }

 exports.getAccessToken = function (init) {
  var success = (typeof init.success != "undefined") ? init.success : function () {}
  var error   = (typeof init.error   != "undefined") ? init.error   : function () {}
  cordova.exec (success, error, "GooglePlayServices", "getAccessToken", [])
 }

 return exports
} ()
<commit_msg>Update googleplayservices.js<commit_after>module.exports = function () {
 var exports = {}

 exports.initialize = function (init) {
  var init = init || {}
  var success = (typeof init.success != "undefined") ? init.success : function () {}
  var error   = (typeof init.error   != "undefined") ? init.error   : function () {}
  cordova.exec (success, error, "GooglePlayServices", "tryConnect", [])
 }

 exports.getPlayerId = function (init) {
  var init = init || {}
  var success = (typeof init.success != "undefined") ? init.success : function () {}
  var error   = (typeof init.error   != "undefined") ? init.error   : function () {}
  cordova.exec (success, error, "GooglePlayServices", "getPlayerId", [])
 }

 exports.getAccessToken = function (init) {
  var init = init || {}
  var success = (typeof init.success != "undefined") ? init.success : function () {}
  var error   = (typeof init.error   != "undefined") ? init.error   : function () {}
  cordova.exec (success, error, "GooglePlayServices", "getAccessToken", [])
 }

 return exports
} ()
<|endoftext|>