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

var browserResolve = require('browser-resolve');
var nodeResolve = require('resolve');
var detective = require('detective');
var through = require('through');
var concat = require('concat-stream');

module.exports = function (mains, opts) {
    if (!opts) opts = {};
    var cache = opts.cache;

    if (!Array.isArray(mains)) mains = [ mains ].filter(Boolean);
    var basedir = opts.basedir || process.cwd();

    var entries = mains.map(function (file) {
        if (file && typeof file.pipe === 'function') {
            var n = Math.floor(Math.pow(16,8) * Math.random()).toString(16);
            return path.join(basedir, 'fake_' + n + '.js');
        }
        return path.resolve(file);
    });

    var visited = {};
    var pending = 0;

    var output = through();

    var transforms = [].concat(opts.transform).filter(Boolean);
    var resolve = opts.resolve || browserResolve;

    var top = { id: '/', filename: '/', paths: [] };
    mains.forEach(function (main, ix) {
        if (typeof main === 'object') {
            walk({ stream: main, file: entries[ix] }, top);
        }
        else walk(main, top)
    });

    if (mains.length === 0) {
        output.pause();
        output.queue(null);
        process.nextTick(function () { output.resume() });
    }

    return output;

    function walk (id, parent, cb) {
        pending ++;

        if (typeof id === 'object') {
            return id.stream.pipe(concat(function (src) {
                var pkgfile = path.join(basedir, 'package.json');
                fs.readFile(pkgfile, function (err, pkgsrc) {
                    var pkg = {};
                    if (!err) {
                        try { pkg = JSON.parse(pkgsrc) }
                        catch (e) {};
                    }
                    var trx = getTransform(pkg);
                    applyTransforms(id.file, trx, src, pkg);
                });
            }));
        }

        var c = opts.cache && opts.cache[parent.id];
        var resolver = c && typeof c === 'object'
        && !Buffer.isBuffer(c) && c.deps[id]
            ? function (xid, xparent, cb) {
                cb(null, opts.cache[parent.id].deps[id]);
            }
            : resolve;
        ;

        if (opts.packageFilter) parent.packageFilter = opts.packageFilter;
        if (opts.extensions) parent.extensions = opts.extensions;
        if (opts.modules) parent.modules = opts.modules;

        resolver(id, parent, function (err, file, pkg) {
            if (err) return output.emit('error', err);
            if (!file) return output.emit('error', new Error([
                'module not found: "' + id + '" from file ',
                parent.filename
            ].join('')));
            if (cb) cb(file);
            if (visited[file]) {
                if (--pending === 0) output.queue(null);
                return;
            }
            visited[file] = true;

            var trx = getTransform(pkg);

            if (cache && cache[file]) {
                parseDeps(file, cache[file], pkg);
            }
            else fs.readFile(file, 'utf8', function (err, src) {
                if (err) return output.emit('error', err);
                applyTransforms(file, trx, src, pkg);
            });
        });
    }

    function getTransform (pkg) {
        var trx = [];
        if (opts.transformKey) {
            var n = pkg;
            opts.transformKey.forEach(function (key) {
                if (n && typeof n === 'object') n = n[key];
            });
            trx = [].concat(n).filter(Boolean);
        }
        return trx;
    }

    function applyTransforms (file, trx, src, pkg) {
        var isTopLevel = mains.some(function (main) {
            var m = path.relative(path.dirname(main), file);
            return m.split('/').indexOf('node_modules') < 0;
        });
        var transf = (isTopLevel ? transforms : []).concat(trx);
        if (transf.length === 0) return done();

        (function ap (trs) {
            if (trs.length === 0) return done();
            makeTransform(file, trs[0], function (err, s) {
                if (err) return output.emit('error', err);

                s.on('error', output.emit.bind(output, 'error'));
                s.pipe(concat(function (data) {
                    src = data;
                    ap(trs.slice(1));
                }));
                s.end(src);
            });
        })(transf);

        function done () {
            parseDeps(file, src, pkg);
        }
    }

    function parseDeps (file, src, pkg) {
        var deps;
        if (!Buffer.isBuffer(src) && typeof src === 'object') {
            deps = Object.keys(src.deps);
            src = src.source;
        }
        else if (opts.noParse && opts.noParse.indexOf(file) >= 0) {
            deps = [];
        }
        else if (/\.json$/.test(file)) {
            deps = [];
        }
        else {
            try { deps = detective(src) }
            catch (ex) {
                var message = ex && ex.message ? ex.message : ex;
                return output.emit('error', new Error(
                    'Parsing file ' + file + ': ' + message
                ));
            }
        }
        var p = deps.length;
        var current = { id: file, filename: file, paths: [], package: pkg };
        var resolved = {};

        deps.forEach(function (id) {
            if (opts.filter && !opts.filter(id)) {
                resolved[id] = false;
                if (--p === 0) done();
                return;
            }

            walk(id, current, function (r) {
                resolved[id] = r;
                if (--p === 0) done();
            });
        });
        if (deps.length === 0) done();

        function done () {
            var rec = {
                id: file,
                source: src,
                deps: resolved
            };
            if (entries.indexOf(file) >= 0) {
                rec.entry = true;
            }
            output.queue(rec);
            if (--pending === 0) output.queue(null);
        }
    }

    function makeTransform (file, tr, cb) {
        if (typeof tr === 'function') return cb(null, tr(file));

        var params = { basedir: path.dirname(file) };
        nodeResolve(tr, params, function nr (err, res, again) {
            if (err && again) return cb(err);

            if (err) {
                params.basedir = process.cwd();
                nodeResolve(tr, params, function (e, r) {
                    nr(e, r, true)
                });
                return;
            }

            if (!res) return cb(new Error([
                'cannot find transform module ', tr,
                ' while transforming ', file
            ].join('')));

            cb(null, require(res)(file));
        });
    }
};
<commit_msg>use a package cache to hold onto package.json entries<commit_after>var fs = require('fs');
var path = require('path');
var spawn = require('child_process').spawn;

var browserResolve = require('browser-resolve');
var nodeResolve = require('resolve');
var detective = require('detective');
var through = require('through');
var concat = require('concat-stream');

module.exports = function (mains, opts) {
    if (!opts) opts = {};
    var cache = opts.cache;
    var pkgCache = opts.packageCache;

    if (!Array.isArray(mains)) mains = [ mains ].filter(Boolean);
    var basedir = opts.basedir || process.cwd();

    var entries = mains.map(function (file) {
        if (file && typeof file.pipe === 'function') {
            var n = Math.floor(Math.pow(16,8) * Math.random()).toString(16);
            return path.join(basedir, 'fake_' + n + '.js');
        }
        return path.resolve(file);
    });

    var visited = {};
    var pending = 0;

    var output = through();

    var transforms = [].concat(opts.transform).filter(Boolean);
    var resolve = opts.resolve || browserResolve;

    var top = { id: '/', filename: '/', paths: [] };
    mains.forEach(function (main, ix) {
        if (typeof main === 'object') {
            walk({ stream: main, file: entries[ix] }, top);
        }
        else walk(main, top)
    });

    if (mains.length === 0) {
        output.pause();
        output.queue(null);
        process.nextTick(function () { output.resume() });
    }

    return output;

    function walk (id, parent, cb) {
        pending ++;

        if (typeof id === 'object') {
            return id.stream.pipe(concat(function (src) {
                var pkgfile = path.join(basedir, 'package.json');
                fs.readFile(pkgfile, function (err, pkgsrc) {
                    var pkg = {};
                    if (!err) {
                        try { pkg = JSON.parse(pkgsrc) }
                        catch (e) {};
                    }
                    var trx = getTransform(pkg);
                    applyTransforms(id.file, trx, src, pkg);
                });
            }));
        }

        var c = cache && cache[parent.id];
        var resolver = c && typeof c === 'object'
        && !Buffer.isBuffer(c) && c.deps[id]
            ? function (xid, xparent, cb) {
                var file = cache[parent.id].deps[id];
                cb(null, file, pkgCache && pkgCache[file]);
            }
            : resolve;
        ;

        if (opts.packageFilter) parent.packageFilter = opts.packageFilter;
        if (opts.extensions) parent.extensions = opts.extensions;
        if (opts.modules) parent.modules = opts.modules;

        resolver(id, parent, function (err, file, pkg) {
            if (err) return output.emit('error', err);
            if (!file) return output.emit('error', new Error([
                'module not found: "' + id + '" from file ',
                parent.filename
            ].join('')));
            if (cb) cb(file);
            if (visited[file]) {
                if (--pending === 0) output.queue(null);
                return;
            }
            visited[file] = true;

            var trx = getTransform(pkg);

            if (cache && cache[file]) {
                parseDeps(file, cache[file], pkg);
            }
            else fs.readFile(file, 'utf8', function (err, src) {
                if (err) return output.emit('error', err);
                applyTransforms(file, trx, src, pkg);
            });
        });
    }

    function getTransform (pkg) {
        var trx = [];
        if (opts.transformKey) {
            var n = pkg;
            opts.transformKey.forEach(function (key) {
                if (n && typeof n === 'object') n = n[key];
            });
            trx = [].concat(n).filter(Boolean);
        }
        return trx;
    }

    function applyTransforms (file, trx, src, pkg) {
        var isTopLevel = mains.some(function (main) {
            var m = path.relative(path.dirname(main), file);
            return m.split('/').indexOf('node_modules') < 0;
        });
        var transf = (isTopLevel ? transforms : []).concat(trx);
        if (transf.length === 0) return done();

        (function ap (trs) {
            if (trs.length === 0) return done();
            makeTransform(file, trs[0], function (err, s) {
                if (err) return output.emit('error', err);

                s.on('error', output.emit.bind(output, 'error'));
                s.pipe(concat(function (data) {
                    src = data;
                    ap(trs.slice(1));
                }));
                s.end(src);
            });
        })(transf);

        function done () {
            parseDeps(file, src, pkg);
        }
    }

    function parseDeps (file, src, pkg) {
        var deps;
        if (!Buffer.isBuffer(src) && typeof src === 'object') {
            deps = Object.keys(src.deps);
            src = src.source;
        }
        else if (opts.noParse && opts.noParse.indexOf(file) >= 0) {
            deps = [];
        }
        else if (/\.json$/.test(file)) {
            deps = [];
        }
        else {
            try { deps = detective(src) }
            catch (ex) {
                var message = ex && ex.message ? ex.message : ex;
                return output.emit('error', new Error(
                    'Parsing file ' + file + ': ' + message
                ));
            }
        }
        var p = deps.length;
        var current = { id: file, filename: file, paths: [], package: pkg };
        var resolved = {};

        deps.forEach(function (id) {
            if (opts.filter && !opts.filter(id)) {
                resolved[id] = false;
                if (--p === 0) done();
                return;
            }

            walk(id, current, function (r) {
                resolved[id] = r;
                if (--p === 0) done();
            });
        });
        if (deps.length === 0) done();

        function done () {
            var rec = {
                id: file,
                source: src,
                deps: resolved
            };
            if (entries.indexOf(file) >= 0) {
                rec.entry = true;
            }
            output.queue(rec);
            if (--pending === 0) output.queue(null);
        }
    }

    function makeTransform (file, tr, cb) {
        if (typeof tr === 'function') return cb(null, tr(file));

        var params = { basedir: path.dirname(file) };
        nodeResolve(tr, params, function nr (err, res, again) {
            if (err && again) return cb(err);

            if (err) {
                params.basedir = process.cwd();
                nodeResolve(tr, params, function (e, r) {
                    nr(e, r, true)
                });
                return;
            }

            if (!res) return cb(new Error([
                'cannot find transform module ', tr,
                ' while transforming ', file
            ].join('')));

            cb(null, require(res)(file));
        });
    }
};
<|endoftext|>


