<commit_before>var crypto = require('crypto')
var stream = require('stream')
var fileType = require('file-type')
var parallel = require('run-parallel')

function staticValue (value) {
  return function (req, file, cb) {
    cb(null, value)
  }
}

var defaultAcl = staticValue('private')
var defaultContentType = staticValue('application/octet-stream')

var defaultMetadata = staticValue(null)
var defaultCacheControl = staticValue(null)
var defaultContentDisposition = staticValue(null)
var defaultStorageClass = staticValue('STANDARD')
var defaultSSE = staticValue(null)
var defaultSSEKMS = staticValue(null)

function defaultKey (req, file, cb) {
  crypto.randomBytes(16, function (err, raw) {
    cb(err, err ? undefined : raw.toString('hex'))
  })
}

function autoContentType (req, file, cb) {
  file.stream.once('data', function (firstChunk) {
    var type = fileType(firstChunk)
    var mime = (type === null ? 'application/octet-stream' : type.mime)
    var outStream = new stream.PassThrough()

    outStream.write(firstChunk)
    file.stream.pipe(outStream)

    cb(null, mime, outStream)
  })
}

function collect (storage, req, file, cb) {
  parallel([
    storage.getBucket.bind(storage, req, file),
    storage.getKey.bind(storage, req, file),
    storage.getAcl.bind(storage, req, file),
    storage.getMetadata.bind(storage, req, file),
    storage.getCacheControl.bind(storage, req, file),
    storage.getContentDisposition.bind(storage, req, file),
    storage.getStorageClass.bind(storage, req, file),
    storage.getSSE.bind(storage, req, file),
    storage.getSSEKMS.bind(storage, req, file)
  ], function (err, values) {
    if (err) return cb(err)

    storage.getContentType(req, file, function (err, contentType, replacementStream) {
      if (err) return cb(err)

      cb.call(storage, null, {
        bucket: values[0],
        key: values[1],
        acl: values[2],
        metadata: values[3],
        cacheControl: values[4],
        contentDisposition: values[5],
        storageClass: values[6],
        contentType: contentType,
        replacementStream: replacementStream,
        sse: values[7],
        sseKms: values[8]
      })
    })
  })
}

function S3Storage (opts) {
  switch (typeof opts.s3) {
    case 'object': this.s3 = opts.s3; break
    default: throw new TypeError('Expected opts.s3 to be object')
  }

  switch (typeof opts.bucket) {
    case 'function': this.getBucket = opts.bucket; break
    case 'string': this.getBucket = staticValue(opts.bucket); break
    case 'undefined': throw new Error('bucket is required')
    default: throw new TypeError('Expected opts.bucket to be undefined, string or function')
  }

  switch (typeof opts.key) {
    case 'function': this.getKey = opts.key; break
    case 'undefined': this.getKey = defaultKey; break
    default: throw new TypeError('Expected opts.key to be undefined or function')
  }

  switch (typeof opts.acl) {
    case 'function': this.getAcl = opts.acl; break
    case 'string': this.getAcl = staticValue(opts.acl); break
    case 'undefined': this.getAcl = defaultAcl; break
    default: throw new TypeError('Expected opts.acl to be undefined, string or function')
  }

  switch (typeof opts.contentType) {
    case 'function': this.getContentType = opts.contentType; break
    case 'undefined': this.getContentType = defaultContentType; break
    default: throw new TypeError('Expected opts.contentType to be undefined or function')
  }

  switch (typeof opts.metadata) {
    case 'function': this.getMetadata = opts.metadata; break
    case 'undefined': this.getMetadata = defaultMetadata; break
    default: throw new TypeError('Expected opts.metadata to be undefined or function')
  }

  switch (typeof opts.cacheControl) {
    case 'function': this.getCacheControl = opts.cacheControl; break
    case 'string': this.getCacheControl = staticValue(opts.cacheControl); break
    case 'undefined': this.getCacheControl = defaultCacheControl; break
    default: throw new TypeError('Expected opts.cacheControl to be undefined, string or function')
  }

  switch (typeof opts.contentDisposition) {
    case 'function': this.getContentDisposition = opts.contentDisposition; break
    case 'string': this.getContentDisposition = staticValue(opts.contentDisposition); break
    case 'undefined': this.getContentDisposition = defaultContentDisposition; break
    default: throw new TypeError('Expected opts.contentDisposition to be undefined, string or function')
  }

  switch (typeof opts.storageClass) {
    case 'function': this.getStorageClass = opts.storageClass; break
    case 'string': this.getStorageClass = staticValue(opts.storageClass); break
    case 'undefined': this.getStorageClass = defaultStorageClass; break
    default: throw new TypeError('Expected opts.storageClass to be undefined, string or function')
  }

  switch (typeof opts.sse) {
    case 'function': this.getSSE = opts.sse; break
    case 'string': this.getSSE = staticValue(opts.sse); break
    case 'undefined': this.getSSE = defaultSSE; break
    default: throw new TypeError('Expected opts.sse to be undefined, string or function')
  }

  switch (typeof opts.sseKms) {
    case 'function': this.getSSEKMS = opts.sseKms; break
    case 'string': this.getSSEKMS = opts.sseKms; break
    case 'undefined': this.getSSEKMS = defaultSSEKMS; break
    default: throw new TypeError('Expected opts.sseKms to be undefined, string, or function')
  }
}

S3Storage.prototype._handleFile = function (req, file, cb) {
  collect(this, req, file, function (err, opts) {
    if (err) return cb(err)

    var currentSize = 0

    var params = {
      Bucket: opts.bucket,
      Key: opts.key,
      ACL: opts.acl,
      CacheControl: opts.cacheControl,
      ContentType: opts.contentType,
      Metadata: opts.metadata,
      StorageClass: opts.storageClass,
      ServerSideEncryption: opts.sse,
      SSEKMSKeyId: opts.sseKms,
      Body: (opts.replacementStream || file.stream)
    }

    if (opts.contentDisposition) {
      params.ContentDisposition = opts.contentDisposition
    }

    var upload = this.s3.upload(params)

    upload.on('httpUploadProgress', function (ev) {
      if (ev.total) currentSize = ev.total
    })

    upload.send(function (err, result) {
      if (err) return cb(err)

      cb(null, {
        size: currentSize,
        bucket: opts.bucket,
        key: opts.key,
        acl: opts.acl,
        contentType: opts.contentType,
        contentDisposition: opts.contentDisposition,
        storageClass: opts.storageClass,
        serverSideEncryption: opts.sse,
        metadata: opts.metadata,
        location: result.Location,
        etag: result.ETag
      })
    })
  })
}

S3Storage.prototype._removeFile = function (req, file, cb) {
  this.s3.deleteObject({ Bucket: file.bucket, Key: file.key }, cb)
}

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

module.exports.AUTO_CONTENT_TYPE = autoContentType
module.exports.DEFAULT_CONTENT_TYPE = defaultContentType
<commit_msg>Fixed small error binding sseKms to static value<commit_after>var crypto = require('crypto')
var stream = require('stream')
var fileType = require('file-type')
var parallel = require('run-parallel')

function staticValue (value) {
  return function (req, file, cb) {
    cb(null, value)
  }
}

var defaultAcl = staticValue('private')
var defaultContentType = staticValue('application/octet-stream')

var defaultMetadata = staticValue(null)
var defaultCacheControl = staticValue(null)
var defaultContentDisposition = staticValue(null)
var defaultStorageClass = staticValue('STANDARD')
var defaultSSE = staticValue(null)
var defaultSSEKMS = staticValue(null)

function defaultKey (req, file, cb) {
  crypto.randomBytes(16, function (err, raw) {
    cb(err, err ? undefined : raw.toString('hex'))
  })
}

function autoContentType (req, file, cb) {
  file.stream.once('data', function (firstChunk) {
    var type = fileType(firstChunk)
    var mime = (type === null ? 'application/octet-stream' : type.mime)
    var outStream = new stream.PassThrough()

    outStream.write(firstChunk)
    file.stream.pipe(outStream)

    cb(null, mime, outStream)
  })
}

function collect (storage, req, file, cb) {
  parallel([
    storage.getBucket.bind(storage, req, file),
    storage.getKey.bind(storage, req, file),
    storage.getAcl.bind(storage, req, file),
    storage.getMetadata.bind(storage, req, file),
    storage.getCacheControl.bind(storage, req, file),
    storage.getContentDisposition.bind(storage, req, file),
    storage.getStorageClass.bind(storage, req, file),
    storage.getSSE.bind(storage, req, file),
    storage.getSSEKMS.bind(storage, req, file)
  ], function (err, values) {
    if (err) return cb(err)

    storage.getContentType(req, file, function (err, contentType, replacementStream) {
      if (err) return cb(err)

      cb.call(storage, null, {
        bucket: values[0],
        key: values[1],
        acl: values[2],
        metadata: values[3],
        cacheControl: values[4],
        contentDisposition: values[5],
        storageClass: values[6],
        contentType: contentType,
        replacementStream: replacementStream,
        sse: values[7],
        sseKms: values[8]
      })
    })
  })
}

function S3Storage (opts) {
  switch (typeof opts.s3) {
    case 'object': this.s3 = opts.s3; break
    default: throw new TypeError('Expected opts.s3 to be object')
  }

  switch (typeof opts.bucket) {
    case 'function': this.getBucket = opts.bucket; break
    case 'string': this.getBucket = staticValue(opts.bucket); break
    case 'undefined': throw new Error('bucket is required')
    default: throw new TypeError('Expected opts.bucket to be undefined, string or function')
  }

  switch (typeof opts.key) {
    case 'function': this.getKey = opts.key; break
    case 'undefined': this.getKey = defaultKey; break
    default: throw new TypeError('Expected opts.key to be undefined or function')
  }

  switch (typeof opts.acl) {
    case 'function': this.getAcl = opts.acl; break
    case 'string': this.getAcl = staticValue(opts.acl); break
    case 'undefined': this.getAcl = defaultAcl; break
    default: throw new TypeError('Expected opts.acl to be undefined, string or function')
  }

  switch (typeof opts.contentType) {
    case 'function': this.getContentType = opts.contentType; break
    case 'undefined': this.getContentType = defaultContentType; break
    default: throw new TypeError('Expected opts.contentType to be undefined or function')
  }

  switch (typeof opts.metadata) {
    case 'function': this.getMetadata = opts.metadata; break
    case 'undefined': this.getMetadata = defaultMetadata; break
    default: throw new TypeError('Expected opts.metadata to be undefined or function')
  }

  switch (typeof opts.cacheControl) {
    case 'function': this.getCacheControl = opts.cacheControl; break
    case 'string': this.getCacheControl = staticValue(opts.cacheControl); break
    case 'undefined': this.getCacheControl = defaultCacheControl; break
    default: throw new TypeError('Expected opts.cacheControl to be undefined, string or function')
  }

  switch (typeof opts.contentDisposition) {
    case 'function': this.getContentDisposition = opts.contentDisposition; break
    case 'string': this.getContentDisposition = staticValue(opts.contentDisposition); break
    case 'undefined': this.getContentDisposition = defaultContentDisposition; break
    default: throw new TypeError('Expected opts.contentDisposition to be undefined, string or function')
  }

  switch (typeof opts.storageClass) {
    case 'function': this.getStorageClass = opts.storageClass; break
    case 'string': this.getStorageClass = staticValue(opts.storageClass); break
    case 'undefined': this.getStorageClass = defaultStorageClass; break
    default: throw new TypeError('Expected opts.storageClass to be undefined, string or function')
  }

  switch (typeof opts.sse) {
    case 'function': this.getSSE = opts.sse; break
    case 'string': this.getSSE = staticValue(opts.sse); break
    case 'undefined': this.getSSE = defaultSSE; break
    default: throw new TypeError('Expected opts.sse to be undefined, string or function')
  }

  switch (typeof opts.sseKms) {
    case 'function': this.getSSEKMS = opts.sseKms; break
    case 'string': this.getSSEKMS = staticValue(opts.sseKms); break
    case 'undefined': this.getSSEKMS = defaultSSEKMS; break
    default: throw new TypeError('Expected opts.sseKms to be undefined, string, or function')
  }
}