<commit_before>/**
 * Created by petersquicciarini on 3/9/17.
 */

const winston = require('winston');

if (!process.env.slackClientID || !process.env.slackClientSecret ||
  !process.env.ticketSystemUrl || !process.env.PORT || !process.env.mongoUri ||
  !process.env.escalationTeam) {
  winston.log('error', 'Please see README for required env vars.');
  process.exit();
}

const Botkit = require('botkit');
const mongoStorage = require('botkit-storage-mongo')({ mongoUri: process.env.mongoUri });
const url = require('url');
const quotes = require('./lib/quotes');
const freshservice = require('./lib/freshservice');
const request = require('request');

const connectionInfo = {
  slackClientID: process.env.slackClientID,
  slackClientSecret: process.env.slackClientSecret,
  ticketSystemUrl: process.env.ticketSystemUrl,
  ticketSystemAPIKey: process.env.ticketSystemAPIKey,
};
const controller = Botkit.slackbot({
  storage: mongoStorage,
}).configureSlackApp({
  clientId: connectionInfo.slackClientID,
  clientSecret: connectionInfo.slackClientSecret,
  scopes: ['bot', 'chat:write:bot', 'users:read', 'channels:read'],
});

controller.setupWebserver(process.env.PORT, () => {
  controller.createWebhookEndpoints(controller.webserver);
  controller.createHomepageEndpoint(controller.webserver);
  controller.createOauthEndpoints(controller.webserver, (err, req, res) => {
    if (err) {
      res.status(500).send(`ERROR: ${err}`);
    } else {
      res.send('Success!');
    }
  });
});

// just a simple way to make sure we don't
// connect to the RTM twice for the same team
const activeBots = {};
function trackBot(bot) {
  activeBots[bot.config.token] = bot;
}

controller.on('create_bot', (bot) => {
  if (activeBots[bot.config.token]) {
    // already online! do nothing.
  } else {
    bot.startRTM((err) => {
      if (!err) {
        trackBot(bot);
      }
    });
  }
});

controller.storage.teams.all((err, teams) => {
  if (err) {
    throw new Error(err);
  }
  // connect all teams with bots up to slack!
  Object.keys(teams).forEach((t) => {
    if (teams[t].bot) {
      controller.spawn(teams[t]).startRTM((startErr, bot) => {
        if (startErr) {
          winston.log('error', 'Could not connect to Slack RTM.');
        } else {
          trackBot(bot);
        }
      });
    }
  });
});
controller.on('rtm_open', () => {
  winston.log('info', '** The RTM api just connected!');
});
controller.on('rtm_close', (bot) => {
  winston.log('warn', '** The RTM api just closed');
  bot.startRTM((err) => {
    if (!err) {
      trackBot(bot);
    }
  });
});

// *** Begin Ticket Info/Link Handler *** //
controller.hears(['ticket ([0-9]+)'], ['ambient'], (bot, message) => {
  winston.log('info', 'Hazel heard a ticket # pattern. Crafting reply...');
  bot.api.channels.info({ channel: message.channel }, (err, info) => {
    if (err) {
      winston.log('error', 'Hazel could not get channel info.');
    } else {
      winston.log('debug', 'Hazel got the channel info.');
      if (info.channel.name === 'emg') {
        winston.log('info', 'We are in the EMG channel. Sending buttons...');
        const emgTicketReply = {
          username: 'hazel',
          icon_emoji: ':octopus:',
          text: "On Call Tech: Let everyone know you're taking care of it, and escalate if you need to:",
          attachments: [
            {
              fallback: "(Sorry. I couldn't make the cool buttons this time.)",
              callback_id: 'emgResponse',
              actions: [
                {
                  name: 'acceptEmg',
                  text: "I've got it.",
                  style: 'primary',
                  type: 'button',
                },
                {
                  name: 'escalateEmg',
                  text: 'I need to escalate!',
                  type: 'button',
                },
              ],
            },
          ],
        };
        bot.reply(message, emgTicketReply);
      } else {
        const ticketID = message.match[1];
        if (process.env.ticketSystemAPIKey) {
          bot.startTyping(message);
          winston.log('info', 'Looks like an API key for FreshService was provided. Will try to get ticket info...');
          const reqOptions = freshservice(connectionInfo.ticketSystemUrl, connectionInfo.ticketSystemAPIKey, 'GET', `${ticketID}.json`);
          request(reqOptions, (reqErr, res, body) => {
            winston.log('debug', 'Just sent request to FreshService.');
            if (err || res.statusCode !== 200) {
              winston.log('warning', 'Hazel could not get ticket info from FreshService. Sending link instead...');
              bot.reply(message, {
                text: url.resolve(connectionInfo.ticketSystemUrl, ticketID),
                username: 'hazel',
                icon_emoji: ':octopus:',
              });
            } else {
              winston.log('debug', 'Got a good response from FreshService. Sending ticket stub...');
              const ticketInfoMessage = {
                username: 'hazel',
                icon_emoji: ':octopus:',
                attachments: [{
                  title: `Ticket ${ticketID}: ${body.helpdesk_ticket.subject}`,
                  title_link: url.resolve(connectionInfo.ticketSystemUrl, ticketID),
                  fields: [
                    {
                      title: 'Description',
                      value: `${body.helpdesk_ticket.description.substring(0, 300)}...`,
                      short: false,
                    },
                    /*
                    {
                      title: 'Requester',
                      value: body.helpdesk_ticket.requester_name,
                      short: true,
                    },
                    {
                      title: 'Agent',
                      value: body.helpdesk_ticket.responder_name,
                      short: true,
                    },
                    {
                      title: 'Status',
                      value: body.helpdesk_ticket.status_name,
                      short: true,
                    },
                    {
                      title: 'Priority',
                      value: body.helpdesk_ticket.priority_name,
                      short: true,
                    },
                    */
                  ],
                }],
              };
              bot.reply(message, ticketInfoMessage);
            }
          });
        } else {
          winston.log('info', 'No API key provided, so just sending the URL to the ticket...');
          bot.reply(message, {
            text: url.resolve(connectionInfo.ticketSystemUrl, ticketID),
            username: 'hazel',
            icon_emoji: ':octopus:',
          });
        }
      }
    }
  });
});
// *** End Ticket Info/Link Handler *** //

// *** Begin Quote Handler *** //
controller.hears(['quote', 'proverb', 'wisdom'], ['direct_mention'], (bot, message) => {
  winston.log('info', 'Hazel heard someone mention her directly. Sending reply...');
  bot.reply(message, {
    username: 'hazel',
    icon_emoji: ':octopus:',
    text: quotes.getRandomQuote(),
  });
});
// *** End Quote Handler *** //

// *** Begin EMG Buttons Handler *** //
controller.on('interactive_message_callback', (bot, message) => {
  bot.api.users.info({ user: message.user }, (err, info) => {
    let buttonPresser = null;
    if (err) {
      winston.log('error', 'Could not get user name of button presser');
    } else {
      buttonPresser = info.user.name;
    }
    if (message.actions[0].name === 'acceptEmg') {
      bot.replyInteractive(message, {
        username: 'hazel',
        icon_emoji: ':octopus:',
        text: message.original_message.text,
        attachments: [
          {
            fallback: "(Sorry. I couldn't make the cool buttons this time.)",
            callback_id: 'emgResponse',
            actions: [
              {
                name: 'escalateEmg',
                text: 'I need to escalate!',
                type: 'button',
              },
            ],
          },
        ],
      });
      bot.reply(message, {
        text: `<!everyone> ${buttonPresser || 'A tech'} is taking care of this emergency.`,
        username: 'hazel',
        icon_emoji: ':octopus:',
      });
    }
    if (message.actions[0].name === 'escalateEmg') {
      bot.replyInteractive(message, {
        username: 'hazel',
        icon_emoji: ':octopus:',
        text: message.original_message.text,
        attachments: [
          {
            fallback: 'Tech needs to escalate!',
            text: '*Message sent to the escalation team for help.*',
            mrkdwn_in: ['text'],
          },
        ],
      });
      const escalationTeam = process.env.escalationTeam.split(/,\s?/);
      escalationTeam.forEach((person) => {
        bot.say({
          username: 'hazel',
          icon_emoji: ':octopus:',
          channel: `@${person}`,
          text: `${buttonPresser || 'The On Call Tech'} needs to escalate the emergency.`,
        });
      });
    }
  });
});
// *** End EMG Buttons Handler *** //
<commit_msg>stopped her from typing after she sent a message<commit_after>/**
 * Created by petersquicciarini on 3/9/17.
 */

const winston = require('winston');

if (!process.env.slackClientID || !process.env.slackClientSecret ||
  !process.env.ticketSystemUrl || !process.env.PORT || !process.env.mongoUri ||
  !process.env.escalationTeam) {
  winston.log('error', 'Please see README for required env vars.');
  process.exit();
}

const Botkit = require('botkit');
const mongoStorage = require('botkit-storage-mongo')({ mongoUri: process.env.mongoUri });
const url = require('url');
const quotes = require('./lib/quotes');
const freshservice = require('./lib/freshservice');
const request = require('request');

const connectionInfo = {
  slackClientID: process.env.slackClientID,
  slackClientSecret: process.env.slackClientSecret,
  ticketSystemUrl: process.env.ticketSystemUrl,
  ticketSystemAPIKey: process.env.ticketSystemAPIKey,
};
const controller = Botkit.slackbot({
  storage: mongoStorage,
}).configureSlackApp({
  clientId: connectionInfo.slackClientID,
  clientSecret: connectionInfo.slackClientSecret,
  scopes: ['bot', 'chat:write:bot', 'users:read', 'channels:read'],
});

controller.setupWebserver(process.env.PORT, () => {
  controller.createWebhookEndpoints(controller.webserver);
  controller.createHomepageEndpoint(controller.webserver);
  controller.createOauthEndpoints(controller.webserver, (err, req, res) => {
    if (err) {
      res.status(500).send(`ERROR: ${err}`);
    } else {
      res.send('Success!');
    }
  });
});

// just a simple way to make sure we don't
// connect to the RTM twice for the same team
const activeBots = {};
function trackBot(bot) {
  activeBots[bot.config.token] = bot;
}

controller.on('create_bot', (bot) => {
  if (activeBots[bot.config.token]) {
    // already online! do nothing.
  } else {
    bot.startRTM((err) => {
      if (!err) {
        trackBot(bot);
      }
    });
  }
});

controller.storage.teams.all((err, teams) => {
  if (err) {
    throw new Error(err);
  }
  // connect all teams with bots up to slack!
  Object.keys(teams).forEach((t) => {
    if (teams[t].bot) {
      controller.spawn(teams[t]).startRTM((startErr, bot) => {
        if (startErr) {
          winston.log('error', 'Could not connect to Slack RTM.');
        } else {
          trackBot(bot);
        }
      });
    }
  });
});
controller.on('rtm_open', () => {
  winston.log('info', '** The RTM api just connected!');
});
controller.on('rtm_close', (bot) => {
  winston.log('warn', '** The RTM api just closed');
  bot.startRTM((err) => {
    if (!err) {
      trackBot(bot);
    }
  });
});

// *** Begin Ticket Info/Link Handler *** //
controller.hears(['ticket ([0-9]+)'], ['ambient'], (bot, message) => {
  winston.log('info', 'Hazel heard a ticket # pattern. Crafting reply...');
  bot.api.channels.info({ channel: message.channel }, (err, info) => {
    if (err) {
      winston.log('error', 'Hazel could not get channel info.');
    } else {
      winston.log('debug', 'Hazel got the channel info.');
      if (info.channel.name === 'emg') {
        winston.log('info', 'We are in the EMG channel. Sending buttons...');
        const emgTicketReply = {
          username: 'hazel',
          icon_emoji: ':octopus:',
          text: "On Call Tech: Let everyone know you're taking care of it, and escalate if you need to:",
          attachments: [
            {
              fallback: "(Sorry. I couldn't make the cool buttons this time.)",
              callback_id: 'emgResponse',
              actions: [
                {
                  name: 'acceptEmg',
                  text: "I've got it.",
                  style: 'primary',
                  type: 'button',
                },
                {
                  name: 'escalateEmg',
                  text: 'I need to escalate!',
                  type: 'button',
                },
              ],
            },
          ],
        };
        bot.reply(message, emgTicketReply);
      } else {
        const ticketID = message.match[1];
        if (process.env.ticketSystemAPIKey) {
          bot.startTyping(message);
          winston.log('info', 'Looks like an API key for FreshService was provided. Will try to get ticket info...');
          const reqOptions = freshservice(connectionInfo.ticketSystemUrl, connectionInfo.ticketSystemAPIKey, 'GET', `${ticketID}.json`);
          request(reqOptions, (reqErr, res, body) => {
            winston.log('debug', 'Just sent request to FreshService.');
            if (err || res.statusCode !== 200) {
              winston.log('warning', 'Hazel could not get ticket info from FreshService. Sending link instead...');
              bot.reply(message, {
                text: url.resolve(connectionInfo.ticketSystemUrl, ticketID),
                username: 'hazel',
                icon_emoji: ':octopus:',
              });
            } else {
              winston.log('debug', 'Got a good response from FreshService. Sending ticket stub...');
              const ticketInfoMessage = {
                username: 'hazel',
                icon_emoji: ':octopus:',
                attachments: [{
                  title: `Ticket ${ticketID}: ${body.helpdesk_ticket.subject}`,
                  title_link: url.resolve(connectionInfo.ticketSystemUrl, ticketID),
                  fields: [
                    {
                      title: 'Description',
                      value: `${body.helpdesk_ticket.description.substring(0, 300)}...`,
                      short: false,
                    },
                    /*
                    {
                      title: 'Requester',
                      value: body.helpdesk_ticket.requester_name,
                      short: true,
                    },
                    {
                      title: 'Agent',
                      value: body.helpdesk_ticket.responder_name,
                      short: true,
                    },
                    {
                      title: 'Status',
                      value: body.helpdesk_ticket.status_name,
                      short: true,
                    },
                    {
                      title: 'Priority',
                      value: body.helpdesk_ticket.priority_name,
                      short: true,
                    },
                    */
                  ],
                }],
              };
              bot.stopTyping(message);
              bot.reply(message, ticketInfoMessage);
            }
          });
        } else {
          winston.log('info', 'No API key provided, so just sending the URL to the ticket...');
          bot.reply(message, {
            text: url.resolve(connectionInfo.ticketSystemUrl, ticketID),
            username: 'hazel',
            icon_emoji: ':octopus:',
          });
        }
      }
    }
  });
});
// *** End Ticket Info/Link Handler *** //

// *** Begin Quote Handler *** //
controller.hears(['quote', 'proverb', 'wisdom'], ['direct_mention'], (bot, message) => {
  winston.log('info', 'Hazel heard someone mention her directly. Sending reply...');
  bot.reply(message, {
    username: 'hazel',
    icon_emoji: ':octopus:',
    text: quotes.getRandomQuote(),
  });
});
// *** End Quote Handler *** //

// *** Begin EMG Buttons Handler *** //
controller.on('interactive_message_callback', (bot, message) => {
  bot.api.users.info({ user: message.user }, (err, info) => {
    let buttonPresser = null;
    if (err) {
      winston.log('error', 'Could not get user name of button presser');
    } else {
      buttonPresser = info.user.name;
    }
    if (message.actions[0].name === 'acceptEmg') {
      bot.replyInteractive(message, {
        username: 'hazel',
        icon_emoji: ':octopus:',
        text: message.original_message.text,
        attachments: [
          {
            fallback: "(Sorry. I couldn't make the cool buttons this time.)",
            callback_id: 'emgResponse',
            actions: [
              {
                name: 'escalateEmg',
                text: 'I need to escalate!',
                type: 'button',
              },
            ],
          },
        ],
      });
      bot.reply(message, {
        text: `<!everyone> ${buttonPresser || 'A tech'} is taking care of this emergency.`,
        username: 'hazel',
        icon_emoji: ':octopus:',
      });
    }
    if (message.actions[0].name === 'escalateEmg') {
      bot.replyInteractive(message, {
        username: 'hazel',
        icon_emoji: ':octopus:',
        text: message.original_message.text,
        attachments: [
          {
            fallback: 'Tech needs to escalate!',
            text: '*Message sent to the escalation team for help.*',
            mrkdwn_in: ['text'],
          },
        ],
      });
      const escalationTeam = process.env.escalationTeam.split(/,\s?/);
      escalationTeam.forEach((person) => {
        bot.say({
          username: 'hazel',
          icon_emoji: ':octopus:',
          channel: `@${person}`,
          text: `${buttonPresser || 'The On Call Tech'} needs to escalate the emergency.`,
        });
      });
    }
  });
});
// *** End EMG Buttons Handler *** //
<|endoftext|>


<commit_before>let toggleNavi = function() {
    if (!$('.navibar').hasClass('hidden')) {
        $('.navibar').addClass('hidden');
    } else {
        $('.navibar').removeClass('hidden');
    }
}

let checkWidth = function() {
    if ($(window).width() >= 700) {
        $('.navibar').removeClass('hidden');
        let homebottom = 1 / 2 * ($('#home').offset().top + $('#home').height());
        $(window).on('scroll', function() {
            // we round here to reduce a little workload
            let stop = Math.round($(window).scrollTop());
            if (stop > homebottom) {
                if (!$('.navibar').hasClass('navi-scroll')) {
                    $('.navibar').addClass('navi-scroll');
                }
            } else {
                $('.navibar').removeClass('navi-scroll');
            }
        });
    }
    if ($(window).width() < 700) {
        $('.navi-elem').on('click', function(){
          $('.navibar').addClass('hidden');
        });
    }
}

$('#toggle-button').on('click', toggleNavi);

$('a[href*=\\#]').on('click', function(event){
    event.preventDefault();
    $('html,body').animate({scrollTop:$(this.hash).offset().top}, 500);
});

let navElems = document.getElementsByClassName('navi-elem');
let navElemsArr = Array.from(navElems);
navElemsArr.forEach(el => {
  el.onmouseover = () => el.classList.add('uppercase');
  el.onmouseleave = () => el.classList.remove('uppercase');
})

checkWidth();
$(window).resize(checkWidth);

AOS.init({
  startEvent: 'load'
});
<commit_msg>[30c] Problem with AOS<commit_after>import AOS from 'aos';

let toggleNavi = function() {
    if (!$('.navibar').hasClass('hidden')) {
        $('.navibar').addClass('hidden');
    } else {
        $('.navibar').removeClass('hidden');
    }
}

let checkWidth = function() {
    if ($(window).width() >= 700) {
        $('.navibar').removeClass('hidden');
        let homebottom = 1 / 2 * ($('#home').offset().top + $('#home').height());
        $(window).on('scroll', function() {
            // we round here to reduce a little workload
            let stop = Math.round($(window).scrollTop());
            if (stop > homebottom) {
                if (!$('.navibar').hasClass('navi-scroll')) {
                    $('.navibar').addClass('navi-scroll');
                }
            } else {
                $('.navibar').removeClass('navi-scroll');
            }
        });
    }
    if ($(window).width() < 700) {
        $('.navi-elem').on('click', function(){
          $('.navibar').addClass('hidden');
        });
    }
}