S3Storage.prototype._handleFile = function (req, file, cb) {
  collect(this, req, file, function (err, opts) {
    if (err) return cb(err)

    var currentSize = 0

    var params = {
      Bucket: opts.bucket,
      Key: opts.key,
      ACL: opts.acl,
      CacheControl: opts.cacheControl,
      ContentType: opts.contentType,
      Metadata: opts.metadata,
      StorageClass: opts.storageClass,
      ServerSideEncryption: opts.sse,
      SSEKMSKeyId: opts.sseKms,
      Body: (opts.replacementStream || file.stream)
    }

    if (opts.contentDisposition) {
      params.ContentDisposition = opts.contentDisposition
    }

    var upload = this.s3.upload(params)

    upload.on('httpUploadProgress', function (ev) {
      if (ev.total) currentSize = ev.total
    })

    upload.send(function (err, result) {
      if (err) return cb(err)

      cb(null, {
        size: currentSize,
        bucket: opts.bucket,
        key: opts.key,
        acl: opts.acl,
        contentType: opts.contentType,
        contentDisposition: opts.contentDisposition,
        storageClass: opts.storageClass,
        serverSideEncryption: opts.sse,
        metadata: opts.metadata,
        location: result.Location,
        etag: result.ETag
      })
    })
  })
}

S3Storage.prototype._removeFile = function (req, file, cb) {
  this.s3.deleteObject({ Bucket: file.bucket, Key: file.key }, cb)
}

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

module.exports.AUTO_CONTENT_TYPE = autoContentType
module.exports.DEFAULT_CONTENT_TYPE = defaultContentType
<|endoftext|>


<commit_before>/*
 * index.js: Create an http AND/OR an https server and call the same request handler.
 *
 * (C) 2013, Charlie Robbins.
 *
 */

var fs = require('fs'),
    http = require('http'),
    https = require('https'),
    path = require('path'),
    connected = require('connected'),
    errs = require('errs');

//
// ### function createServers (dispatch, options, callback)
// Creates and listens on both HTTP and HTTPS servers.
//
module.exports = function createServers(options, listening) {
  if (!options || (!options.http && !options.https)
      || (!options.handler && !options.http.handler && !options.https.handler)) {
    return listening(new Error('handler, http and/or https are required options.'));
  }

  var handler = options.handler,
      log     = options.log || function () { },
      errors  = {},
      servers = {},
      errState;

  //
  // ### function onListen(type, err, server)
  // Responds to the `listening` callback if necessary
  // with the appropriate servers.
  //
  function onListen(type, err, server) {
    servers[type] = server || true;
    if (err) {
      errors[type] = err;
    }

    if (servers.http && servers.https) {
      Object.keys(servers)
        .forEach(function (key) {
          if (typeof servers[key] === 'boolean') {
            delete servers[key];
          }
        })

      if (errors.http || errors.https) {
        return listening(errs.create({
          https: errors.https,
          http:  errors.http,
        }), servers);
      }

      listening(undefined, servers);
    }
  }

  //
  // ### function createHttp ()
  // Attempts to create and listen on the the HTTP server.
  //
  function createHttp() {
    if (!options.http) {
      log('http | no options.http; no server')
      return onListen('http');
    }

    if (typeof options.http !== 'object') {
      options.http = {
        // accept both a string and a number
        port: !isNaN(options.http)
          ? +options.http
          : false
      };
    }

    var server = http.createServer(options.http.handler || handler),
        port   = options.http.port || 80,
        args,
        ip;

    args = [server, port];
    if (ip === options.http.ip) {
      args.push(ip);
    }

    log('http | try listen ' + port);
    args.push(function listener(err) { onListen('http', err, this); });
    connected.apply(null, args);
  }

  //
  // ### function createHttps ()
  // Attempts to create and listen on the HTTPS server.
  //
  function createHttps(next) {
    if (!options.https) {
      log('https | no options.https; no server')
      return onListen('https');
    }

    var port = +options.https.port || 443,
        ssl  = options.https,
        server,
        args,
        ip;

    if (ssl.ca && !Array.isArray(ssl.ca)) {
      ssl.ca = [ssl.ca];
    }

    log('https | listening on %d', port);
    server = https.createServer({
      key:  fs.readFileSync(path.join(ssl.root, ssl.key)),
      cert: fs.readFileSync(path.join(ssl.root, ssl.cert)),
      ca:   ssl.ca && ssl.ca.map(
        function (file) {
          return fs.readFileSync(path.join(ssl.root, file));
        }
      )
    }, ssl.handler || handler);

    args = [server, port];
    if (ip === options.https.ip) {
      args.push(ip);
    }

    args.push(function listener(err) { onListen('https', err, this); });
    connected.apply(null, args);
  }

  [createHttp, createHttps]
    .forEach(function (fn) { fn(); });
};<commit_msg>[minor] Use strict mode to capture potential issues.<commit_after>'use strict';

/*
 * index.js: Create an http AND/OR an https server and call the same request handler.
 *
 * (C) 2013, Charlie Robbins.
 *
 */

var fs = require('fs'),
    http = require('http'),
    https = require('https'),
    path = require('path'),
    connected = require('connected'),
    errs = require('errs');

//
// ### function createServers (dispatch, options, callback)
// Creates and listens on both HTTP and HTTPS servers.
//
module.exports = function createServers(options, listening) {
  if (!options || (!options.http && !options.https)
      || (!options.handler && !options.http.handler && !options.https.handler)) {
    return listening(new Error('handler, http and/or https are required options.'));
  }

  var handler = options.handler,
      log     = options.log || function () { },
      errors  = {},
      servers = {},
      errState;

  //
  // ### function onListen(type, err, server)
  // Responds to the `listening` callback if necessary
  // with the appropriate servers.
  //
  function onListen(type, err, server) {
    servers[type] = server || true;
    if (err) {
      errors[type] = err;
    }

    if (servers.http && servers.https) {
      Object.keys(servers)
        .forEach(function (key) {
          if (typeof servers[key] === 'boolean') {
            delete servers[key];
          }
        });

      if (errors.http || errors.https) {
        return listening(errs.create({
          https: errors.https,
          http:  errors.http,
        }), servers);
      }

      listening(undefined, servers);
    }
  }

  //
  // ### function createHttp ()
  // Attempts to create and listen on the the HTTP server.
  //
  function createHttp() {
    if (!options.http) {
      log('http | no options.http; no server');
      return onListen('http');
    }

    if (typeof options.http !== 'object') {
      options.http = {
        // accept both a string and a number
        port: !isNaN(options.http)
          ? +options.http
          : false
      };
    }

    var server = http.createServer(options.http.handler || handler),
        port   = options.http.port || 80,
        args,
        ip;

    args = [server, port];
    if (ip === options.http.ip) {
      args.push(ip);
    }

    log('http | try listen ' + port);
    args.push(function listener(err) { onListen('http', err, this); });
    connected.apply(null, args);
  }

  //
  // ### function createHttps ()
  // Attempts to create and listen on the HTTPS server.
  //
  function createHttps(next) {
    if (!options.https) {
      log('https | no options.https; no server');
      return onListen('https');
    }

    var port = +options.https.port || 443,
        ssl  = options.https,
        server,
        args,
        ip;

    if (ssl.ca && !Array.isArray(ssl.ca)) {
      ssl.ca = [ssl.ca];
    }

    log('https | listening on %d', port);
    server = https.createServer({
      key:  fs.readFileSync(path.join(ssl.root, ssl.key)),
      cert: fs.readFileSync(path.join(ssl.root, ssl.cert)),
      ca:   ssl.ca && ssl.ca.map(
        function (file) {
          return fs.readFileSync(path.join(ssl.root, file));
        }
      )
    }, ssl.handler || handler);

    args = [server, port];
    if (ip === options.https.ip) {
      args.push(ip);
    }

    args.push(function listener(err) { onListen('https', err, this); });
    connected.apply(null, args);
  }

  [createHttp, createHttps]
    .forEach(function (fn) { fn(); });
};
<|endoftext|>


<commit_before>'use strict'

// ===================================================================

var AnyPromise = require('any-promise')

// ===================================================================

function makeEventAdder (emitter, arrayArg) {
  var addListener =
    emitter.addEventListener ||
    emitter.addListener ||
    emitter.on

  if (!addListener) {
    throw new Error('cannot register an event listener')
  }

  var removeListener =
    emitter.removeEventListener ||
    emitter.removeListener ||
    emitter.off

  var eventsAndListeners = []

  var cleanUp = removeListener && function () {
    for (var i = 0, n = eventsAndListeners.length; i < n; i += 2) {
      removeListener.call(emitter, eventsAndListeners[i], eventsAndListeners[i + 1])
    }
  }

  return function (event, cb) {
    function listener () {
      cleanUp && cleanUp()

      var arg
      var n = arguments.length
      if (arrayArg) {
        arg = new Array(n)
        for (var i = 0; i < n; ++i) {
          arg[i] = arguments[i]
        }
        arg.event = event
      } else {
        arg = n > 0 ? arguments[0] : undefined
      }

      cb(arg)
    }

    eventsAndListeners.push(event, listener)
    addListener.call(emitter, event, listener)
  }
}

// ===================================================================

function eventToPromise (emitter, event, opts) {
  return new AnyPromise(function (resolve, reject) {
    var addEvent = makeEventAdder(emitter, opts && opts.array)

    addEvent(event, resolve)

    if (!opts || !opts.ignoreErrors) {
      addEvent(opts && opts.error || 'error', reject)
    }
  })
}

var defaultErrorEvents = [ 'error' ]
eventToPromise.multi = function eventsToPromise (emitter, successEvents, errorEvents) {
  errorEvents || (errorEvents = defaultErrorEvents)

  return new AnyPromise(function (resolve, reject) {
    var addEvent = makeEventAdder(emitter, true)

    var i, n
    for (i = 0, n = successEvents.length; i < n; ++i) {
      addEvent(successEvents[i], resolve)
    }
    for (i = 0, n = errorEvents.length; i < n; ++i) {
      addEvent(errorEvents[i], reject)
    }
  })
}

module.exports = eventToPromise
<commit_msg>promise.cancel(): removes all event listeners.<commit_after>'use strict'

// ===================================================================

var AnyPromise = require('any-promise')

// ===================================================================

function noop () {}

function makeEventAdder (emitter, arrayArg) {
  var addListener =
    emitter.addEventListener ||
    emitter.addListener ||
    emitter.on

  if (!addListener) {
    throw new Error('cannot register an event listener')
  }

  var removeListener =
    emitter.removeEventListener ||
    emitter.removeListener ||
    emitter.off

  var eventsAndListeners = []

  var cleanUp = removeListener
    ? function () {
      for (var i = 0, n = eventsAndListeners.length; i < n; i += 2) {
        removeListener.call(emitter, eventsAndListeners[i], eventsAndListeners[i + 1])
      }
    }
    : noop

  function addEvent (event, cb) {
    function listener () {
      cleanUp()

      var arg
      var n = arguments.length
      if (arrayArg) {
        arg = new Array(n)
        for (var i = 0; i < n; ++i) {
          arg[i] = arguments[i]
        }
        arg.event = event
      } else {
        arg = n > 0 ? arguments[0] : undefined
      }

      cb(arg)
    }

    eventsAndListeners.push(event, listener)
    addListener.call(emitter, event, listener)
  }
  addEvent.cleanUp = cleanUp

  return addEvent
}