$('#toggle-button').on('click', toggleNavi);

$('a[href*=\\#]').on('click', function(event){
    event.preventDefault();
    $('html,body').animate({scrollTop:$(this.hash).offset().top}, 500);
});

let navElems = document.getElementsByClassName('navi-elem');
let navElemsArr = Array.from(navElems);
navElemsArr.forEach(el => {
  el.onmouseover = () => el.classList.add('uppercase');
  el.onmouseleave = () => el.classList.remove('uppercase');
})

checkWidth();
$(window).resize(checkWidth);

AOS.init({
  startEvent: 'load'
});
<|endoftext|>


<commit_before>function EventEmitter() {
	this._events = {};
};

EventEmitter.EventEmitter = EventEmitter;

module.exports = EventEmitter;

EventEmitter.listenerCount = function (emitter, evt) {
	var handlers = emitter._events[evt];
	return handlers ? handlers.length : 0;
};

EventEmitter.prototype.on = function (evt, fn) {
	if (typeof fn !== 'function') {
		console.warn('Tried to register non-function', fn, 'as event handler for event:', evt);
		return this;
	}

	this.emit('newListener', evt, fn);

	var allHandlers = this._events;
	var evtHandlers = allHandlers[evt];
	if (evtHandlers === undefined) {
		// first event handler for this event type
		allHandlers[evt] = [fn];
		return this;
	}

	evtHandlers.push(fn);
	return this;
};

EventEmitter.prototype.addListener = EventEmitter.prototype.on;

EventEmitter.prototype.once = function (evt, fn) {
	if (!fn.once) {
		fn.once = 1;
	} else {
		fn.once += 1;
	}

	return this.on(evt, fn);
};

EventEmitter.prototype.setMaxListeners = function () {
	console.warn('Method setMaxListeners not supported, there is no limit to the number of listeners');
};

EventEmitter.prototype.removeListener = function (evt, handler) {
	// like node.js, we only remove a single listener at a time, even if it occurs multiple times

	var handlers = this._events[evt];
	if (handlers !== undefined) {
		var index = handlers.indexOf(handler);
		if (index !== -1) {
			handlers.splice(index, 1);
			this.emit('removeListener', evt, handler);
			if (handlers.length === 0) {
				delete this._events[evt];
			}
		}
	}
	return this;
};

EventEmitter.prototype.removeAllListeners = function (evt) {
	if (evt) {
		delete this._events[evt];
	} else {
		this._events = {};
	}
	return this;
};

EventEmitter.prototype.hasListeners = function (evt) {
	return this._events[evt] !== undefined;
};

EventEmitter.prototype.listeners = function (evt) {
	var handlers = this._events[evt];
	if (handlers !== undefined) {
		return handlers.slice();
	}

	return [];
};

var slice = Array.prototype.slice;

EventEmitter.prototype.emit = function (evt) {
	var handlers = this._events[evt];
	if (handlers === undefined) {
		return false;
	}

	// copy handlers into a new array, so that handler removal doesn't affect array length
	handlers = handlers.slice();

	var hadListener = false;
	var args = slice.call(arguments, 1);
	for (var i = 0, len = handlers.length; i < len; i++) {
		var handler = handlers[i];
		if (handler === undefined) {
			continue;
		}

		handler.apply(this, args);
		hadListener = true;

		if (handler.once) {
			if (handler.once > 1) {
				handler.once--;
			} else {
				delete handler.once;
			}

			this.removeListener(evt, handler);
		}
	}

	return hadListener;
};
<commit_msg>Only emit removeListener after all mutations are done<commit_after>function EventEmitter() {
	this._events = {};
};

EventEmitter.EventEmitter = EventEmitter;

module.exports = EventEmitter;

EventEmitter.listenerCount = function (emitter, evt) {
	var handlers = emitter._events[evt];
	return handlers ? handlers.length : 0;
};

EventEmitter.prototype.on = function (evt, fn) {
	if (typeof fn !== 'function') {
		console.warn('Tried to register non-function', fn, 'as event handler for event:', evt);
		return this;
	}

	// we emit first, because if evt is "newListener" it would go recursive
	this.emit('newListener', evt, fn);

	var allHandlers = this._events;
	var evtHandlers = allHandlers[evt];
	if (evtHandlers === undefined) {
		// first event handler for this event type
		allHandlers[evt] = [fn];
	} else {
		evtHandlers.push(fn);
	}

	return this;
};

EventEmitter.prototype.addListener = EventEmitter.prototype.on;

EventEmitter.prototype.once = function (evt, fn) {
	if (!fn.once) {
		fn.once = 1;
	} else {
		fn.once += 1;
	}

	return this.on(evt, fn);
};

EventEmitter.prototype.setMaxListeners = function () {
	console.warn('Method setMaxListeners not supported, there is no limit to the number of listeners');
};

EventEmitter.prototype.removeListener = function (evt, handler) {
	// like node.js, we only remove a single listener at a time, even if it occurs multiple times

	var handlers = this._events[evt];
	if (handlers !== undefined) {
		var index = handlers.indexOf(handler);
		if (index !== -1) {
			handlers.splice(index, 1);

			if (handlers.length === 0) {
				delete this._events[evt];
			}

			this.emit('removeListener', evt, handler);
		}
	}
	return this;
};

EventEmitter.prototype.removeAllListeners = function (evt) {
	if (evt) {
		delete this._events[evt];
	} else {
		this._events = {};
	}
	return this;
};

EventEmitter.prototype.hasListeners = function (evt) {
	return this._events[evt] !== undefined;
};

EventEmitter.prototype.listeners = function (evt) {
	var handlers = this._events[evt];
	if (handlers !== undefined) {
		return handlers.slice();
	}

	return [];
};

var slice = Array.prototype.slice;

EventEmitter.prototype.emit = function (evt) {
	var handlers = this._events[evt];
	if (handlers === undefined) {
		return false;
	}

	// copy handlers into a new array, so that handler removal doesn't affect array length
	handlers = handlers.slice();

	var hadListener = false;
	var args = slice.call(arguments, 1);
	for (var i = 0, len = handlers.length; i < len; i++) {
		var handler = handlers[i];
		if (handler === undefined) {
			continue;
		}

		handler.apply(this, args);
		hadListener = true;

		if (handler.once) {
			if (handler.once > 1) {
				handler.once--;
			} else {
				delete handler.once;
			}

			this.removeListener(evt, handler);
		}
	}

	return hadListener;
};
<|endoftext|>


<commit_before>
module.exports = function (str) {
  var q = []
  return {
    insertAfter: function (index, s) {
      //order must be stable. so find the last insert for this
      var l = q.length

      if(!l)
        return q.push([index, s]), this

      for(var i = 0; i < l && q[i][0] <= index; i++)
        ;

      q.splice(i, 0, [index, s])
      return this
    },

    insertBefore: function (index, s) {
      //order must be stable. so find the last insert for this
      var l = q.length
      if(!l)
        return q.push([index, s]), this

      //find the index of the fist queued item with index.
      var i = 0
      for(; i < l && q[i][0] < index; i++)
        ;

      q.splice(i, 0, [index, s])
      return this
    },

    wrap: function (rx, before, after) {
      if(Array.isArray(before))
        after = before[1], before = before[0]
      if('undefined' == typeof after)
        after = before
      rx.global = true
      rx.lastIndex = 0

      var m = rx.exec(str)
      if(!m) return this
      do {
        if(!m) return this
        this.insertBefore(m.index + m[0].length, after)
        this.insertAfter(m.index, before)
      } while(rx.global && (m = rx.exec(str)))

      return this
    },

    apply: function () {
      var l = q.length, f = str

      while(l--) {
        var i = q[l][0], s = q[l][1]
        f = f.substring(0, i) + s + f.substring(i)
      }
      return f
    },
    queue: q,
    toString: function () {
      return str
    }
  }
}
<commit_msg>expose the string<commit_after>
module.exports = function (str) {
  var q = []
  return {
    insertAfter: function (index, s) {
      //order must be stable. so find the last insert for this
      var l = q.length

      if(!l)
        return q.push([index, s]), this

      for(var i = 0; i < l && q[i][0] <= index; i++)
        ;

      q.splice(i, 0, [index, s])
      return this
    },

    insertBefore: function (index, s) {
      //order must be stable. so find the last insert for this
      var l = q.length
      if(!l)
        return q.push([index, s]), this

      //find the index of the fist queued item with index.
      var i = 0
      for(; i < l && q[i][0] < index; i++)
        ;

      q.splice(i, 0, [index, s])
      return this
    },

    wrap: function (rx, before, after) {
      if(Array.isArray(before))
        after = before[1], before = before[0]
      if('undefined' == typeof after)
        after = before
      rx.global = true
      rx.lastIndex = 0

      var m = rx.exec(str)
      if(!m) return this
      do {
        if(!m) return this
        this.insertBefore(m.index + m[0].length, after)
        this.insertAfter(m.index, before)
      } while(rx.global && (m = rx.exec(str)))

      return this
    },

    apply: function () {
      var l = q.length, f = this.string

      while(l--) {
        var i = q[l][0], s = q[l][1]
        f = f.substring(0, i) + s + f.substring(i)
      }
      return f
    },
    queue: q,
    toString: function () {
      return str
    },
    string: str
  }
}
<|endoftext|>


<commit_before>/**
 * Module dependencies
 */
var expat = require('node-expat')
  , util = require('util')
  , debug = require('debug')('feed-stream')
  , stream = require('stream');

// Default options
var defaults = {
  blacklist: [],
  rename: {},
  productElement: 'product',
  newlines: false,
  lowercaseKeys: false,
  trim: false,
  json: false
}

var FeedStream = module.exports = function (opts) {
  // Grab opts
  opts = this.opts = opts || {};

  // Set default options
  for (var k in defaults) {
    if (!opts[k]) opts[k] = defaults[k];
  }

  // In progress object
  this.obj = {};
  // In progress key and value
  this.key = this.val = '';

  // Initialize state
  this.state = 'none';

  // Setup parser
  var parser = this.parser = new expat.Parser('UTF-8');

  // Handle element start
  parser.on('startElement', this._handleStart.bind(this));

  // Handle text
  parser.on('text', this._handleText.bind(this));

  // Handle element end
  parser.on('endElement', this._handleEnd.bind(this));

  // Handle end events
  this.on('end', function () {
    if (opts.json) this.push(']');
  });

  // Inherit from duplex stream
  stream.Duplex.call(this, opts);

  // Add opening [ if in json mode
  if (opts.json) this.push('[');
};
util.inherits(FeedStream, stream.Duplex);

FeedStream.prototype._handleStart = function (name, attrs) {
  var opts = this.opts
    , state = this.state;

  debug('start state: %s, name: %s', this.state, name);
  if (state === 'none') {
    if (name === opts.productElement) this.state = 'product';
  } else if (state === 'product') {
    this.state = 'item', this.key = name;
  }
};

FeedStream.prototype._handleText = function (text) {
  debug('text state: %s, text: %s', this.state, text);
  if (this.state === 'item') {
    this.val += text;
  }
};

FeedStream.prototype._handleEnd = function (name) {
  var opts = this.opts
    , state = this.state
    , product = opts.productElement
    , rename = opts.rename
    , blacklist = opts.blacklist
    , newlines = opts.newlines
    , lowercase = opts.lowercaseKeys
    , json = opts.json
    , trim = opts.trim;

  debug('end state: %s, name: %s', this.state, name);
  if (state === 'product' && name === product) {
    // Finished a product, pass it on to consumers
    this.push(JSON.stringify(this.obj) + (json ? ',' : '') + (newlines ? '\n' : ''));

    // Reset state and object
    this.state = 'none', this.obj = {};
  } else if (state === 'item') {
    // Rename key, if applicable
    if (rename[this.key]) this.key = rename[this.key];

    // Lowercase keys, if applicable
    if (lowercase) this.key = this.key.toLowerCase();

    // Trim value, if applicable
    if (trim) this.val = this.val.trim();

    // Add key to object, if allowed
    if (!~blacklist.indexOf(this.key)) {
      this.obj[this.key] = this.val;
    }

    // Finished a key-value pair, move back into the product state
    this.state = 'product';

    // Reset key and val
    this.key = this.val = '';
  }
};

FeedStream.prototype._write = function (chunk, encoding, cb) {
  this.parser.write(chunk);
  cb();
};

FeedStream.prototype._read = function () {
  return;
};

FeedStream.prototype.end = function () {
  // Just emit end at stream end
  return this.emit('end');
};
<commit_msg>Add extractAttrs option<commit_after>/**
 * Module dependencies
 */
var expat = require('node-expat')
  , util = require('util')
  , debug = require('debug')('feed-stream')
  , stream = require('stream');

// Default options
var defaults = {
  blacklist: [],
  rename: {},
  productElement: 'product',
  newlines: false,
  lowercaseKeys: false,
  trim: false,
  json: false
}

var FeedStream = module.exports = function (opts) {
  // Grab opts
  opts = this.opts = opts || {};

  // Set default options
  for (var k in defaults) {
    if (!opts[k]) opts[k] = defaults[k];
  }

  // In progress object
  this.obj = {};
  // In progress key and value
  this.key = this.val = '';

  // Initialize state
  this.state = 'none';

  // Setup parser
  var parser = this.parser = new expat.Parser('UTF-8');

  // Handle element start
  parser.on('startElement', this._handleStart.bind(this));

  // Handle text
  parser.on('text', this._handleText.bind(this));

  // Handle element end
  parser.on('endElement', this._handleEnd.bind(this));

  // Handle end events
  this.on('end', function () {
    if (opts.json) this.push(']');
  });

  // Inherit from duplex stream
  stream.Duplex.call(this, opts);

  // Add opening [ if in json mode
  if (opts.json) this.push('[');
};
util.inherits(FeedStream, stream.Duplex);

FeedStream.prototype._handleStart = function (name, attrs) {
  var opts = this.opts
    , state = this.state;

  debug('start state: %s, name: %s', this.state, name);
  if (state === 'none') {
    if (name === opts.productElement) this.state = 'product';
  } else if (state === 'product') {
    this.state = 'item', this.key = name;
    if (this.opts.extractAttrs) extend(this.obj, attrs);
  }
};

FeedStream.prototype._handleText = function (text) {
  debug('text state: %s, text: %s', this.state, text);
  if (this.state === 'item') {
    this.val += text;
  }
};

FeedStream.prototype._handleEnd = function (name) {
  var opts = this.opts
    , state = this.state
    , product = opts.productElement
    , rename = opts.rename
    , blacklist = opts.blacklist
    , newlines = opts.newlines
    , lowercase = opts.lowercaseKeys
    , json = opts.json
    , trim = opts.trim;

  debug('end state: %s, name: %s', this.state, name);
  if (state === 'product' && name === product) {
    // Finished a product, pass it on to consumers
    this.push(JSON.stringify(this.obj) + (json ? ',' : '') + (newlines ? '\n' : ''));

    // Reset state and object
    this.state = 'none', this.obj = {};
  } else if (state === 'item') {
    // Rename key, if applicable
    if (rename[this.key]) this.key = rename[this.key];

    // Lowercase keys, if applicable
    if (lowercase) this.key = this.key.toLowerCase();

    // Trim value, if applicable
    if (trim) this.val = this.val.trim();

    // Add key to object, if allowed
    if (!~blacklist.indexOf(this.key)) {
      this.obj[this.key] = this.val;
    }

    // Finished a key-value pair, move back into the product state
    this.state = 'product';

    // Reset key and val
    this.key = this.val = '';
  }
};

FeedStream.prototype._write = function (chunk, encoding, cb) {
  this.parser.write(chunk);
  cb();
};

FeedStream.prototype._read = function () {
  return;
};

FeedStream.prototype.end = function () {
  // Just emit end at stream end
  return this.emit('end');
};

var extend = function () {
  var base = arguments[0]
    , others = Array.prototype.slice.call(arguments, 1);

  for (var i = 0, len = others.length; i < len; i++) {
    var o = others[i];

    for (var k in o) {
      base[k] = o[k];
    }
  }
};
<|endoftext|>


<commit_before>var tar = require('tar-stream')
var pump = require('pump')
var mkdirp = require('mkdirp')
var fs = require('fs')
var path = require('path')
var os = require('os')

var win32 = os.platform() === 'win32'

var noop = function () {}

var echo = function (name) {
  return name
}

var normalize = !win32 ? echo : function (name) {
  return name.replace(/\\/g, '/').replace(/:/g, '_')
}

var statAll = function (fs, stat, cwd, ignore, entries) {
  var queue = entries || ['.']

  return function loop (callback) {
    if (!queue.length) return callback()
    var next = queue.shift()
    var nextAbs = path.join(cwd, next)

    stat(nextAbs, function (err, stat) {
      if (err) return callback(err)

      if (!stat.isDirectory()) return callback(null, next, stat)

      fs.readdir(nextAbs, function (err, files) {
        if (err) return callback(err)

        for (var i = 0; i < files.length; i++) {
          if (!ignore(path.join(cwd, next, files[i]))) queue.push(path.join(next, files[i]))
        }

        callback(null, next, stat)
      })
    })
  }
}

var strip = function (map, level) {
  return function (header) {
    header.name = header.name.split('/').slice(level).join('/')
    if (header.linkname) header.linkname = header.linkname.split('/').slice(level).join('/')
    return map(header)
  }
}

exports.pack = function (cwd, opts) {
  if (!cwd) cwd = '.'
  if (!opts) opts = {}

  var xfs = opts.fs || fs
  var ignore = opts.ignore || opts.filter || noop
  var map = opts.map || noop
  var mapStream = opts.mapStream || echo
  var statNext = statAll(xfs, opts.dereference ? xfs.stat : xfs.lstat, cwd, ignore, opts.entries)
  var strict = opts.strict !== false
  var dmode = typeof opts.dmode === 'number' ? opts.dmode : 0
  var fmode = typeof opts.fmode === 'number' ? opts.fmode : 0
  var pack = opts.pack || tar.pack()

  if (opts.strip) map = strip(map, opts.strip)

  if (opts.readable) {
    dmode |= parseInt(555, 8)
    fmode |= parseInt(444, 8)
  }
  if (opts.writable) {
    dmode |= parseInt(333, 8)
    fmode |= parseInt(222, 8)
  }

  var onlink = function (filename, header) {
    xfs.readlink(path.join(cwd, filename), function (err, linkname) {
      if (err) return pack.destroy(err)
      header.linkname = normalize(linkname)
      pack.entry(header, onnextentry)
    })
  }

  var onstat = function (err, filename, stat) {
    if (err) return pack.destroy(err)
    if (!filename) return pack.finalize()

    if (stat.isSocket()) return onnextentry() // tar does not support sockets...

    var header = {
      name: normalize(filename),
      mode: stat.mode | (stat.isDirectory() ? dmode : fmode),
      mtime: stat.mtime,
      size: stat.size,
      type: 'file',
      uid: stat.uid,
      gid: stat.gid
    }

    header = map(header) || header

    if (stat.isDirectory()) {
      header.size = 0
      header.type = 'directory'
      return pack.entry(header, onnextentry)
    }

    if (stat.isSymbolicLink()) {
      header.size = 0
      header.type = 'symlink'
      return onlink(filename, header)
    }

    // TODO: add fifo etc...

    if (!stat.isFile()) {
      if (strict) return pack.destroy(new Error('unsupported type for ' + filename))
      return onnextentry()
    }

    var entry = pack.entry(header, onnextentry)
    if (!entry) return

    var rs = mapStream(xfs.createReadStream(path.join(cwd, filename)), header)

    rs.on('error', function (err) { // always forward errors on destroy
      entry.destroy(err)
    })

    pump(rs, entry)
  }

  var onnextentry = function (err) {
    if (err) return pack.destroy(err)
    statNext(onstat)
  }

  onnextentry()

  return pack
}

var head = function (list) {
  return list.length ? list[list.length - 1] : null
}

var processGetuid = function () {
  return process.getuid ? process.getuid() : -1
}

var processUmask = function () {
  return process.umask ? process.umask() : 0
}