// ===================================================================

function eventToPromise (emitter, event, opts) {
  var cancel
  var promise = new AnyPromise(function (resolve, reject) {
    var addEvent = makeEventAdder(emitter, opts && opts.array)
    cancel = function () {
      cancel = noop
      addEvent.cleanUp()
    }

    addEvent(event, resolve)

    if (!opts || !opts.ignoreErrors) {
      addEvent(opts && opts.error || 'error', reject)
    }
  })
  promise.cancel = function () { return cancel() }

  return promise
}

var defaultErrorEvents = [ 'error' ]
eventToPromise.multi = function eventsToPromise (emitter, successEvents, errorEvents) {
  errorEvents || (errorEvents = defaultErrorEvents)

  var cancel
  var promise = new AnyPromise(function (resolve, reject) {
    var addEvent = makeEventAdder(emitter, true)
    cancel = function () {
      cancel = noop
      addEvent.cleanUp()
    }

    var i, n
    for (i = 0, n = successEvents.length; i < n; ++i) {
      addEvent(successEvents[i], resolve)
    }
    for (i = 0, n = errorEvents.length; i < n; ++i) {
      addEvent(errorEvents[i], reject)
    }
  })
  promise.cancel = function () { return cancel() }

  return promise
}

module.exports = eventToPromise
<|endoftext|>


<commit_before>/* jshint node: true */
'use strict';

var path = require('path');
var mergeTrees = require('broccoli-merge-trees');

module.exports = {
  name: 'lodash',

  treeForAddon: function(tree) {
    var lodashPath = path.join(this.project.addonPackages['ember-lodash'].path, 'node_modules', 'lodash-es');
    var lodashTree = this.treeGenerator(lodashPath);

    var trees = mergeTrees([lodashTree, tree], {
      overwrite: true
    });

    return this._super.treeForAddon.call(this, trees);
  }
};
<commit_msg>Fix relative lookup<commit_after>/* jshint node: true */
'use strict';

var path = require('path');
var mergeTrees = require('broccoli-merge-trees');

module.exports = {
  name: 'lodash',

  treeForAddon: function(tree) {
    var lodashPath = path.dirname(require.resolve('lodash-es/lodash.js'));
    var lodashTree = this.treeGenerator(lodashPath);

    var trees = mergeTrees([lodashTree, tree], {
      overwrite: true
    });

    return this._super.treeForAddon.call(this, trees);
  }
};
<|endoftext|>


<commit_before>// From: http://stackoverflow.com/questions/6707476/how-to-find-if-text-contains-url-string
function replace(text)
    {
      var exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
      return $.trim( text.replace(exp,"").replace(/^RT/, "") );
    }

Template.IFeelT.helpers( {
	hasImage : function() {
		return _.isUndefined( Session.get("Image") ) == false;
	},
	ifeel : function() {
		var image = Session.get("Image");
		if( _.isUndefined( image ) ) {
			return;
		}
		return replace( image.text );
	},
	ifeeldate : function() {
		var image = Session.get("Image");
		if( _.isUndefined( image ) ) {
			return;
		}
		return moment(image.created_at).format('MMMM Do YYYY, h:mm:ss a'); new Date(  );
	},
	tweetURL : function() {
		var image = Session.get("Image");
		if( _.isUndefined( image ) ) {
			return;
		}
		var link = "https://twitter.com/" + image.screenName + "/status/" + image.id_str;
		return link;
	},
	screenName : function() {
		var image = Session.get("Image");
		if( _.isUndefined( image ) ) {
			return;
		}
		return "@" + image.screen_name;
	}
} );<commit_msg>Fix small bug<commit_after>// From: http://stackoverflow.com/questions/6707476/how-to-find-if-text-contains-url-string
function replace(text)
    {
      var exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
      return $.trim( text.replace(exp,"").replace(/^RT/, "") );
    }

Template.IFeelT.helpers( {
	hasImage : function() {
		return _.isUndefined( Session.get("Image") ) == false;
	},
	ifeel : function() {
		var image = Session.get("Image");
		if( _.isUndefined( image ) ) {
			return;
		}
		return replace( image.text );
	},
	ifeeldate : function() {
		var image = Session.get("Image");
		if( _.isUndefined( image ) ) {
			return;
		}
		return moment(image.created_at).format('MMMM Do YYYY, h:mm:ss a'); new Date(  );
	},
	tweetURL : function() {
		var image = Session.get("Image");
		if( _.isUndefined( image ) ) {
			return;
		}
		var link = "https://twitter.com/" + image.screen_name + "/status/" + image.id_str;
		return link;
	},
	screenName : function() {
		var image = Session.get("Image");
		if( _.isUndefined( image ) ) {
			return;
		}
		return "@" + image.screen_name;
	}
} );<|endoftext|>


<commit_before>/**
 * @module ol/source/TileJSON
 */
// FIXME check order of async callbacks

/**
 * @see http://mapbox.com/developers/api/
 */

import {createFromTemplates} from '../tileurlfunction.js';
import {assert} from '../asserts.js';
import {applyTransform, intersects} from '../extent.js';
import {jsonp as requestJSONP} from '../net.js';
import {get as getProjection, getTransformFromProjections} from '../proj.js';
import SourceState from '../source/State.js';
import TileImage from '../source/TileImage.js';
import {createXYZ, extentFromProjection} from '../tilegrid.js';

/**
 * @typedef {Object} Options
 * @property {module:ol/source/Source~AttributionLike} [attributions] Attributions.
 * @property {number} [cacheSize=2048] Cache size.
 * @property {null|string} [crossOrigin] The `crossOrigin` attribute for loaded images.  Note that
 * you must provide a `crossOrigin` value if you are using the WebGL renderer or if you want to
 * access pixel data with the Canvas renderer.  See
 * {@link https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image} for more detail.
 * @property {boolean} [jsonp=false] Use JSONP with callback to load the TileJSON.
 * Useful when the server does not support CORS..
 * @property {boolean} [reprojectionErrorThreshold=0.5] Maximum allowed reprojection error (in pixels).
 * Higher values can increase reprojection performance, but decrease precision.
 * @property {tileJSON} [tileJSON] TileJSON configuration for this source.
 * If not provided, `url` must be configured.
 * @property {module:ol/Tile~LoadFunction} [tileLoadFunction] Optional function to load a tile given a URL. The default is
 * ```js
 * function(imageTile, src) {
 *   imageTile.getImage().src = src;
 * };
 * ```
 * @property {string} [url] URL to the TileJSON file. If not provided, `tileJSON` must be configured.
 * @property {boolean} [wrapX=true] Whether to wrap the world horizontally.
 * @property {number} [transition] Duration of the opacity transition for rendering.
 * To disable the opacity transition, pass `transition: 0`.
 */

class TileJSON extends TileImage {
  /**
   * @classdesc
   * Layer source for tile data in TileJSON format.
   *
   * @param {module:ol/source/TileJSON~Options=} options TileJSON options.
   * @api
   */
  constructor(options) {

    /**
     * @type {TileJSON}
     * @private
     */
    this.tileJSON_ = null;

    super({
      attributions: options.attributions,
      cacheSize: options.cacheSize,
      crossOrigin: options.crossOrigin,
      projection: getProjection('EPSG:3857'),
      reprojectionErrorThreshold: options.reprojectionErrorThreshold,
      state: SourceState.LOADING,
      tileLoadFunction: options.tileLoadFunction,
      wrapX: options.wrapX !== undefined ? options.wrapX : true,
      transition: options.transition
    });

    if (options.url) {
      if (options.jsonp) {
        requestJSONP(options.url, this.handleTileJSONResponse.bind(this),
          this.handleTileJSONError.bind(this));
      } else {
        const client = new XMLHttpRequest();
        client.addEventListener('load', this.onXHRLoad_.bind(this));
        client.addEventListener('error', this.onXHRError_.bind(this));
        client.open('GET', options.url);
        client.send();
      }
    } else if (options.tileJSON) {
      this.handleTileJSONResponse(options.tileJSON);
    } else {
      assert(false, 51); // Either `url` or `tileJSON` options must be provided
    }

  }

  /**
   * @private
   * @param {Event} event The load event.
   */
  onXHRLoad_(event) {
    const client = /** @type {XMLHttpRequest} */ (event.target);
    // status will be 0 for file:// urls
    if (!client.status || client.status >= 200 && client.status < 300) {
      let response;
      try {
        response = /** @type {TileJSON} */(JSON.parse(client.responseText));
      } catch (err) {
        this.handleTileJSONError();
        return;
      }
      this.handleTileJSONResponse(response);
    } else {
      this.handleTileJSONError();
    }
  }

  /**
   * @private
   * @param {Event} event The error event.
   */
  onXHRError_(event) {
    this.handleTileJSONError();
  }

  /**
   * @return {TileJSON} The tilejson object.
   * @api
   */
  getTileJSON() {
    return this.tileJSON_;
  }

  /**
   * @protected
   * @param {TileJSON} tileJSON Tile JSON.
   */
  handleTileJSONResponse(tileJSON) {

    const epsg4326Projection = getProjection('EPSG:4326');

    const sourceProjection = this.getProjection();
    let extent;
    if (tileJSON.bounds !== undefined) {
      const transform = getTransformFromProjections(
        epsg4326Projection, sourceProjection);
      extent = applyTransform(tileJSON.bounds, transform);
    }

    const minZoom = tileJSON.minzoom || 0;
    const maxZoom = tileJSON.maxzoom || 22;
    const tileGrid = createXYZ({
      extent: extentFromProjection(sourceProjection),
      maxZoom: maxZoom,
      minZoom: minZoom
    });
    this.tileGrid = tileGrid;

    this.tileUrlFunction = createFromTemplates(tileJSON.tiles, tileGrid);

    if (tileJSON.attribution !== undefined && !this.getAttributions()) {
      const attributionExtent = extent !== undefined ?
        extent : epsg4326Projection.getExtent();

      this.setAttributions(function(frameState) {
        if (intersects(attributionExtent, frameState.extent)) {
          return [tileJSON.attribution];
        }
        return null;
      });

    }
    this.tileJSON_ = tileJSON;
    this.setState(SourceState.READY);

  }

  /**
   * @protected
   */
  handleTileJSONError() {
    this.setState(SourceState.ERROR);
  }
}

export default TileJSON;
<commit_msg>Super before this in TileJSON source<commit_after>/**
 * @module ol/source/TileJSON
 */
// FIXME check order of async callbacks

/**
 * @see http://mapbox.com/developers/api/
 */

import {createFromTemplates} from '../tileurlfunction.js';
import {assert} from '../asserts.js';
import {applyTransform, intersects} from '../extent.js';
import {jsonp as requestJSONP} from '../net.js';
import {get as getProjection, getTransformFromProjections} from '../proj.js';
import SourceState from '../source/State.js';
import TileImage from '../source/TileImage.js';
import {createXYZ, extentFromProjection} from '../tilegrid.js';

/**
 * @typedef {Object} Options
 * @property {module:ol/source/Source~AttributionLike} [attributions] Attributions.
 * @property {number} [cacheSize=2048] Cache size.
 * @property {null|string} [crossOrigin] The `crossOrigin` attribute for loaded images.  Note that
 * you must provide a `crossOrigin` value if you are using the WebGL renderer or if you want to
 * access pixel data with the Canvas renderer.  See
 * {@link https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image} for more detail.
 * @property {boolean} [jsonp=false] Use JSONP with callback to load the TileJSON.
 * Useful when the server does not support CORS..
 * @property {boolean} [reprojectionErrorThreshold=0.5] Maximum allowed reprojection error (in pixels).
 * Higher values can increase reprojection performance, but decrease precision.
 * @property {tileJSON} [tileJSON] TileJSON configuration for this source.
 * If not provided, `url` must be configured.
 * @property {module:ol/Tile~LoadFunction} [tileLoadFunction] Optional function to load a tile given a URL. The default is
 * ```js
 * function(imageTile, src) {
 *   imageTile.getImage().src = src;
 * };
 * ```
 * @property {string} [url] URL to the TileJSON file. If not provided, `tileJSON` must be configured.
 * @property {boolean} [wrapX=true] Whether to wrap the world horizontally.
 * @property {number} [transition] Duration of the opacity transition for rendering.
 * To disable the opacity transition, pass `transition: 0`.
 */

class TileJSON extends TileImage {
  /**
   * @classdesc
   * Layer source for tile data in TileJSON format.
   *
   * @param {module:ol/source/TileJSON~Options=} options TileJSON options.
   * @api
   */
  constructor(options) {
    super({
      attributions: options.attributions,
      cacheSize: options.cacheSize,
      crossOrigin: options.crossOrigin,
      projection: getProjection('EPSG:3857'),
      reprojectionErrorThreshold: options.reprojectionErrorThreshold,
      state: SourceState.LOADING,
      tileLoadFunction: options.tileLoadFunction,
      wrapX: options.wrapX !== undefined ? options.wrapX : true,
      transition: options.transition
    });

    /**
     * @type {TileJSON}
     * @private
     */
    this.tileJSON_ = null;

    if (options.url) {
      if (options.jsonp) {
        requestJSONP(options.url, this.handleTileJSONResponse.bind(this),
          this.handleTileJSONError.bind(this));
      } else {
        const client = new XMLHttpRequest();
        client.addEventListener('load', this.onXHRLoad_.bind(this));
        client.addEventListener('error', this.onXHRError_.bind(this));
        client.open('GET', options.url);
        client.send();
      }
    } else if (options.tileJSON) {
      this.handleTileJSONResponse(options.tileJSON);
    } else {
      assert(false, 51); // Either `url` or `tileJSON` options must be provided
    }

  }

  /**
   * @private
   * @param {Event} event The load event.
   */
  onXHRLoad_(event) {
    const client = /** @type {XMLHttpRequest} */ (event.target);
    // status will be 0 for file:// urls
    if (!client.status || client.status >= 200 && client.status < 300) {
      let response;
      try {
        response = /** @type {TileJSON} */(JSON.parse(client.responseText));
      } catch (err) {
        this.handleTileJSONError();
        return;
      }
      this.handleTileJSONResponse(response);
    } else {
      this.handleTileJSONError();
    }
  }

  /**
   * @private
   * @param {Event} event The error event.
   */
  onXHRError_(event) {
    this.handleTileJSONError();
  }

  /**
   * @return {TileJSON} The tilejson object.
   * @api
   */
  getTileJSON() {
    return this.tileJSON_;
  }

  /**
   * @protected
   * @param {TileJSON} tileJSON Tile JSON.
   */
  handleTileJSONResponse(tileJSON) {

    const epsg4326Projection = getProjection('EPSG:4326');

    const sourceProjection = this.getProjection();
    let extent;
    if (tileJSON.bounds !== undefined) {
      const transform = getTransformFromProjections(
        epsg4326Projection, sourceProjection);
      extent = applyTransform(tileJSON.bounds, transform);
    }

    const minZoom = tileJSON.minzoom || 0;
    const maxZoom = tileJSON.maxzoom || 22;
    const tileGrid = createXYZ({
      extent: extentFromProjection(sourceProjection),
      maxZoom: maxZoom,
      minZoom: minZoom
    });
    this.tileGrid = tileGrid;

    this.tileUrlFunction = createFromTemplates(tileJSON.tiles, tileGrid);

    if (tileJSON.attribution !== undefined && !this.getAttributions()) {
      const attributionExtent = extent !== undefined ?
        extent : epsg4326Projection.getExtent();

      this.setAttributions(function(frameState) {
        if (intersects(attributionExtent, frameState.extent)) {
          return [tileJSON.attribution];
        }
        return null;
      });

    }
    this.tileJSON_ = tileJSON;
    this.setState(SourceState.READY);

  }

  /**
   * @protected
   */
  handleTileJSONError() {
    this.setState(SourceState.ERROR);
  }
}

export default TileJSON;
<|endoftext|>


<commit_before>'use strict'

const amqp = require('amqp')
const uuid = require('node-uuid').v4
const os = require('os')
const debug = require('debug')('qpc')
const memoize = require('memoizee')

function noop() {}

function Rpc(opt) {
  opt = opt || {}

  this._conn = opt.connection
  this._url = opt.url || 'amqp://guest:guest@localhost:5672'
  this._exchange = opt.exchangeInstance
  this._exchangeName = opt.exchange || 'rpc_exchange'
  this._exchangeOptions = opt.exchangeOptions || {
    exclusive: false,
    autoDelete: true,
  }
  this._implOptions = opt.ipmlOptions || {
    defaultExchangeName: this._exchangeName,
  }
  this._connOptions = opt.connOptions || {}

  this._resultsQueue = null
  this._resultsQueueName = null
  this._resultsCallback = {}

  this._cmds = {}

  this._connect = memoize(function(cb) {
    let options = this._connOptions
    if (!options.url && !options.host) {
      options.url = this._url
    }

    debug('createConnection options=', options,
      ', ipmlOptions=', this._implOptions || {})
    this._conn = amqp.createConnection(options, this._implOptions)

    this._conn.on('ready', () => {
      debug('connected to ' + this._conn.serverProperties.product)
      cb(this._conn)
    })
  }, { async: true })

  this._makeExchange = memoize(function(cb) {
    /*
     * Added option autoDelete=false.
     * Otherwise we had an error in library node-amqp version > 0.1.7.
     * Text of such error: "PRECONDITION_FAILED - cannot redeclare
     *  exchange '<exchange name>' in vhost '/' with different type,
     *  durable, internal or autodelete value"
     */
    this._exchange = this._conn.exchange(this._exchangeName, {
      autoDelete: false,
    }, exchange => {
      debug('Exchange ' + exchange.name + ' is open')
      cb(this._exchange)
    })
  }, { async: true })

  this._makeResultsQueue = memoize(function(cb) {
    this._resultsQueueName = this.generateQueueName('callback')

    this._makeExchange(() =>
      this._resultsQueue = this._conn.queue(
        this._resultsQueueName,
        this._exchangeOptions,
        queue => {
          debug('Callback queue ' + queue.name + ' is open')
          queue.subscribe(this._onResult.bind(this))

          queue.bind(this._exchange, this._resultsQueueName)
          debug('Bind queue ' + queue.name +
            ' to exchange ' + this._exchange.name)
          cb()
        }
      )
    )
  }, { async: true })
}

/**
 * generate unique name for new queue
 *
 * @returns {string}
 */

Rpc.prototype.generateQueueName = function(type) {
  return os.hostname() + ':pid' + process.pid + ':' + type + ':' +
    Math.random().toString(16).split('.')[1]
}

/**
 * disconnect from MQ broker
 */
Rpc.prototype.disconnect = function() {
  debug('disconnect()')
  if (!this._conn) return

  this._conn.end()
  this._conn = null
}

Rpc.prototype._onResult = function(message, headers, deliveryInfo) {
  debug('_onResult()')
  if (!this._resultsCallback[deliveryInfo.correlationId]) {
    return
  }

  let cb = this._resultsCallback[deliveryInfo.correlationId]

  let args = [].concat(message)

  cb.cb.apply(cb.context, args)

  if (cb.autoDeleteCallback !== false) {
    delete this._resultsCallback[deliveryInfo.correlationId]
  }
}

/**
 * call a remote command
 *
 * @param {string} cmd   command name
 * @param {Buffer|Object|String}params    parameters of command
 * @param {function} cb        callback
 * @param {object} context   context of callback
 * @param {object} options   advanced options of amqp
 */

Rpc.prototype.call = function(cmd, params, cb, context, options) {
  debug('call()', cmd)

  options = options || {}

  options.contentType = 'application/json'
  let corrId = options.correlationId || uuid()

  this._connect(() => {
    if (!cb) {
      this._createQ(cmd, () => this._exchange.publish(cmd, params, options))
      return
    }

    this._makeExchange(() =>
      this._makeResultsQueue(() => {
        this._resultsCallback[corrId] = {
          cb,
          context,
          autoDeleteCallback: !!options.autoDeleteCallback,
        }

        options.mandatory = true
        options.replyTo = this._resultsQueueName
        options.correlationId = corrId
        //options.domain    = "localhost"

        this._exchange.publish(cmd, params, options, err => {
          if (err) {
            delete this._resultsCallback[corrId]

            cb(err)
          }
        })
      })
    )
  })

  return corrId
}

Rpc.prototype._createQ = memoize(function(qname, cb) {
  this._connect(() => this._conn.queue(qname, queue => {
    this._makeExchange(() => {
      queue.bind(this._exchange, qname, () => cb(queue))
    })
  }))
}, { async: true })

/**
 * add new command handler
 * @param {string} cmd                command name or match string
 * @param {function} cb               handler
 * @param {object} context            context for handler
 * @param {object} options            advanced options
 * @param {string} options.queueName  name of queue. Default equal to "cmd" parameter
 * @param {boolean} options.durable   If true, the queue will be marked as durable.
 *                                    Durable queues remain active when a server restarts.
 *                                    Non-durable queues (transient queues) are purged if/when a server restarts.
 *                                    Note that durable queues do not necessarily hold persistent messages,
 *                                    although it does not make sense to send persistent messages to a transient queue.

 * @param {boolean} options.exclusive Exclusive queues may only be accessed by the current connection,
 *                                    and are deleted when that connection closes.
 * @param {boolean} options.autoDelete If true, the queue is deleted when all consumers have finished using it.
 *                                     The last consumer can be cancelled either explicitly or because its channel is closed.
 *                                     If there was no consumer ever on the queue, it won't be deleted. Applications
 *                                     can explicitly delete auto-delete queues using the Delete method as normal.
 * @return {boolean}
 */
Rpc.prototype.on = function(cmd, cb, context, options) {
  debug('on(), routingKey=%s', cmd)
  if (this._cmds[cmd]) {
    return false
  }

  this._createQ(cmd, queue => {
    this._cmds[cmd] = { queue }
    queue.subscribe((message, d, headers, deliveryInfo) => {
      let cmdInfo = {
        cmd: deliveryInfo.routingKey,
        exchange: deliveryInfo.exchange,
        contentType: deliveryInfo.contentType,
        size: deliveryInfo.size,
      }

      if (deliveryInfo.correlationId && deliveryInfo.replyTo) {
        return cb.call(context, message, function(err, data) {
          let options = {
            correlationId: deliveryInfo.correlationId,
          }

          this._exchange.publish(
            deliveryInfo.replyTo,
            Array.prototype.slice.call(arguments),
            options
          )
        }.bind(this), cmdInfo)
      }

      return cb.call(context, message, noop, cmdInfo)
    })
  })

  return true
}

/**
 * remove command handler added with "on" method
 *
 * @param {string} cmd       command or match string
 * @return {boolean}
 */