exports.extract = function (cwd, opts) {
  if (!cwd) cwd = '.'
  if (!opts) opts = {}

  var xfs = opts.fs || fs
  var ignore = opts.ignore || opts.filter || noop
  var map = opts.map || noop
  var mapStream = opts.mapStream || echo
  var own = opts.chown !== false && !win32 && processGetuid() === 0
  var extract = opts.extract || tar.extract()
  var stack = []
  var now = new Date()
  var umask = typeof opts.umask === 'number' ? ~opts.umask : ~processUmask()
  var dmode = typeof opts.dmode === 'number' ? opts.dmode : 0
  var fmode = typeof opts.fmode === 'number' ? opts.fmode : 0
  var strict = opts.strict !== false

  if (opts.strip) map = strip(map, opts.strip)

  if (opts.readable) {
    dmode |= parseInt(555, 8)
    fmode |= parseInt(444, 8)
  }
  if (opts.writable) {
    dmode |= parseInt(333, 8)
    fmode |= parseInt(222, 8)
  }

  var utimesParent = function (name, cb) { // we just set the mtime on the parent dir again everytime we write an entry
    var top
    while ((top = head(stack)) && name.slice(0, top[0].length) !== top[0]) stack.pop()
    if (!top) return cb()
    xfs.utimes(top[0], now, top[1], cb)
  }

  var utimes = function (name, header, cb) {
    if (opts.utimes === false) return cb()

    if (header.type === 'directory') return xfs.utimes(name, now, header.mtime, cb)
    if (header.type === 'symlink') return utimesParent(name, cb) // TODO: how to set mtime on link?

    xfs.utimes(name, now, header.mtime, function (err) {
      if (err) return cb(err)
      utimesParent(name, cb)
    })
  }

  var chperm = function (name, header, cb) {
    var link = header.type === 'symlink'
    var chmod = link ? xfs.lchmod : xfs.chmod
    var chown = link ? xfs.lchown : xfs.chown

    if (!chmod) return cb()
    chmod(name, (header.mode | (header.type === 'directory' ? dmode : fmode)) & umask, function (err) {
      if (err) return cb(err)
      if (!own) return cb()
      if (!chown) return cb()
      chown(name, header.uid, header.gid, cb)
    })
  }

  extract.on('entry', function (header, stream, next) {
    header = map(header) || header
    header.name = normalize(header.name)
    var name = path.join(cwd, path.join('/', header.name))

    if (ignore(name)) {
      stream.resume()
      return next()
    }

    var stat = function (err) {
      if (err) return next(err)
      if (win32) return next()
      utimes(name, header, function (err) {
        if (err) return next(err)
        chperm(name, header, next)
      })
    }

    var onlink = function () {
      if (win32) return next() // skip symlinks on win for now before it can be tested
      xfs.unlink(name, function () {
        xfs.symlink(header.linkname, name, stat)
      })
    }

    var onfile = function () {
      var ws = xfs.createWriteStream(name)
      var rs = mapStream(stream, header)

      ws.on('error', function (err) { // always forward errors on destroy
        rs.destroy(err)
      })

      pump(rs, ws, function (err) {
        if (err) return next(err)
        ws.on('close', stat)
      })
    }

    if (header.type === 'directory') {
      stack.push([name, header.mtime])
      return mkdirp(name, {fs: xfs}, stat)
    }

    mkdirp(path.dirname(name), {fs: xfs}, function (err) {
      if (err) return next(err)
      if (header.type === 'symlink') return onlink()

      if (header.type !== 'file') {
        if (strict) return next(new Error('unsupported type for ' + name + ' (' + header.type + ')'))
        stream.resume()
        return next()
      }

      onfile()
    })
  })

  return extract
}
<commit_msg>Restore the call on utimes on win32 platform<commit_after>var tar = require('tar-stream')
var pump = require('pump')
var mkdirp = require('mkdirp')
var fs = require('fs')
var path = require('path')
var os = require('os')

var win32 = os.platform() === 'win32'

var noop = function () {}

var echo = function (name) {
  return name
}

var normalize = !win32 ? echo : function (name) {
  return name.replace(/\\/g, '/').replace(/:/g, '_')
}

var statAll = function (fs, stat, cwd, ignore, entries) {
  var queue = entries || ['.']

  return function loop (callback) {
    if (!queue.length) return callback()
    var next = queue.shift()
    var nextAbs = path.join(cwd, next)

    stat(nextAbs, function (err, stat) {
      if (err) return callback(err)

      if (!stat.isDirectory()) return callback(null, next, stat)

      fs.readdir(nextAbs, function (err, files) {
        if (err) return callback(err)

        for (var i = 0; i < files.length; i++) {
          if (!ignore(path.join(cwd, next, files[i]))) queue.push(path.join(next, files[i]))
        }

        callback(null, next, stat)
      })
    })
  }
}

var strip = function (map, level) {
  return function (header) {
    header.name = header.name.split('/').slice(level).join('/')
    if (header.linkname) header.linkname = header.linkname.split('/').slice(level).join('/')
    return map(header)
  }
}

exports.pack = function (cwd, opts) {
  if (!cwd) cwd = '.'
  if (!opts) opts = {}

  var xfs = opts.fs || fs
  var ignore = opts.ignore || opts.filter || noop
  var map = opts.map || noop
  var mapStream = opts.mapStream || echo
  var statNext = statAll(xfs, opts.dereference ? xfs.stat : xfs.lstat, cwd, ignore, opts.entries)
  var strict = opts.strict !== false
  var dmode = typeof opts.dmode === 'number' ? opts.dmode : 0
  var fmode = typeof opts.fmode === 'number' ? opts.fmode : 0
  var pack = opts.pack || tar.pack()

  if (opts.strip) map = strip(map, opts.strip)

  if (opts.readable) {
    dmode |= parseInt(555, 8)
    fmode |= parseInt(444, 8)
  }
  if (opts.writable) {
    dmode |= parseInt(333, 8)
    fmode |= parseInt(222, 8)
  }

  var onlink = function (filename, header) {
    xfs.readlink(path.join(cwd, filename), function (err, linkname) {
      if (err) return pack.destroy(err)
      header.linkname = normalize(linkname)
      pack.entry(header, onnextentry)
    })
  }

  var onstat = function (err, filename, stat) {
    if (err) return pack.destroy(err)
    if (!filename) return pack.finalize()

    if (stat.isSocket()) return onnextentry() // tar does not support sockets...

    var header = {
      name: normalize(filename),
      mode: stat.mode | (stat.isDirectory() ? dmode : fmode),
      mtime: stat.mtime,
      size: stat.size,
      type: 'file',
      uid: stat.uid,
      gid: stat.gid
    }

    header = map(header) || header

    if (stat.isDirectory()) {
      header.size = 0
      header.type = 'directory'
      return pack.entry(header, onnextentry)
    }

    if (stat.isSymbolicLink()) {
      header.size = 0
      header.type = 'symlink'
      return onlink(filename, header)
    }

    // TODO: add fifo etc...

    if (!stat.isFile()) {
      if (strict) return pack.destroy(new Error('unsupported type for ' + filename))
      return onnextentry()
    }

    var entry = pack.entry(header, onnextentry)
    if (!entry) return

    var rs = mapStream(xfs.createReadStream(path.join(cwd, filename)), header)

    rs.on('error', function (err) { // always forward errors on destroy
      entry.destroy(err)
    })

    pump(rs, entry)
  }

  var onnextentry = function (err) {
    if (err) return pack.destroy(err)
    statNext(onstat)
  }

  onnextentry()

  return pack
}

var head = function (list) {
  return list.length ? list[list.length - 1] : null
}

var processGetuid = function () {
  return process.getuid ? process.getuid() : -1
}

var processUmask = function () {
  return process.umask ? process.umask() : 0
}

exports.extract = function (cwd, opts) {
  if (!cwd) cwd = '.'
  if (!opts) opts = {}

  var xfs = opts.fs || fs
  var ignore = opts.ignore || opts.filter || noop
  var map = opts.map || noop
  var mapStream = opts.mapStream || echo
  var own = opts.chown !== false && !win32 && processGetuid() === 0
  var extract = opts.extract || tar.extract()
  var stack = []
  var now = new Date()
  var umask = typeof opts.umask === 'number' ? ~opts.umask : ~processUmask()
  var dmode = typeof opts.dmode === 'number' ? opts.dmode : 0
  var fmode = typeof opts.fmode === 'number' ? opts.fmode : 0
  var strict = opts.strict !== false

  if (opts.strip) map = strip(map, opts.strip)

  if (opts.readable) {
    dmode |= parseInt(555, 8)
    fmode |= parseInt(444, 8)
  }
  if (opts.writable) {
    dmode |= parseInt(333, 8)
    fmode |= parseInt(222, 8)
  }

  var utimesParent = function (name, cb) { // we just set the mtime on the parent dir again everytime we write an entry
    var top
    while ((top = head(stack)) && name.slice(0, top[0].length) !== top[0]) stack.pop()
    if (!top) return cb()
    xfs.utimes(top[0], now, top[1], cb)
  }

  var utimes = function (name, header, cb) {
    if (opts.utimes === false) return cb()

    if (header.type === 'directory') return xfs.utimes(name, now, header.mtime, cb)
    if (header.type === 'symlink') return utimesParent(name, cb) // TODO: how to set mtime on link?

    xfs.utimes(name, now, header.mtime, function (err) {
      if (err) return cb(err)
      utimesParent(name, cb)
    })
  }

  var chperm = function (name, header, cb) {
    var link = header.type === 'symlink'
    var chmod = link ? xfs.lchmod : xfs.chmod
    var chown = link ? xfs.lchown : xfs.chown

    if (!chmod) return cb()
    chmod(name, (header.mode | (header.type === 'directory' ? dmode : fmode)) & umask, function (err) {
      if (err) return cb(err)
      if (!own) return cb()
      if (!chown) return cb()
      chown(name, header.uid, header.gid, cb)
    })
  }

  extract.on('entry', function (header, stream, next) {
    header = map(header) || header
    header.name = normalize(header.name)
    var name = path.join(cwd, path.join('/', header.name))

    if (ignore(name)) {
      stream.resume()
      return next()
    }

    var stat = function (err) {
      if (err) return next(err)
      utimes(name, header, function (err) {
        if (err) return next(err)
        if (win32) return next()
        chperm(name, header, next)
      })
    }

    var onlink = function () {
      if (win32) return next() // skip symlinks on win for now before it can be tested
      xfs.unlink(name, function () {
        xfs.symlink(header.linkname, name, stat)
      })
    }

    var onfile = function () {
      var ws = xfs.createWriteStream(name)
      var rs = mapStream(stream, header)

      ws.on('error', function (err) { // always forward errors on destroy
        rs.destroy(err)
      })

      pump(rs, ws, function (err) {
        if (err) return next(err)
        ws.on('close', stat)
      })
    }

    if (header.type === 'directory') {
      stack.push([name, header.mtime])
      return mkdirp(name, {fs: xfs}, stat)
    }

    mkdirp(path.dirname(name), {fs: xfs}, function (err) {
      if (err) return next(err)
      if (header.type === 'symlink') return onlink()

      if (header.type !== 'file') {
        if (strict) return next(new Error('unsupported type for ' + name + ' (' + header.type + ')'))
        stream.resume()
        return next()
      }

      onfile()
    })
  })

  return extract
}
<|endoftext|>