Rpc.prototype.off = function(cmd) {
  debug('off', cmd)
  if (!this._cmds[cmd]) {
    return false
  }

  let c = this._cmds[cmd]

  function unsubscribe(cb) {
    if (c.ctag) {
      c.queue.unsubscribe(c.ctag)
    }

    if (cb) {
      return cb()
    }
  }

  let unbind = cb => {
    if (c.queue) {
      unsubscribe(() => {
        c.queue.unbind(this._exchange, cmd)

        if (cb) {
          return cb()
        }
      })
    }
  }

  function destroy(cb) {
    if (c.queue) {
      unbind(() => {
        c.queue.destroy()

        if (cb) {
          return cb()
        }
      })
    }
  }

  destroy(() => delete this._cmds[cmd])

  return true
}

module.exports = Rpc
<commit_msg>Context input params removed<commit_after>'use strict'

const amqp = require('amqp')
const uuid = require('node-uuid').v4
const os = require('os')
const debug = require('debug')('qpc')
const memoize = require('memoizee')

function noop() {}

function Rpc(opt) {
  opt = opt || {}

  this._conn = opt.connection
  this._url = opt.url || 'amqp://guest:guest@localhost:5672'
  this._exchange = opt.exchangeInstance
  this._exchangeName = opt.exchange || 'rpc_exchange'
  this._exchangeOptions = opt.exchangeOptions || {
    exclusive: false,
    autoDelete: true,
  }
  this._implOptions = opt.ipmlOptions || {
    defaultExchangeName: this._exchangeName,
  }
  this._connOptions = opt.connOptions || {}

  this._resultsQueue = null
  this._resultsQueueName = null
  this._resultsCallback = {}

  this._cmds = {}

  this._connect = memoize(function(cb) {
    let options = this._connOptions
    if (!options.url && !options.host) {
      options.url = this._url
    }

    debug('createConnection options=', options,
      ', ipmlOptions=', this._implOptions || {})
    this._conn = amqp.createConnection(options, this._implOptions)

    this._conn.on('ready', () => {
      debug('connected to ' + this._conn.serverProperties.product)
      cb(this._conn)
    })
  }, { async: true })

  this._makeExchange = memoize(function(cb) {
    /*
     * Added option autoDelete=false.
     * Otherwise we had an error in library node-amqp version > 0.1.7.
     * Text of such error: "PRECONDITION_FAILED - cannot redeclare
     *  exchange '<exchange name>' in vhost '/' with different type,
     *  durable, internal or autodelete value"
     */
    this._exchange = this._conn.exchange(this._exchangeName, {
      autoDelete: false,
    }, exchange => {
      debug('Exchange ' + exchange.name + ' is open')
      cb(this._exchange)
    })
  }, { async: true })

  this._makeResultsQueue = memoize(function(cb) {
    this._resultsQueueName = this.generateQueueName('callback')

    this._makeExchange(() =>
      this._resultsQueue = this._conn.queue(
        this._resultsQueueName,
        this._exchangeOptions,
        queue => {
          debug('Callback queue ' + queue.name + ' is open')
          queue.subscribe(this._onResult.bind(this))

          queue.bind(this._exchange, this._resultsQueueName)
          debug('Bind queue ' + queue.name +
            ' to exchange ' + this._exchange.name)
          cb()
        }
      )
    )
  }, { async: true })
}

/**
 * generate unique name for new queue
 *
 * @returns {string}
 */

Rpc.prototype.generateQueueName = function(type) {
  return os.hostname() + ':pid' + process.pid + ':' + type + ':' +
    Math.random().toString(16).split('.')[1]
}

/**
 * disconnect from MQ broker
 */
Rpc.prototype.disconnect = function() {
  debug('disconnect()')
  if (!this._conn) return

  this._conn.end()
  this._conn = null
}

Rpc.prototype._onResult = function(message, headers, deliveryInfo) {
  debug('_onResult()')
  if (!this._resultsCallback[deliveryInfo.correlationId]) {
    return
  }

  let cb = this._resultsCallback[deliveryInfo.correlationId]

  let args = [].concat(message)

  cb.cb(...args)

  if (cb.autoDeleteCallback !== false) {
    delete this._resultsCallback[deliveryInfo.correlationId]
  }
}

/**
 * call a remote command
 *
 * @param {string} cmd   command name
 * @param {Buffer|Object|String}params    parameters of command
 * @param {function} cb        callback
 * @param {object} options   advanced options of amqp
 */
Rpc.prototype.call = function(cmd, params, cb, options) {
  debug('call()', cmd)

  options = options || {}

  options.contentType = 'application/json'
  let corrId = options.correlationId || uuid()

  this._connect(() => {
    if (!cb) {
      this._createQ(cmd, () => this._exchange.publish(cmd, params, options))
      return
    }

    this._makeExchange(() =>
      this._makeResultsQueue(() => {
        this._resultsCallback[corrId] = {
          cb,
          autoDeleteCallback: !!options.autoDeleteCallback,
        }

        options.mandatory = true
        options.replyTo = this._resultsQueueName
        options.correlationId = corrId
        //options.domain    = "localhost"

        this._exchange.publish(cmd, params, options, err => {
          if (err) {
            delete this._resultsCallback[corrId]

            cb(err)
          }
        })
      })
    )
  })

  return corrId
}

Rpc.prototype._createQ = memoize(function(qname, cb) {
  this._connect(() => this._conn.queue(qname, queue => {
    this._makeExchange(() => {
      queue.bind(this._exchange, qname, () => cb(queue))
    })
  }))
}, { async: true })

/**
 * add new command handler
 * @param {string} cmd                command name or match string
 * @param {function} cb               handler
 * @param {object} options            advanced options
 * @param {string} options.queueName  name of queue. Default equal to "cmd" parameter
 * @param {boolean} options.durable   If true, the queue will be marked as durable.
 *                                    Durable queues remain active when a server restarts.
 *                                    Non-durable queues (transient queues) are purged if/when a server restarts.
 *                                    Note that durable queues do not necessarily hold persistent messages,
 *                                    although it does not make sense to send persistent messages to a transient queue.

 * @param {boolean} options.exclusive Exclusive queues may only be accessed by the current connection,
 *                                    and are deleted when that connection closes.
 * @param {boolean} options.autoDelete If true, the queue is deleted when all consumers have finished using it.
 *                                     The last consumer can be cancelled either explicitly or because its channel is closed.
 *                                     If there was no consumer ever on the queue, it won't be deleted. Applications
 *                                     can explicitly delete auto-delete queues using the Delete method as normal.
 * @return {boolean}
 */
Rpc.prototype.on = function(cmd, cb, options) {
  debug('on(), routingKey=%s', cmd)
  if (this._cmds[cmd]) {
    return false
  }

  this._createQ(cmd, queue => {
    this._cmds[cmd] = { queue }
    queue.subscribe((message, d, headers, deliveryInfo) => {
      let cmdInfo = {
        cmd: deliveryInfo.routingKey,
        exchange: deliveryInfo.exchange,
        contentType: deliveryInfo.contentType,
        size: deliveryInfo.size,
      }

      if (deliveryInfo.correlationId && deliveryInfo.replyTo) {
        return cb(message, function() {
          let options = {
            correlationId: deliveryInfo.correlationId,
          }

          this._exchange.publish(
            deliveryInfo.replyTo,
            Array.prototype.slice.call(arguments),
            options
          )
        }.bind(this), cmdInfo)
      }

      return cb(message, noop, cmdInfo)
    })
  })

  return true
}

/**
 * remove command handler added with "on" method
 *
 * @param {string} cmd       command or match string
 * @return {boolean}
 */
Rpc.prototype.off = function(cmd) {
  debug('off', cmd)
  if (!this._cmds[cmd]) {
    return false
  }

  let c = this._cmds[cmd]

  function unsubscribe(cb) {
    if (c.ctag) {
      c.queue.unsubscribe(c.ctag)
    }

    if (cb) {
      return cb()
    }
  }

  let unbind = cb => {
    if (c.queue) {
      unsubscribe(() => {
        c.queue.unbind(this._exchange, cmd)

        if (cb) {
          return cb()
        }
      })
    }
  }

  function destroy(cb) {
    if (c.queue) {
      unbind(() => {
        c.queue.destroy()

        if (cb) {
          return cb()
        }
      })
    }
  }

  destroy(() => delete this._cmds[cmd])

  return true
}

module.exports = Rpc
<|endoftext|>


<commit_before>const BASEURL = 'https://dynasty-scans.com'

const fs = require('fs')
const https = require('https')
const cheerio = require('cheerio')
const path = require('path')
const pdfkit = require('pdfkit')
const imageSize = require('imagesize')
const progress = require('progress')

const PNG = require('pngjs').PNG

var emulated = ''.split(' ')

const argv = require('commander')
	.version(require('./package.json').version)
	.arguments('<url>')
	.description('Simple tool for batch-downloading from Dynasty-Scans. Supports also PDF saving as well as chapter selection.')
	.option('-c, --chapters <a>-<b>', 'Chapter range.')
	.option('-C, --listChapters', 'List all chapters with correct indexes.')
	.option('-o, --output [path]', 'Different output path, defaults to current working directory.')
	.option('-p, --pdf', 'Downloads pdf instead of seperated images.')
	.option('-n, --noconvert', 'Skips PNG to PDF coversion.')
	.option('-v, --verbose', 'Includes progressbar for each GET request.')
	.parse(emulated || process.argv)

if(!argv.args[0]) argv.help()

var config = {
	pdf: argv.pdf,
	outputDir: path.resolve(argv.output || process.cwd())
}

parseManga({
	url: argv.args[0],
	isSeries: argv.args[0].includes('series'),
	chapters: argv.chapters
})

async function parseManga(manga){
	if(manga.isSeries){
		var sBody = cheerio.load(await get(manga.url)), cPath = config.outputDir+'/', doc

		console.log(`\n  ${sBody('.tag-title > b').text()}`)

		var mangaInfo = {
			title: legalize(sBody('.tag-title > b').text()),
			chapters: sBody('a.name').map((i, url) => {
				return {
					url: BASEURL+url.attribs.href,
					name: url.children[0].data
				}
			}).toArray()
		}

		if(argv.listChapters){
			for(var i = 0; i < mangaInfo.chapters.length; i++){
				console.log(`  ${i}: ${mangaInfo.chapters[i].name}`)
			}
			process.exit(0)
		}

		//slice chapters that are needed and stuff
		if(manga.chapters){
			let selection = argv.chapters.split('-')
			if(selection.length == 1){
				mangaInfo.chapters = [mangaInfo.chapters[selection[0]]]
			}else if(selection.length == 2){
				mangaInfo.chapters = mangaInfo.chapters.slice(selection[0], selection[1])
			}
		}

		if(config.pdf){
			doc = new pdfkit({autoFirstPage: false})
			doc.pipe(fs.createWriteStream(cPath+mangaInfo.title+'.pdf'))
		}else{
			cPath += mangaInfo.title+'/'
			mkdir(cPath);
		}
		for(var i = 0; i < mangaInfo.chapters.length; i++){
			let chapter = await downloadChapter(mangaInfo.chapters[i].url)
			if(config.pdf){
				for(var y = 0; y < chapter.images.length; y++){
					let image = chapter.images[y]
					doc.addPage({size: [image.size.width, image.size.height]})
					if(image.size.format == 'png' && !argv.noconvert) image.buffer = await reconvertPNG(image.buffer)
					doc.image(image.buffer, 0, 0)
				}
			}else{
				let tPath = cPath+chapter.name+'/'
				mkdir(tPath)
				for(var y = 0; y < chapter.images.length; y++){
					let image = chapter.images[y]
					await write(tPath+path.basename(image.image), image.buffer)
				}
			}
		}
		if(config.pdf) doc.end()
	}else{
		let chapter = await downloadChapter(manga.url)

		let cPath = config.outputDir+'/'
		if(config.pdf){
			var doc = new pdfkit({autoFirstPage: false})
			doc.pipe(fs.createWriteStream(cPath+chapter.name+'.pdf'))
			for(var i = 0; i < chapter.images.length; i++){
				let image = chapter.images[i]
				doc.addPage({size: [image.size.width, image.size.height]})
				if(image.size.format == 'png') image.buffer = await reconvertPNG(image.buffer)
				doc.image(image.buffer, 0, 0)
			}
			doc.end()
		}else{
			mkdir(chapter.name); cPath += chapter.name+'/'
			for(var i = 0; i < chapter.images.length; i++){
				let image = chapter.images[i]
				await write(cPath+path.basename(image.image), image.buffer)
			}
		}
	}
}