<commit_before>
var Parser = require('jsonparse')
  , Stream = require('stream').Stream

/*

  the value of this.stack that creationix's jsonparse has is weird.

  it makes this code ugly, but his problem is way harder that mine,
  so i'll forgive him.

*/

exports.parse = function (path) {

  var stream = new Stream()
  var parser = new Parser()
  var count = 0
  if(!path.length)
    path = null
  parser.onValue = function () {
    if(!this.root && this.stack.length == 1){
      stream.root = this.value
      }
    if(!path || this.stack.length !== path.length)
      return
    var _path = []
    for( var i = 0; i < (path.length - 1); i++) {
      var key = path[i]
      var c = this.stack[1 + (+i)]

      if(!c) {
        return
      }
      var m = check(key, c.key)
      _path.push(c.key)

       if(!m)
        return

    }
    var c = this

    var key = path[path.length - 1]
      var m = check(key, c.key)
     if(!m)
      return
      _path.push(c.key)

  count ++
  stream.emit('data', this.value[this.key])
  }

  parser.onError = function (err) {
    stream.emit('error', err)
  }
  stream.readable = true
  stream.writable = true
  stream.write = function (chunk) {
    if('string' === typeof chunk) {
      if ('undefined' === typeof Buffer) {
        var buf = new Array(chunk.length)
        for (var i = 0; i < chunk.length; i++) buf[i] = chunk.charCodeAt(i)
        chunk = new Int32Array(buf)
      } else {
        chunk = new Buffer(chunk)
      }
    }
    parser.write(chunk)
  }
  stream.end = function (data) {
    if(data)
      stream.write(data)
    if(!count && !path)
      stream.emit('data', stream.root)
    stream.emit('end')
  }
  return stream
}

function check (x, y) {
  if ('string' === typeof x)
    return y == x
  else if (x && 'function' === typeof x.exec)
    return x.exec(y)
  else if ('boolean' === typeof x)
    return x
  else if ('function' === typeof x)
    return x(y)
  return false
}

exports.stringify = function (op, sep, cl) {
  if (op === false){
    op = ''
    sep = '\n'
    cl = ''
  } else if (op == null) {

    op = '[\n'
    sep = '\n,\n'
    cl = '\n]\n'

  }

  //else, what ever you like

  var stream = new Stream ()
    , first = true
    , ended = false
    , anyData = false
  stream.write = function (data) {
    anyData = true
    var json = JSON.stringify(data)
    if(first) { first = false ; stream.emit('data', op + json)}
    else stream.emit('data', sep + json)
  }
  stream.end = function (data) {
    if(ended)
      return
    ended = true
    if(data) stream.write(data)
    if(!anyData) stream.emit('data', op)
    stream.emit('data', cl)

    stream.emit('end')
  }
  stream.writable = true
  stream.readable = true

  return stream
}

exports.stringifyObject = function (op, sep, cl) {
  if (op === false){
    op = ''
    sep = '\n'
    cl = ''
  } else if (op == null) {

    op = '{\n'
    sep = '\n,\n'
    cl = '\n}\n'

  }

  //else, what ever you like

  var stream = new Stream ()
    , first = true
    , ended = false
    , anyData = false
  stream.write = function (data) {
    anyData = true
    var json = JSON.stringify(data[0]) + ':' + JSON.stringify(data[1])
    if(first) { first = false ; stream.emit('data', op + json)}
    else stream.emit('data', sep + json)
  }
  stream.end = function (data) {
    if(ended) return
    ended = true
    if(data) stream.write(data)
    if(!anyData) stream.emit('data', op)
    stream.emit('data', cl)

    stream.emit('end')
  }
  stream.writable = true
  stream.readable = true

  return stream
}
<commit_msg>Emit 'root' event when no matches are found<commit_after>var Parser = require('jsonparse')
  , Stream = require('stream').Stream

/*

  the value of this.stack that creationix's jsonparse has is weird.

  it makes this code ugly, but his problem is way harder that mine,
  so i'll forgive him.

*/

exports.parse = function (path) {

  var stream = new Stream()
  var parser = new Parser()
  var count = 0
  if(!path.length)
    path = null
  parser.onValue = function () {
    if(!this.root && this.stack.length == 1){
      stream.root = this.value
      }
    if(!path || this.stack.length !== path.length)
      return
    var _path = []
    for( var i = 0; i < (path.length - 1); i++) {
      var key = path[i]
      var c = this.stack[1 + (+i)]

      if(!c) {
        return
      }
      var m = check(key, c.key)
      _path.push(c.key)

       if(!m)
        return

    }
    var c = this

    var key = path[path.length - 1]
      var m = check(key, c.key)
     if(!m)
      return
      _path.push(c.key)

  count ++
  stream.emit('data', this.value[this.key])
  }

  parser.onError = function (err) {
    stream.emit('error', err)
  }
  stream.readable = true
  stream.writable = true
  stream.write = function (chunk) {
    if('string' === typeof chunk) {
      if ('undefined' === typeof Buffer) {
        var buf = new Array(chunk.length)
        for (var i = 0; i < chunk.length; i++) buf[i] = chunk.charCodeAt(i)
        chunk = new Int32Array(buf)
      } else {
        chunk = new Buffer(chunk)
      }
    }
    parser.write(chunk)
  }
  stream.end = function (data) {
    if(data)
      stream.write(data)
    if(!count && !path)
      stream.emit('data', stream.root)
    else if(!count)
      stream.emit('root', stream.root)
    stream.emit('end')
  }
  return stream
}

function check (x, y) {
  if ('string' === typeof x)
    return y == x
  else if (x && 'function' === typeof x.exec)
    return x.exec(y)
  else if ('boolean' === typeof x)
    return x
  else if ('function' === typeof x)
    return x(y)
  return false
}

exports.stringify = function (op, sep, cl) {
  if (op === false){
    op = ''
    sep = '\n'
    cl = ''
  } else if (op == null) {

    op = '[\n'
    sep = '\n,\n'
    cl = '\n]\n'

  }

  //else, what ever you like

  var stream = new Stream ()
    , first = true
    , ended = false
    , anyData = false
  stream.write = function (data) {
    anyData = true
    var json = JSON.stringify(data)
    if(first) { first = false ; stream.emit('data', op + json)}
    else stream.emit('data', sep + json)
  }
  stream.end = function (data) {
    if(ended)
      return
    ended = true
    if(data) stream.write(data)
    if(!anyData) stream.emit('data', op)
    stream.emit('data', cl)

    stream.emit('end')
  }
  stream.writable = true
  stream.readable = true

  return stream
}

exports.stringifyObject = function (op, sep, cl) {
  if (op === false){
    op = ''
    sep = '\n'
    cl = ''
  } else if (op == null) {

    op = '{\n'
    sep = '\n,\n'
    cl = '\n}\n'

  }

  //else, what ever you like

  var stream = new Stream ()
    , first = true
    , ended = false
    , anyData = false
  stream.write = function (data) {
    anyData = true
    var json = JSON.stringify(data[0]) + ':' + JSON.stringify(data[1])
    if(first) { first = false ; stream.emit('data', op + json)}
    else stream.emit('data', sep + json)
  }
  stream.end = function (data) {
    if(ended) return
    ended = true
    if(data) stream.write(data)
    if(!anyData) stream.emit('data', op)
    stream.emit('data', cl)

    stream.emit('end')
  }
  stream.writable = true
  stream.readable = true

  return stream
}
<|endoftext|>


<commit_before>var UINT_32_MAX = Math.pow(2, 32)

exports.encodingLength = function () {
  return 8
}

exports.encode = function (num, buf, offset) {
  if (!buf) buf = new Buffer(8)
  if (!offset) offset = 0

  var top = Math.floor(num / UINT_32_MAX)
  var rem = num - top * UINT_32_MAX

  buf.writeUInt32BE(top, offset)
  buf.writeUInt32BE(rem, offset + 4)
  return buf
}

exports.decode = function (buf, offset) {
  if (!offset) offset = 0

  if (!buf) buf = new Buffer(4)
  if (!offset) offset = 0

  var top = buf.readUInt32BE(offset)
  var rem = buf.readUInt32BE(offset + 4)

  return top * UINT_32_MAX + rem
}

exports.encode.bytes = 8
exports.decode.bytes = 8
<commit_msg>fix dead code<commit_after>var UINT_32_MAX = Math.pow(2, 32)

exports.encodingLength = function () {
  return 8
}

exports.encode = function (num, buf, offset) {
  if (!buf) buf = new Buffer(8)
  if (!offset) offset = 0

  var top = Math.floor(num / UINT_32_MAX)
  var rem = num - top * UINT_32_MAX

  buf.writeUInt32BE(top, offset)
  buf.writeUInt32BE(rem, offset + 4)
  return buf
}

exports.decode = function (buf, offset) {
  if (!offset) offset = 0

  var top = buf.readUInt32BE(offset)
  var rem = buf.readUInt32BE(offset + 4)

  return top * UINT_32_MAX + rem
}

exports.encode.bytes = 8
exports.decode.bytes = 8
<|endoftext|>


<commit_before>/**
 * Created by tusharmathur on 5/15/15.
 */
"use strict";
var fs = require('fs'),
    _ = require('lodash'),
    request = require('request'),
    co = require('co'),
    MAX_BUFFER = 512;

var defaultOptions = {
    headers: {},
    threadCount: 3
};
var fsWrite = promisify(fs.write),
    fsTruncate = promisify(fs.truncate),
    fsRename = promisify(fs.rename),
    requestHead = promisify(request.head);

function asyncCatcher(onError, func) {
    var coFunc = co.wrap(func);
    return () => {
        try {
            coFunc.apply(null, arguments).catch(onError);
        } catch (e) {
            onError(e);
        }
    };
}
function promisify(func) {
    var defer = Promise.defer(),
        handle = (err, data) => err ? defer.reject(err) : defer.resolve(data);
    return _.restParam(function (args) {
        args.push(handle);
        func.apply(null, args);
        return defer.promise;
    })
}
var writeData = (fd, buffer, position) => fsWrite(fd, buffer, 0, buffer.length, position);
var getLength = (res) => parseInt(res.headers['content-length'], 10);
var fsOpen = (path) => promisify(fs.open)(path, 'w+');
var rangeHeader = (thread) => ({'range': `bytes=${thread.start}-${thread.end}`});
var createWriteThread = function (range) {
    return {
        defer: Promise.defer(),
        start: range.start,
        end: range.end,
        position: range.start,
        nextByte: range.start,
        updatePosition: function (distance) {
            this.position += distance;
            if (this.position >= this.end) {
                this.defer.resolve(this);
            }
        },
        writeAt: function (distance) {
            var writeAt = this.nextByte;
            this.nextByte += distance;
            return writeAt;
        }
    };
};
function toBuffer(data, size) {
    size = size || MAX_BUFFER;
    var metaBuffer = new Buffer(size);
    _.fill(metaBuffer, null);
    metaBuffer.write(JSON.stringify(data));
    return metaBuffer;
}
function byteRange(count, total, index) {
    var bytesPerThread = Math.round(total / count),
        start = Math.floor(bytesPerThread * index),
        end = count - index === 1 ? total : start + bytesPerThread - 1;
    return {start, end}
}

var HttpRequest = require('./HttpRequest');
var httpRequest = function (url, start, end) {
    return HttpRequest(url, rangeHeader({start, end}))
};

var writerThreadOnReject = _.partial(_.rearg(_.get, 1, 0), 'defer.reject');
var invoke = (invocationList) => _.partial(_.invoke, invocationList, _.call, null);
var bytesPerThread = (threadCount, size) => Math.floor(size / threadCount);

var createThreadStartPositions = function (threadCount, size) {
    var _bytesPerThread = bytesPerThread(threadCount, size);
    return _.times(threadCount, (x)=> x * _bytesPerThread);
};
var createThreadEndPositions = function (threadCount, size) {
    var _bytesPerThread = bytesPerThread(threadCount, size);
    var positions = _.times(threadCount, (x)=> (x + 1) * _bytesPerThread - 1);
    positions[positions.length - 1] = size;
    return positions;
};
var iterate = function * (list, func) {
    var count = 0;
    for (var i of list) {
        yield func(i, count++, list);
    }
};
function * download(options) {
    var url = options.url,
        threadCount = options.threadCount,
        path = options.path,
        size = getLength(yield requestHead(url)),
        meta = {url, path: path, threads: []},
        fd = yield fsOpen(path),
        _fsTruncate = _.partial(fsTruncate, fd, size),
        _fsRename = _.partial(fsRename, path, path.replace('.mtd', '')),
        _write = function * (fd, thread, buffer) {
            yield writeData(fd, buffer, thread.writeAt(buffer.length));
            thread.updatePosition(buffer.length);
            yield writeData(fd, toBuffer(meta), size + 1);
        },
        _byteRange = _.partial(byteRange, threadCount, size);
    var threads = meta.threads = _(threadCount).times(_byteRange).map(createWriteThread).value();

    yield _.map(threads, function * (thread) {
        let response = yield httpRequest(url, thread.start, thread.end);
        yield iterate(response.read(), _.partial(_write, fd, thread));
    });

    yield _fsTruncate();
    yield _fsRename();
    return meta;
}

class Download {
    constructor(options) {
        this.options = _.assign(options, defaultOptions);
        this.options.path += '.mtd';
    }

    start() {
        return co.wrap(download)(this.options);
    }
}
module.exports = Download;<commit_msg>clean up writer<commit_after>/**
 * Created by tusharmathur on 5/15/15.
 */
"use strict";
var fs = require('fs'),
    _ = require('lodash'),
    request = require('request'),
    HttpRequest = require('./HttpRequest'),
    co = require('co'),
    MAX_BUFFER = 128;

var defaultOptions = {
    headers: {},
    threadCount: 10
};
var fsWrite = promisify(fs.write),
    fsTruncate = promisify(fs.truncate),
    fsRename = promisify(fs.rename),
    requestHead = promisify(request.head);

function promisify(func) {
    var defer = Promise.defer(),
        handle = (err, data) => err ? defer.reject(err) : defer.resolve(data);
    return _.restParam(function (args) {
        args.push(handle);
        func.apply(null, args);
        return defer.promise;
    })
}
var writeData = (fd, buffer, position) => fsWrite(fd, buffer, 0, buffer.length, position);
var getLength = (res) => parseInt(res.headers['content-length'], 10);
var fsOpen = (path) => promisify(fs.open)(path, 'w+');
var rangeHeader = (thread) => ({'range': `bytes=${thread.start}-${thread.end}`});
var createWriteThread = function (range) {
    return {
        defer: Promise.defer(),
        start: range.start,
        end: range.end,
        position: range.start,
        nextByte: range.start,
        updatePosition: function (distance) {
            this.position += distance;
            if (this.position >= this.end) {
                this.defer.resolve(this);
            }
        },
        writeAt: function (distance) {
            var writeAt = this.nextByte;
            this.nextByte += distance;
            return writeAt;
        }
    };
};
function toBuffer(data, size) {
    size = size || MAX_BUFFER;
    var metaBuffer = new Buffer(size);
    _.fill(metaBuffer, null);
    metaBuffer.write(JSON.stringify(data));
    return metaBuffer;
}
function byteRange(count, total, index) {
    var bytesPerThread = Math.round(total / count),
        start = Math.floor(bytesPerThread * index),
        end = count - index === 1 ? total : start + bytesPerThread - 1;
    return {start, end}
}

var writerThreadOnReject = _.partial(_.rearg(_.get, 1, 0), 'defer.reject');
var invoke = (invocationList) => _.partial(_.invoke, invocationList, _.call, null);
var bytesPerThread = (threadCount, size) => Math.floor(size / threadCount);

var createThreadStartPositions = function (threadCount, size) {
    var _bytesPerThread = bytesPerThread(threadCount, size);
    return _.times(threadCount, (x)=> x * _bytesPerThread);
};
var createThreadEndPositions = function (threadCount, size) {
    var _bytesPerThread = bytesPerThread(threadCount, size);
    var positions = _.times(threadCount, (x)=> (x + 1) * _bytesPerThread - 1);
    positions[positions.length - 1] = size;
    return positions;
};
var iterate = function * (list, func) {
    var count = 0;
    for (var i of list) {
        yield func(i, count++, list);
    }
};
function * download(options) {
    var url = options.url,
        threadCount = options.threadCount,
        path = options.path,
        size = getLength(yield requestHead(url)),
        meta = {url, path: path, threads: []},
        fd = yield fsOpen(path),
        _fsTruncate = _.partial(fsTruncate, fd, size),
        _write = _.partial(writeData, fd),
        _httpRequest = _.partial(HttpRequest, url),
        _httpRequestRange = _.flowRight(_httpRequest, rangeHeader),
        _fsRename = _.partial(fsRename, path, path.replace('.mtd', '')),
        _byteRange = _.partial(byteRange, threadCount, size);
    meta.threads = _.chain(threadCount).times(_byteRange).map(createWriteThread).value();

    yield _.map(meta.threads, function * (thread) {
        let response = yield _httpRequestRange(thread);
        for (let buffer of response.read()) {
            yield _write(buffer, thread.writeAt(buffer.length));
            thread.updatePosition(buffer.length);
            yield _write(toBuffer(meta), size + 1);
        }
    });

    yield _fsTruncate();
    yield _fsRename();
    return meta;
}

class Download {
    constructor(options) {
        this.options = _.assign(options, defaultOptions);
        this.options.path += '.mtd';
    }

    start() {
        return co.wrap(download)(this.options);
    }
}
module.exports = Download;<|endoftext|>


<commit_before>import './lib/server.js';
<commit_msg>Fix: Add babel-register to index.js<commit_after>'use strict'; // eslint-disable-line strict

require('babel/register');
require('./lib/server.js');
<|endoftext|>


<commit_before>var siteKey = process.env.HORSELIGHTS_SITEKEY
var lightId = process.argv[2]

if(siteKey == null || lightId == null) {
  throw "Please provide site key in environment variable and light id as command line parameter"
}

console.log("Controlling lightId", lightId);

var midi = require('midi')
var request = require('request')

function putLightState(message) {
  var url = "https://houm.herokuapp.com/api/site/" + siteKey + "/light/state"
  request({ method: 'PUT', url: url, body: message, json: true}, function (error, response, body) {
    if(error) {
      console.log('Failed setting light state to', message)
    }
  });
}

var input = new midi.input()

input.on('message', function(deltaTime, message) {
  var isControlMessage = (message[0] >> 4) === 0xb;
  if(isControlMessage) {
    var controllerNumber = message[1];
    var controllerValue = message[2];
    console.log('Set brightness to', controllerValue);
    putLightState({
      _id: lightId,
      on: controllerValue > 0,
      bri: controllerValue
    });
  }
});

input.openPort(0);
<commit_msg>Scale MIDI value (0-127) to expected scale (0-255)<commit_after>var siteKey = process.env.HORSELIGHTS_SITEKEY
var lightId = process.argv[2]

if(siteKey == null || lightId == null) {
  throw "Please provide site key in environment variable and light id as command line parameter"
}

console.log("Controlling lightId", lightId);

var midi = require('midi')
var request = require('request')

function putLightState(message) {
  var url = "https://houm.herokuapp.com/api/site/" + siteKey + "/light/state"
  request({ method: 'PUT', url: url, body: message, json: true}, function (error, response, body) {
    if(error) {
      console.log('Failed setting light state to', message)
    }
  });
}

var input = new midi.input()

input.on('message', function(deltaTime, message) {
  var isControlMessage = (message[0] >> 4) === 0xb;
  if(isControlMessage) {
    var controllerValue = message[2];
    var brightness = controllerValue * 2;
    console.log('Set brightness to', brightness);
    putLightState({
      _id: lightId,
      on: brightness > 0,
      bri: brightness
    });
  }
});

input.openPort(0);
<|endoftext|>