function downloadChapter(url){
	return new Promise((resolve, reject) => {
		get(url).then(async body => {
			try{
				var cBody = cheerio.load(body), name = cBody('#chapter-title > b').text()
				var images = JSON.parse(cBody('body > script').html().match(/\[(.*)\]/)[0])
				console.log(`\n  ${name}`)
				var progressBar = new progress('  (:current/:total) [:bar] :percent', {
					complete: '=',
					incomplete: ' ',
					width: images.length,
					total: images.length
				})
				for(var i = 0; i < images.length; i++){
					let imgData = await get(BASEURL+images[i].image, true)
					images[i].buffer = imgData.buffer
					images[i].size = imgData.size
					progressBar.tick()
				}
				resolve({
					name: legalize(name),
					images: images
				})
			}catch(err){
				reject(err)
			}
		})
	})
}

/* Helper functions */
function mkdir(path){
	if (!fs.existsSync(path))
		fs.mkdirSync(path)
}

function pipe(url, path){
	return new Promise((resolve, reject) => {
		https.get(url, res => {
			res.pipe(fs.createWriteStream(path))
			res.on('end', resolve)
			res.on('error', reject)
		})
	})
}

// in case we need buffer later on
function get(url, buffer = false){
	return new Promise((resolve, reject) => {
		https.get(url, async res => {
			//console.log(res.headers)
			//console.log(res.headers['content-length'])

			if(argv.verbose){
				console.log('  >>', url, '\n')
				var bar = new progress('  (:current/:total) [:bar] :rate/bps :percent :etas', {
					complete: '=',
					incomplete: ' ',
					width: res.headers['content-length'] || 25,
					total: res.headers['content-length'] ? parseInt(res.headers['content-length']) : 5000
				});
			}

			var size, cap, lURL = url.toLowerCase()
			if(lURL.endsWith('.gif') || lURL.endsWith('.png') || lURL.endsWith('.jpg') || lURL.endsWith('.jpeg')){
				getImageSize(res).then(ssize => {
					size = ssize
				})
			}

			res.on('error', (err) => {
				console.log(err)
			})

			if(buffer){
				cap = []
				res.on('data', chunk => {
					cap.push(chunk)
					if(argv.verbose) bar.tick(chunk.length)
				})
				res.on('end', () => {
					resolve(size ? {buffer: Buffer.concat(cap), size: size}: Buffer.concat(cap))
				})
			}else{
				cap = ''
				res.on('data', chunk => {
					cap += chunk
					if(argv.verbose) bar.tick(chunk.length)
				})
				res.on('end', () => {
					resolve(cap)
					//no point of including size in here, since who in the right mind would download images to string?
				})

			}
		})
	})
}

function getImageSize(stream){
	return new Promise((resolve, reject) => {
		imageSize(stream, (err,res) => {
			if(err) return reject(err)
			resolve(res)
		})
	})
}

// some OS (eg. Windows) don't like them in the path name, so they throw a tantrum
function legalize(text, replacer = ''){
	return text.replace(/\\|\/|:|\*|\?|"|<|>/g, replacer)
}

// okay i might have gone overboard with promises
function write(file, data){
	return new Promise((resolve,reject) => {
		fs.writeFile(file,data, (err) => {
			if(err) return reject(err)
			resolve()
		})
	})
}

function reconvertPNG(buffer){
	return new Promise((resolve,reject) => {
		let png = new PNG()
		png.parse(buffer, (err,data) => {
			if(err) return reject(err)
			let stream = png.pack()
			var cap = []
			stream.on('data', chunk => {cap.push(chunk)})
			stream.on('end', () => {
				resolve(Buffer.concat(cap))
			})
		})
	})
}<commit_msg>Dumb mistake, as always<commit_after>const BASEURL = 'https://dynasty-scans.com'

const fs = require('fs')
const https = require('https')
const cheerio = require('cheerio')
const path = require('path')
const pdfkit = require('pdfkit')
const imageSize = require('imagesize')
const progress = require('progress')

const PNG = require('pngjs').PNG

const argv = require('commander')
	.version(require('./package.json').version)
	.arguments('<url>')
	.description('Simple tool for batch-downloading from Dynasty-Scans. Supports also PDF saving as well as chapter selection.')
	.option('-c, --chapters <a>-<b>', 'Chapter range.')
	.option('-C, --listChapters', 'List all chapters with correct indexes.')
	.option('-o, --output [path]', 'Different output path, defaults to current working directory.')
	.option('-p, --pdf', 'Downloads pdf instead of seperated images.')
	.option('-n, --noconvert', 'Skips PNG to PDF coversion.')
	.option('-v, --verbose', 'Includes progressbar for each GET request.')
	.parse(process.argv)

if(!argv.args[0]) argv.help()

var config = {
	pdf: argv.pdf,
	outputDir: path.resolve(argv.output || process.cwd())
}

parseManga({
	url: argv.args[0],
	isSeries: argv.args[0].includes('series'),
	chapters: argv.chapters
})

async function parseManga(manga){
	if(manga.isSeries){
		var sBody = cheerio.load(await get(manga.url)), cPath = config.outputDir+'/', doc

		console.log(`\n  ${sBody('.tag-title > b').text()}`)

		var mangaInfo = {
			title: legalize(sBody('.tag-title > b').text()),
			chapters: sBody('a.name').map((i, url) => {
				return {
					url: BASEURL+url.attribs.href,
					name: url.children[0].data
				}
			}).toArray()
		}

		if(argv.listChapters){
			for(var i = 0; i < mangaInfo.chapters.length; i++){
				console.log(`  ${i}: ${mangaInfo.chapters[i].name}`)
			}
			process.exit(0)
		}

		//slice chapters that are needed and stuff
		if(manga.chapters){
			let selection = argv.chapters.split('-')
			if(selection.length == 1){
				mangaInfo.chapters = [mangaInfo.chapters[selection[0]]]
			}else if(selection.length == 2){
				mangaInfo.chapters = mangaInfo.chapters.slice(selection[0], selection[1])
			}
		}

		if(config.pdf){
			doc = new pdfkit({autoFirstPage: false})
			doc.pipe(fs.createWriteStream(cPath+mangaInfo.title+'.pdf'))
		}else{
			cPath += mangaInfo.title+'/'
			mkdir(cPath);
		}
		for(var i = 0; i < mangaInfo.chapters.length; i++){
			let chapter = await downloadChapter(mangaInfo.chapters[i].url)
			if(config.pdf){
				for(var y = 0; y < chapter.images.length; y++){
					let image = chapter.images[y]
					doc.addPage({size: [image.size.width, image.size.height]})
					if(image.size.format == 'png' && !argv.noconvert) image.buffer = await reconvertPNG(image.buffer)
					doc.image(image.buffer, 0, 0)
				}
			}else{
				let tPath = cPath+chapter.name+'/'
				mkdir(tPath)
				for(var y = 0; y < chapter.images.length; y++){
					let image = chapter.images[y]
					await write(tPath+path.basename(image.image), image.buffer)
				}
			}
		}
		if(config.pdf) doc.end()
	}else{
		let chapter = await downloadChapter(manga.url)

		let cPath = config.outputDir+'/'
		if(config.pdf){
			var doc = new pdfkit({autoFirstPage: false})
			doc.pipe(fs.createWriteStream(cPath+chapter.name+'.pdf'))
			for(var i = 0; i < chapter.images.length; i++){
				let image = chapter.images[i]
				doc.addPage({size: [image.size.width, image.size.height]})
				if(image.size.format == 'png') image.buffer = await reconvertPNG(image.buffer)
				doc.image(image.buffer, 0, 0)
			}
			doc.end()
		}else{
			mkdir(chapter.name); cPath += chapter.name+'/'
			for(var i = 0; i < chapter.images.length; i++){
				let image = chapter.images[i]
				await write(cPath+path.basename(image.image), image.buffer)
			}
		}
	}
}

function downloadChapter(url){
	return new Promise((resolve, reject) => {
		get(url).then(async body => {
			try{
				var cBody = cheerio.load(body), name = cBody('#chapter-title > b').text()
				var images = JSON.parse(cBody('body > script').html().match(/\[(.*)\]/)[0])
				console.log(`\n  ${name}`)
				var progressBar = new progress('  (:current/:total) [:bar] :percent', {
					complete: '=',
					incomplete: ' ',
					width: images.length,
					total: images.length
				})
				for(var i = 0; i < images.length; i++){
					let imgData = await get(BASEURL+images[i].image, true)
					images[i].buffer = imgData.buffer
					images[i].size = imgData.size
					progressBar.tick()
				}
				resolve({
					name: legalize(name),
					images: images
				})
			}catch(err){
				reject(err)
			}
		})
	})
}

/* Helper functions */
function mkdir(path){
	if (!fs.existsSync(path))
		fs.mkdirSync(path)
}

function pipe(url, path){
	return new Promise((resolve, reject) => {
		https.get(url, res => {
			res.pipe(fs.createWriteStream(path))
			res.on('end', resolve)
			res.on('error', reject)
		})
	})
}

// in case we need buffer later on
function get(url, buffer = false){
	return new Promise((resolve, reject) => {
		https.get(url, async res => {
			//console.log(res.headers)
			//console.log(res.headers['content-length'])

			if(argv.verbose){
				console.log('  >>', url, '\n')
				var bar = new progress('  (:current/:total) [:bar] :rate/bps :percent :etas', {
					complete: '=',
					incomplete: ' ',
					width: res.headers['content-length'] || 25,
					total: res.headers['content-length'] ? parseInt(res.headers['content-length']) : 5000
				});
			}

			var size, cap, lURL = url.toLowerCase()
			if(lURL.endsWith('.gif') || lURL.endsWith('.png') || lURL.endsWith('.jpg') || lURL.endsWith('.jpeg')){
				getImageSize(res).then(ssize => {
					size = ssize
				})
			}

			res.on('error', (err) => {
				console.log(err)
			})

			if(buffer){
				cap = []
				res.on('data', chunk => {
					cap.push(chunk)
					if(argv.verbose) bar.tick(chunk.length)
				})
				res.on('end', () => {
					resolve(size ? {buffer: Buffer.concat(cap), size: size}: Buffer.concat(cap))
				})
			}else{
				cap = ''
				res.on('data', chunk => {
					cap += chunk
					if(argv.verbose) bar.tick(chunk.length)
				})
				res.on('end', () => {
					resolve(cap)
					//no point of including size in here, since who in the right mind would download images to string?
				})

			}
		})
	})
}

function getImageSize(stream){
	return new Promise((resolve, reject) => {
		imageSize(stream, (err,res) => {
			if(err) return reject(err)
			resolve(res)
		})
	})
}

// some OS (eg. Windows) don't like them in the path name, so they throw a tantrum
function legalize(text, replacer = ''){
	return text.replace(/\\|\/|:|\*|\?|"|<|>/g, replacer)
}

// okay i might have gone overboard with promises
function write(file, data){
	return new Promise((resolve,reject) => {
		fs.writeFile(file,data, (err) => {
			if(err) return reject(err)
			resolve()
		})
	})
}

function reconvertPNG(buffer){
	return new Promise((resolve,reject) => {
		let png = new PNG()
		png.parse(buffer, (err,data) => {
			if(err) return reject(err)
			let stream = png.pack()
			var cap = []
			stream.on('data', chunk => {cap.push(chunk)})
			stream.on('end', () => {
				resolve(Buffer.concat(cap))
			})
		})
	})
}<|endoftext|>


<commit_before>var express = require('express');
var bodyParser = require('body-parser');
var request = require('request');
var app = express();

app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
app.listen((process.env.PORT || 3000));

// Current version
ver = 'v.0.0.5';

// Facebook pageId
pageId = '1167308473348175';

// Server endpoint
app.get('/', function (req, res) {
    res.send('JKDbot here! ' + ver);
});

// Facebook webhook
app.get('/webhook', function (req, res) {
    if (req.query['hub.verify_token'] === 'jkdbot_verify_token') {
        res.send(req.query['hub.challenge']);
    } else {
        res.send('Invalid verify token');
    }
});

// Handler receiving messages
app.post('/webhook', function (req, res) {
    var events = req.body.entry[0].messaging;
    for (i = 0; i < events.length; i++) {
        var event = events[i];
        if (event.message && event.message.text) {
            switch(event.message.text) {
                case("cmd_version"):
                    sendMessage(event.sender.id, {text: ver});
                    break;
                case("cmd_subscribers"):
                    sendMessage(event.sender.id, {text: getPageSubscribers(pageId)});
                    break;
                case("cmd_timezone"):
                    sendMessage(event.sender.id, {text: getUserTimezone("1")});
                    break;
                default:
                    sendMessage(event.sender.id, {text: "Message received: " + event.message.text});
                    break;
            }
        }
    }
    res.sendStatus(200);
});

// Sends a message to a Facebook user
var sendMessage = function(recipientId, message) {
    request({
        url: 'https://graph.facebook.com/v2.8/me/messages',
        qs: {access_token: process.env.PAGE_ACCESS_TOKEN},
        method: 'POST',
        json: {
            recipient: {id: recipientId},
            message: message,
        }
    }, function(error, response, body) {
        if (error) {
            console.log('Error sending message: ', error);
        } else if (response.body.error) {
            console.log('Error: ', response.body.error);
        }
    });
};

// Returns the subscribers of a page
var getPageSubscribers = function(pageId) {
    request({
        url: 'https://graph.facebook.com/v2.8/'+pageId+'/likes',
        qs: {access_token: process.env.PAGE_ACCESS_TOKEN},
        method: 'GET'
    }, function(error, response, body) {
        if (error) {
            console.log('Error retrieving page subscribers: ', error);
        } else if (response.body.error) {
            console.log('Error: ', response.body.error);
        }
    });
};

// Returns the timezone of a user
var getUserTimezone = function(userId) {
    return "-9";
};
<commit_msg>Get page likes document<commit_after>var express = require('express');
var bodyParser = require('body-parser');
var request = require('request');
var app = express();

app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
app.listen((process.env.PORT || 3000));

// Current version
ver = 'v.0.0.5';

// Facebook pageId
pageId = '1167308473348175';

// Server endpoint
app.get('/', function (req, res) {
    res.send('JKDbot here! ' + ver);
});

// Facebook webhook
app.get('/webhook', function (req, res) {
    if (req.query['hub.verify_token'] === 'jkdbot_verify_token') {
        res.send(req.query['hub.challenge']);
    } else {
        res.send('Invalid verify token');
    }
});

// Handler receiving messages
app.post('/webhook', function (req, res) {
    var events = req.body.entry[0].messaging;
    for (i = 0; i < events.length; i++) {
        var event = events[i];
        if (event.message && event.message.text) {
            switch(event.message.text) {
                case("cmd_version"):
                    sendMessage(event.sender.id, {text: ver});
                    break;
                case("cmd_subscribers"):
                    sendMessage(event.sender.id, {text: getUserIds()});
                    break;
                case("cmd_timezone"):
                    sendMessage(event.sender.id, {text: getUserTimezone("1")});
                    break;
                default:
                    sendMessage(event.sender.id, {text: "Message received: " + event.message.text});
                    break;
            }
        }
    }
    res.sendStatus(200);
});

// Sends a message to a Facebook user
var sendMessage = function(recipientId, message) {
    request({
        url: 'https://graph.facebook.com/v2.8/me/messages',
        qs: {access_token: process.env.PAGE_ACCESS_TOKEN},
        method: 'POST',
        json: {
            recipient: {id: recipientId},
            message: message,
        }
    }, function(error, response, body) {
        if (error) {
            console.log('Error sending message: ', error);
        } else if (response.body.error) {
            console.log('Error: ', response.body.error);
        }
    });
};

// Collects the userId's from the likes page
var getUserIds = function() {
    var pageLikesDocument = getPageLikesDocument();
    console.log(likesPage);

    /*
    var userIds = "";
    Array.prototype.forEach.call(document.querySelectorAll('a[data-gt]'), function(a){
        var gt = JSON.parse(a.dataset.gt);
        if(!gt.engagement || gt.engagement.eng_type !== "1")
            return;
        userIds += a.innerHTML + ': ' + gt.engagement.eng_tid + "\n";
    });
    console.log(userIds);
    */
}

// Retrieves the page with the likes of a page
var getPageLikesDocument = function() {
    request({
        url: 'https://www.facebook.com/browse/?type=page_fans&page_id='+pageId,
        method: 'GET'
    }, function(error, response, body) {
        if (error) {
            console.log('Error retrieving page likes: ', error);
        } else if (response.body.error) {
            console.log('Error: ', response.body.error);
        }
    });
};

// Retrieves the timezone of a user
var getUserTimezone = function(userId) {
    return "-9";
};
<|endoftext|>


<commit_before>/* @flow */

import webpack from 'webpack';
import { extname as pathExtName, resolve as pathResolve } from 'path';
import appRootDir from 'app-root-dir';
import md5 from 'md5';
import fs from 'fs';
import { sync as globSync } from 'glob';
import matchRequire from 'match-require';
import { createNotification } from '../utils';
import staticConfig from '../../config/static';

const appRootPath = appRootDir.get();

// $FlowFixMe
const packageJSON = require(pathResolve(appRootPath, './package.json'));

// We calculate a hash of the package.json's dependencies, which we can use
// to determine if dependencies have changed since the last time we built
// the vendor dll.
const currentDependenciesHash = md5(JSON.stringify(packageJSON.dependencies));

const vendorDLLHashFilePath = pathResolve(
  appRootPath,
  staticConfig.clientBundle.outputPath,
  `${staticConfig.development.vendorDLL.name}_hash`,
);

console.log(vendorDLLHashFilePath);

function webpackConfigFactory(modules) {
  return {
    // We only use this for development, so lets always include source maps.
    devtool: 'inline-source-map',
    entry: { [staticConfig.development.vendorDLL.name]: modules },
    output: {
      path: pathResolve(appRootPath, staticConfig.clientBundle.outputPath),
      filename: `${staticConfig.development.vendorDLL.name}.js`,
      library: staticConfig.development.vendorDLL.name,
    },
    plugins: [
      new webpack.DllPlugin({
        path: pathResolve(
          appRootPath,
          staticConfig.clientBundle.outputPath,
          `${staticConfig.development.vendorDLL.name}.json`,
        ),
        name: staticConfig.development.vendorDLL.name,
      }),
    ],
  };
}

function getJsFilesFromDir(targetPath) {
  return ['js', 'jsx'].reduce((acc, ext) =>
    acc.concat(globSync(`${targetPath}/**/*.${ext}`)),
    [],
  );
}

function buildVendorDLL() {
  const ignoreModules = staticConfig.development.vendorDLL.ignores;

  return new Promise((resolve, reject) => {
    Promise.all([
      Promise.resolve(
        getJsFilesFromDir(
          pathResolve(appRootPath, staticConfig.clientBundle.srcPath),
        ),
      ),
      Promise.resolve(
        getJsFilesFromDir(
          pathResolve(appRootPath, staticConfig.bundlesSharedSrcPath),
        ),
      ),
    ])
    .then(([clientFiles, universalFiles]) => {
      const isJsFile = file => pathExtName(file) === '.js';
      const allJSFiles = [...clientFiles, ...universalFiles].filter(isJsFile);
      const modules = allJSFiles.reduce((acc, cur) => {
        const fileContents = fs.readFileSync(cur, 'utf8');
        matchRequire.findAll(fileContents).forEach(match => acc.add(match));
        return acc;
      }, new Set());

      // $FlowFixMe
      const filteredModules = [...modules]
        // Remove any modules that have been configured to be ignored.
        .filter(module => ignoreModules.findIndex(x => x === module) === -1)
        // We only want to include absolute imports, no relative required modules.
        .filter(module => !matchRequire.isRelativeModule(module));

      createNotification({
        title: 'vendorDLL',
        level: 'info',
        message: 'Vendor DLL build complete. Check console for module list.',
      });
      console.log(filteredModules);

      const webpackConfig = webpackConfigFactory(filteredModules);
      console.log(JSON.stringify(webpackConfig, null, 4));
      const vendorDLLCompiler = webpack(webpackConfig);
      vendorDLLCompiler.run((err) => {
        if (err) {
          reject(err);
          return;
        }
        // Update the dependency hash
        fs.writeFileSync(vendorDLLHashFilePath, currentDependenciesHash);

        resolve();
      });
    });
  });
}

function ensureVendorDLLExists() {
  return new Promise((resolve, reject) => {
    if (!staticConfig.development.vendorDLL.enabled) {
      resolve();
    }

    if (!fs.existsSync(vendorDLLHashFilePath)) {
      // builddll
      createNotification({
        title: 'vendorDLL',
        level: 'warn',
        message: 'Generating a new vendor dll for boosted development performance...',
      });
      buildVendorDLL().then(resolve).catch(reject);
    } else {
      // first check if the md5 hashes match
      const dependenciesHash = fs.readFileSync(vendorDLLHashFilePath, 'utf8');
      const dependenciesChanged = dependenciesHash !== currentDependenciesHash;

      if (dependenciesChanged) {
        createNotification({
          title: 'vendorDLL',
          level: 'warn',
          message: 'New vendor dependencies detected. Regenerating the vendor dll...',
        });
        buildVendorDLL().then(resolve).catch(reject);
      } else {
        createNotification({
          title: 'vendorDLL',
          level: 'info',
          message: 'No changes to existing vendor dependencies. Using the existing vendor dll.',
        });
        resolve();
      }
    }
  });
}

export default ensureVendorDLLExists;
<commit_msg>Removes some debugging console.log statements.<commit_after>/* @flow */

import webpack from 'webpack';
import { extname as pathExtName, resolve as pathResolve } from 'path';
import appRootDir from 'app-root-dir';
import md5 from 'md5';
import fs from 'fs';
import { sync as globSync } from 'glob';
import matchRequire from 'match-require';
import { createNotification } from '../utils';
import staticConfig from '../../config/static';

const appRootPath = appRootDir.get();

// $FlowFixMe
const packageJSON = require(pathResolve(appRootPath, './package.json'));

// We calculate a hash of the package.json's dependencies, which we can use
// to determine if dependencies have changed since the last time we built
// the vendor dll.
const currentDependenciesHash = md5(JSON.stringify(packageJSON.dependencies));

const vendorDLLHashFilePath = pathResolve(
  appRootPath,
  staticConfig.clientBundle.outputPath,
  `${staticConfig.development.vendorDLL.name}_hash`,
);

function webpackConfigFactory(modules) {
  return {
    // We only use this for development, so lets always include source maps.
    devtool: 'inline-source-map',
    entry: { [staticConfig.development.vendorDLL.name]: modules },
    output: {
      path: pathResolve(appRootPath, staticConfig.clientBundle.outputPath),
      filename: `${staticConfig.development.vendorDLL.name}.js`,
      library: staticConfig.development.vendorDLL.name,
    },
    plugins: [
      new webpack.DllPlugin({
        path: pathResolve(
          appRootPath,
          staticConfig.clientBundle.outputPath,
          `${staticConfig.development.vendorDLL.name}.json`,
        ),
        name: staticConfig.development.vendorDLL.name,
      }),
    ],
  };
}

function getJsFilesFromDir(targetPath) {
  return ['js', 'jsx'].reduce((acc, ext) =>
    acc.concat(globSync(`${targetPath}/**/*.${ext}`)),
    [],
  );
}

function buildVendorDLL() {
  const ignoreModules = staticConfig.development.vendorDLL.ignores;

  return new Promise((resolve, reject) => {
    Promise.all([
      Promise.resolve(
        getJsFilesFromDir(
          pathResolve(appRootPath, staticConfig.clientBundle.srcPath),
        ),
      ),
      Promise.resolve(
        getJsFilesFromDir(
          pathResolve(appRootPath, staticConfig.bundlesSharedSrcPath),
        ),
      ),
    ])
    .then(([clientFiles, universalFiles]) => {
      const isJsFile = file => pathExtName(file) === '.js';
      const allJSFiles = [...clientFiles, ...universalFiles].filter(isJsFile);
      const modules = allJSFiles.reduce((acc, cur) => {
        const fileContents = fs.readFileSync(cur, 'utf8');
        matchRequire.findAll(fileContents).forEach(match => acc.add(match));
        return acc;
      }, new Set());

      // $FlowFixMe
      const filteredModules = [...modules]
        // Remove any modules that have been configured to be ignored.
        .filter(module => ignoreModules.findIndex(x => x === module) === -1)
        // We only want to include absolute imports, no relative required modules.
        .filter(module => !matchRequire.isRelativeModule(module));

      createNotification({
        title: 'vendorDLL',
        level: 'info',
        message: 'Vendor DLL build complete. Check console for module list.',
      });
      console.log(filteredModules);

      const webpackConfig = webpackConfigFactory(filteredModules);
      const vendorDLLCompiler = webpack(webpackConfig);
      vendorDLLCompiler.run((err) => {
        if (err) {
          reject(err);
          return;
        }
        // Update the dependency hash
        fs.writeFileSync(vendorDLLHashFilePath, currentDependenciesHash);

        resolve();
      });
    });
  });
}

function ensureVendorDLLExists() {
  return new Promise((resolve, reject) => {
    if (!staticConfig.development.vendorDLL.enabled) {
      resolve();
    }

    if (!fs.existsSync(vendorDLLHashFilePath)) {
      // builddll
      createNotification({
        title: 'vendorDLL',
        level: 'warn',
        message: 'Generating a new vendor dll for boosted development performance...',
      });
      buildVendorDLL().then(resolve).catch(reject);
    } else {
      // first check if the md5 hashes match
      const dependenciesHash = fs.readFileSync(vendorDLLHashFilePath, 'utf8');
      const dependenciesChanged = dependenciesHash !== currentDependenciesHash;

      if (dependenciesChanged) {
        createNotification({
          title: 'vendorDLL',
          level: 'warn',
          message: 'New vendor dependencies detected. Regenerating the vendor dll...',
        });
        buildVendorDLL().then(resolve).catch(reject);
      } else {
        createNotification({
          title: 'vendorDLL',
          level: 'info',
          message: 'No changes to existing vendor dependencies. Using the existing vendor dll.',
        });
        resolve();
      }
    }
  });
}

export default ensureVendorDLLExists;
<|endoftext|>


<commit_before>var bakerHoods = require('../data/neighborhoods/bakersfield.json');
var bakerHomes = require('../data/kern.json');
var predictions = require('../data/quandl/real_predictions.json');

var isFuture = location.pathname.indexOf('future') >= 0;

function getCoords(coords) {
  return coords.map((coord) => {
    return { lat: coord[1], lng: coord[0] };
  });
}

var COLORS = ['#828282', '#e86828'];

function getCenter(coords) {
  var latSum = 0;
  var lngSum = 0;

  coords.forEach((coord) => {
    latSum += coord.lat;
    lngSum += coord.lng;
  });

  return { lat: latSum / coords.length, lng: lngSum / coords.length };
}

var lastWindow = null;
var hoodData = {};

var hoodsThatChange = [];

global.initMap = () => {
  window.document.getElementById("switch").addEventListener('click', (event) => {
    event.preventDefault();

    isFuture = !isFuture;

    window.document.getElementById("switch").innerHTML =
      isFuture ? 'Show current data' : 'Show future predictions';

    window.document.getElementById("header").innerHTML =
      isFuture ? 'Future predictions for Bakersfield, CA' : 'Current data for Bakersfield, CA'

    hoodsThatChange.forEach((hood) => {
      var color = COLORS[isFuture ? hood.future : hood.present];
      hood.polygons.forEach((polygon) => {
        polygon.setOptions({
          strokeColor: color,
          fillColor: color,
        });
      });
    });
  });

  var center = { lat: 35.3733, lng: -119.0187 };
  var map = new google.maps.Map(document.getElementById('map'), {
    center,
    zoom: 12,
    mapTypeId: google.maps.MapTypeId.ROADMAP,
  });

  var graphHouse = (coords) => {
    var marker = new google.maps.Circle({
      center: coords,
      map: map,
      radius: 60,
      strokeOpacity: 0,
      fillColor: '#e86828',
      fillOpacity: .8,
    });
  };
  bakerHomes.forEach((house) => {
    graphHouse(house.geoLocation);

    var regionId = house.regionId || 'blah';
    hoodData[regionId] = hoodData[regionId] || { kwSum: 0, homeCount: 0 };
    hoodData[regionId].homeCount++;
    hoodData[regionId].kwSum += house.kw;
  });

  bakerHoods.forEach((hood, index) => {
    var present = index % 2;
    // var color = COLORS[good];
    var future = predictions[hood.properties.REGIONID] || present;

    var color = COLORS[isFuture ? future : present];
    var hoodName = hood.properties.NAME;
    var myData = hoodData[hood.properties.REGIONID] || {};

    var polygons = hood.geometry.coordinates.map((coords) => {
      // Construct the polygon.
      var polygon = new google.maps.Polygon({
        paths: getCoords(coords),
        strokeColor: color,
        strokeOpacity: 0.8,
        strokeWeight: 2,
        fillColor: color,
        fillOpacity: 0.35
      });

      polygon.setMap(map);

      var center = getCenter(getCoords(coords));
      var infowindow = new google.maps.InfoWindow({
        content: [
          '
',
          `<h3>${hoodName}</h3>`,
          `<p>kW installed: ${myData.kwSum || 0}</p>`,
          `<p>Num installations: ${myData.homeCount || 0}</p>`,
          `<p>% installations: 5</p>`,
          '
',
        ].join(''),
        position: center,
      });

      polygon.addListener('click', function() {
        if (lastWindow) { lastWindow.close(); }
        infowindow.open(map);
        lastWindow = infowindow;
      });
    });

    if (future !== present) {
      hoodsThatChange.push({ polygons, future, present });
    }

    return polygons;
  });
};
<commit_msg>Add in logic<commit_after>var bakerHoods = require('../data/neighborhoods/bakersfield.json');
var bakerHomes = require('../data/kern.json');
var predictions = require('../data/quandl/real_predictions.json');

var isFuture = location.pathname.indexOf('future') >= 0;

var withSolar = {
  273528: true,
  274019: true,
  272843: true,
  273584: true,
  274211: true,
  273308: true,
  273495: true,
  272940: true,
  275579: true,
  275482: true,
  276240: true,
  275156: true,
  273154: true,
};

function getCoords(coords) {
  return coords.map((coord) => {
    return { lat: coord[1], lng: coord[0] };
  });
}

var COLORS = ['#828282', '#e86828'];

function getCenter(coords) {
  var latSum = 0;
  var lngSum = 0;

  coords.forEach((coord) => {
    latSum += coord.lat;
    lngSum += coord.lng;
  });

  return { lat: latSum / coords.length, lng: lngSum / coords.length };
}

var lastWindow = null;
var hoodData = {};

var hoodsThatChange = [];

global.initMap = () => {
  window.document.getElementById("switch").addEventListener('click', (event) => {
    event.preventDefault();

    isFuture = !isFuture;

    window.document.getElementById("switch").innerHTML =
      isFuture ? 'Show current data' : 'Show future predictions';

    window.document.getElementById("header").innerHTML =
      isFuture ? 'Future predictions for Bakersfield, CA' : 'Current data for Bakersfield, CA'

    hoodsThatChange.forEach((hood) => {
      var color = COLORS[isFuture ? hood.future : hood.present];
      hood.polygons.forEach((polygon) => {
        polygon.setOptions({
          strokeColor: color,
          fillColor: color,
        });
      });
    });
  });

  var center = { lat: 35.3733, lng: -119.0187 };
  var map = new google.maps.Map(document.getElementById('map'), {
    center,
    zoom: 12,
    mapTypeId: google.maps.MapTypeId.ROADMAP,
  });

  var graphHouse = (coords) => {
    var marker = new google.maps.Circle({
      center: coords,
      map: map,
      radius: 60,
      strokeOpacity: 0,
      fillColor: '#e86828',
      fillOpacity: .8,
    });
  };
  bakerHomes.forEach((house) => {
    graphHouse(house.geoLocation);

    var regionId = house.regionId || 'blah';
    hoodData[regionId] = hoodData[regionId] || { kwSum: 0, homeCount: 0 };
    hoodData[regionId].homeCount++;
    hoodData[regionId].kwSum += house.kw;
  });

  bakerHoods.forEach((hood, index) => {
    var hoodName = hood.properties.NAME;
    var regionId = hood.properties.REGIONID;

    // var present = index % 2;
    var present = 0 + (withSolar[regionId] ? 1 : 0);
    // var color = COLORS[good];
    var future = predictions[regionId] || present;

    var color = COLORS[isFuture ? future : present];
    var myData = hoodData[regionId] || {};

    var polygons = hood.geometry.coordinates.map((coords) => {
      // Construct the polygon.
      var polygon = new google.maps.Polygon({
        paths: getCoords(coords),
        strokeColor: color,
        strokeOpacity: 0.8,
        strokeWeight: 2,
        fillColor: color,
        fillOpacity: 0.35
      });

      polygon.setMap(map);

      var center = getCenter(getCoords(coords));
      var infowindow = new google.maps.InfoWindow({
        content: [
          '
',
          `<h3>${hoodName}</h3>`,
          `<h3>${regionId}</h3>`,
          `<p>kW installed: ${myData.kwSum || 0}</p>`,
          `<p>Num installations: ${myData.homeCount || 0}</p>`,
          '
',
        ].join(''),
        position: center,
      });

      polygon.addListener('click', function() {
        if (lastWindow) { lastWindow.close(); }
        infowindow.open(map);
        lastWindow = infowindow;
      });

      return polygon;
    });
    console.log(polygons);

    if (future !== present) {
      hoodsThatChange.push({ polygons, future, present });
    }

    return polygons;
  });
};
<|endoftext|>