<commit_before>'use strict'

const express = require('express')
const Slapp = require('slapp')
const ConvoStore = require('slapp-convo-beepboop')
const Context = require('slapp-context-beepboop')

// use `PORT` env var on Beep Boop - default to 3000 locally
var port = process.env.PORT || 3000

var slapp = Slapp({
  // Beep Boop sets the SLACK_VERIFY_TOKEN env var
  verify_token: process.env.SLACK_VERIFY_TOKEN,
  convo_store: ConvoStore(),
  context: Context()
})

var HELP_TEXT = `
I will respond to the following messages:
\`help\` - to see this message.
\`hi\` - to demonstrate a conversation that tracks state.
\`thanks\` - to demonstrate a simple response.
\`<type-any-other-text>\` - to demonstrate a random emoticon response, some of the time :wink:.
\`attachment\` - to see a Slack attachment message.
`

//*********************************************
// Setup different handlers for messages
//*********************************************

// response to the user typing "help"
slapp.message('help', ['mention', 'direct_message'], (msg) => {
  msg.say(HELP_TEXT)
})

// "Conversation" flow that tracks state - kicks off when user says hi, hello or hey
slapp
.message('^(hi|hello|hey)$', ['direct_mention', 'direct_message'], (msg, text) => {
  msg
  .say(`${text}, how are you?`)
  // sends next event from user to this route, passing along state
  .route('how-are-you', { greeting: text })
})
.route('how-are-you', (msg, state) => {
  var text = (msg.body.event && msg.body.event.text) || ''

  // user may not have typed text as their next action, ask again and re-route
  if (!text) {
    return msg
    .say("Whoops, I'm still waiting to hear how you're doing.")
    .say('How are you?')
    .route('how-are-you', state)
  }

  // add their response to state
  state.status = text

  msg
  .say(`Ok then. What's your favorite color?`)
  .route('color', state)
})
.route('color', (msg, state) => {
  var text = (msg.body.event && msg.body.event.text) || ''

  // user may not have typed text as their next action, ask again and re-route
  if (!text) {
    return msg
    .say("I'm eagerly awaiting to hear your favorite color.")
    .route('color', state)
  }

  // add their response to state
  state.color = text

  msg
  .say('Thanks for sharing.')
  .say(`Here's what you've told me so far: \`\`\`${JSON.stringify(state)}\`\`\``)
  // At this point, since we don't route anywhere, the "conversation" is over
})

// Can use a regex as well
slapp.message(/^(thanks|thank you)/i, ['mention', 'direct_message'], (msg) => {
  // You can provide a list of responses, and a random one will be chosen
  // You can also include slack emoji in your responses
  msg.say([
    "You're welcome :smile:",
    'You bet',
    ':+1: Of course',
    'Anytime :sun_with_face: :full_moon_with_face:'
  ])
})

//Goodnight message
slapp.message('goodnight', ['mention', 'direct_message'], (msg) => {
  msg.say('sweet dreams dude!! :crescent_moon: ')
})

// demonstrate returning an attachment...
slapp.message('attachment', ['mention', 'direct_message'], (msg) => {
  msg.say({
    text: 'Check out this amazing attachment! :confetti_ball: ',
    attachments: [{
      text: 'Slapp is a robust open source library that sits on top of the Slack APIs',
      title: 'Slapp Library - Open Source',
      image_url: 'https://storage.googleapis.com/beepboophq/_assets/bot-1.22f6fb.png',
      title_link: 'https://beepboophq.com/',
      color: '#7CD197',
      "actions": [
        {
          "name": "playPlaylist",
          "text": "Let's get the party started!",
          "type": "button",
          "value": "play"
        }]
      }]
    })
  })

  // Catch-all for any other responses not handled above
  slapp.message('.*', ['direct_mention', 'direct_message'], (msg) => {
    // respond only 40% of the time
    if (Math.random() < 0.4) {
      msg.say([':wave:', ':pray:', ':raised_hands:'])
    }
  })

  // attach Slapp to express server
  var server = slapp.attachToExpress(express())

  // start http server
  server.listen(port, (err) => {
    if (err) {
      return console.error(err)
    }

    console.log(`Listening on port ${port}`)
  })
<commit_msg>The start of a playlist<commit_after>'use strict'

const express = require('express')
const Slapp = require('slapp')
const ConvoStore = require('slapp-convo-beepboop')
const Context = require('slapp-context-beepboop')

// use `PORT` env var on Beep Boop - default to 3000 locally
var port = process.env.PORT || 3000

var slapp = Slapp({
  // Beep Boop sets the SLACK_VERIFY_TOKEN env var
  verify_token: process.env.SLACK_VERIFY_TOKEN,
  convo_store: ConvoStore(),
  context: Context()
})

var HELP_TEXT = `
I will respond to the following messages:
\`help\` - to see this message.
\`hi\` - to demonstrate a conversation that tracks state.
\`thanks\` - to demonstrate a simple response.
\`<type-any-other-text>\` - to demonstrate a random emoticon response, some of the time :wink:.
\`attachment\` - to see a Slack attachment message.
`

//*********************************************
// Setup different handlers for messages
//*********************************************

// response to the user typing "help"
slapp.message('help', ['mention', 'direct_message'], (msg) => {
  msg.say(HELP_TEXT)
})

// "Conversation" flow that tracks state - kicks off when user says hi, hello or hey
slapp
.message('^(hi|hello|hey)$', ['direct_mention', 'direct_message'], (msg, text) => {
  msg
  .say(`${text}, how are you?`)
  // sends next event from user to this route, passing along state
  .route('how-are-you', { greeting: text })
})
.route('how-are-you', (msg, state) => {
  var text = (msg.body.event && msg.body.event.text) || ''

  // user may not have typed text as their next action, ask again and re-route
  if (!text) {
    return msg
    .say("Whoops, I'm still waiting to hear how you're doing.")
    .say('How are you?')
    .route('how-are-you', state)
  }

  // add their response to state
  state.status = text

  msg
  .say(`Ok then. What's your favorite color?`)
  .route('color', state)
})
.route('color', (msg, state) => {
  var text = (msg.body.event && msg.body.event.text) || ''

  // user may not have typed text as their next action, ask again and re-route
  if (!text) {
    return msg
    .say("I'm eagerly awaiting to hear your favorite color.")
    .route('color', state)
  }

  // add their response to state
  state.color = text

  msg
  .say('Thanks for sharing.')
  .say(`Here's what you've told me so far: \`\`\`${JSON.stringify(state)}\`\`\``)
  // At this point, since we don't route anywhere, the "conversation" is over
})

// Can use a regex as well
slapp.message(/^(thanks|thank you)/i, ['mention', 'direct_message'], (msg) => {
  // You can provide a list of responses, and a random one will be chosen
  // You can also include slack emoji in your responses
  msg.say([
    "You're welcome :smile:",
    'You bet',
    ':+1: Of course',
    'Anytime :sun_with_face: :full_moon_with_face:'
  ])
})

//Goodnight message
slapp.message('goodnight', ['mention', 'direct_message'], (msg) => {
  msg.say('sweet dreams dude!! :crescent_moon: ')
})

slapp.command('/playlist', /^in/, (msg) => {
  // `respond` is used for actions or commands and uses the `response_url` provided by the
  // incoming request from Slack
  msg.respond(`Here is your playlist for ${match}!`)
})

// demonstrate returning an attachment...
slapp.message('attachment', ['mention', 'direct_message'], (msg) => {
  msg.say({
    text: 'Check out this amazing attachment! :confetti_ball: ',
    attachments: [{
      text: 'Slapp is a robust open source library that sits on top of the Slack APIs',
      title: 'Slapp Library - Open Source',
      image_url: 'https://storage.googleapis.com/beepboophq/_assets/bot-1.22f6fb.png',
      title_link: 'https://beepboophq.com/',
      color: '#7CD197',
      "actions": [
        {
          "name": "playPlaylist",
          "text": "Let's go!",
          "type": "button",
          "value": "play"
        }]
      }]
    })
  })

  // Catch-all for any other responses not handled above
  slapp.message('.*', ['direct_mention', 'direct_message'], (msg) => {
    // respond only 40% of the time
    if (Math.random() < 0.4) {
      msg.say([':wave:', ':pray:', ':raised_hands:'])
    }
  })

  // attach Slapp to express server
  var server = slapp.attachToExpress(express())

  // start http server
  server.listen(port, (err) => {
    if (err) {
      return console.error(err)
    }

    console.log(`Listening on port ${port}`)
  })
<|endoftext|>


<commit_before>const http = require("http");
const exec = require("exec");

const PORT = 9988;
const PATH = "./html";

const deployServer = http.createServer((request, response) => {
	if(request.url.search(/deploy\/?$/i) > 0) {
		let commands = [
			"cd " + PATH,
			"git pull"
		].join(" && ");

		exec(commands, (err, out, code) => {
			if(err instanceof Error) {
				response.writeHead(500);
				response.end("Server Internal Error.");
				throw err;
			}
			process.stderr.write(err);
			process.stdout.write(out);
			response.writeHead(200);
			response.end("Deploy Done");
		});
	} else {
		response.writeHead(404);
		response.end("Not Found.");
	}
});

deployServer.listen(PORT);<commit_msg>server.js change ES5<commit_after>var http = require("http");
var exec = require("exec");

var PORT =  19988;
var PATH = "./html";

var deployServer = http.createServer( function(request, response) {
	if(request.url.search(/deploy\/?$/i) > 0) {
		let commands = [
			"cd " + PATH,
			"git pull"
		].join(" && ");

		exec(commands, function(err, out, code) {
			if(err instanceof Error) {
				response.writeHead(500);
				response.end("Server Internal Error.");
				throw err;
			}
			process.stderr.write(err);
			process.stdout.write(out);
			response.writeHead(200);
			response.end("Deploy Done");
		});
	} else {
		response.writeHead(404);
		response.end("Not Found.");
	}
});

deployServer.listen(PORT);<|endoftext|>


<commit_before>// Copyright 2014 Joyent, Inc.  All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

var fs = require('fs');
var os = require('os');
var path = require('path');
var util = require('util');

var userid = require('userid');
var assert = require('assert-plus');
var bunyan = require('bunyan');
var clone = require('clone');
var dashdash = require('dashdash');
var LRU = require('lru-cache');
var nfs = require('nfs');
var rpc = require('oncrpc');
var mantafs = require('mantafs');
var vasync = require('vasync');

var app = require('./lib');

// uid/gid for 'nobody' on non-windows systems
var uid = 0;
var gid = 0;
var os_platform;

///--- Globals

var LOG = app.bunyan.createLogger();

var OPTIONS_PARSER = dashdash.createParser({
    options: [
        {
            names: ['file', 'f'],
            type: 'string',
            help: 'configuration file to use',
            helpArg: 'FILE'
        },
        {
            names: ['debug', 'd'],
            type: 'bool',
            help: 'turn on debug bunyan logging'
        },
        {
            names: ['verbose', 'v'],
            type: 'bool',
            help: 'turn on verbose bunyan logging'
        }
    ]
});

///--- Functions

function usage(msg) {
    var help = OPTIONS_PARSER.help({
        includeEnv: true
    }).trimRight();

    if (msg)
        console.error(util.format.apply(util, arguments));
    console.error('usage: nfsd [OPTIONS]\noptions:\n' + help);

    process.exit(msg ? 1 : 0);
}

function configure() {
    var opts;

    try {
        opts = OPTIONS_PARSER.parse(process.argv);
    } catch (e) {
        usage(e.message);
    }

    if (opts.verbose) {
        LOG = LOG.child({
            level: 'trace',
            src: true
        });
    } else if (opts.debug) {
        LOG = LOG.child({
            level: 'debug',
            src: true
        });
    } else {
        LOG = LOG.child({
            level: 'info',
            src: true
        });
    }

    if (opts.help)
        usage();

    var cfg;
    if (opts.file) {
        try {
            cfg = JSON.parse(fs.readFileSync(opts.file, 'utf8'));
        } catch (e) {
            usage('unable to load %s:\n%s\n', opts.file, e.toString());
        }
    } else {
        cfg = {};
    }

    if (cfg.manta) {
        assert.object(cfg.manta, 'config.manta');
    } else if (process.env.MANTA_USER && process.env.HOME) {
        // use the manta config in the environment
        // assume if MANTA_USER is set, all 3 are set
        cfg.manta = {
            'keyFile': path.join(process.env.HOME, '.ssh/id_rsa'),
            'keyId': process.env.MANTA_KEY_ID,
            'url': process.env.MANTA_URL,
            'user': process.env.MANTA_USER
        };
    } else {
        usage('missing manta configuration and no manta environment variables');
    }

    if (cfg.database) {
        assert.object(cfg.database, 'config.database');
    } else {
        // default local cache config
        cfg.database = {
            location: '/var/tmp/mfsdb',
            max_files: 65535,
            sizeMB: 1024,
            ttl: 3600
        };
    }

    if (cfg.portmap) {
        assert.object(cfg.portmap, 'config.portmap');
        // Normally only need to define this section if setting
        //     'usehost': 1
        // so that we always use the system's portmapper, or
        //     'host': {IP addr}
        // so that we listen on an IP address other than the loopback.
        // You can also override the prognum/vers/port for testing
    } else {
        cfg.portmap = {
            'port': 111,
            'mappings': {
                'mountd': [ {
                    'prog': 100005,
                    'vers': 3,
                    'prot': 6,
                    'port': 1892
                }, {
                    'prog': 100005,
                    'vers': 1,
                    'prot': 6,
                    'port': 1892
                }],
                'nfsd': [ {
                    'prog': 100003,
                    'vers': 3,
                    'prot': 6,
                    'port': 2049
                }],
                'portmapd': [ {
                    'prog': 100000,
                    'vers': 2,
                    'prot': 6,
                    'port': 111
                }]
            }
        };
    }

    // Can set 'host' to enable the mountd server to listen on an IP address
    // other than the loopback.
    // You can also define this if you want to query the mountd to
    // see exports. If defined, mounts are restricted to these paths. e.g.
    //     'exports': {
    //        '/user/public/foo': {},
    //        '/user/stor': {}
    //     }
    cfg.mount = cfg.mount || {};
    assert.object(cfg.mount, 'config.mount');

    // Can set 'host' to enable the nfs server to listen on an IP address
    // other than the loopback. Can set uid and gid to specify the uid/gid for
    // 'nobody' on the client. If not provided, the server's values for 'nobody'
    // will be used.
    cfg.nfs = cfg.nfs || {};
    assert.object(cfg.nfs, 'config.nfs');
    cfg.nfs.fd_cache = cfg.nfs.fd_cache || {
        max: 10000,
        ttl: 60
    };

    cfg.log = LOG;
    cfg.manta.log = LOG;
    cfg.mount.log = LOG;
    cfg.nfs.log = LOG;
    cfg.portmap.log = LOG;

    cfg.manta = app.createMantaClient(cfg.manta);
    cfg.mount.manta = cfg.manta;
    cfg.nfs.manta = cfg.manta;

    return (cfg);
}

function step_down() {
    try {
        process.setgid(gid);
        process.setuid(uid);
        LOG.info('server now running as \'nobody\'');
    } catch (e) {
        LOG.fatal(e, 'unable to setuid/setgid to nobody');
        process.exit(1);
    }
}

// Runs the mountd and nfsd servers. Called once we're registered with the
// system's portmapper or once we've started our own portmapper.
function run_servers(log, cfg_mount, cfg_nfs) {
    var barrier = vasync.barrier();
    var mountd = app.createMountServer(cfg_mount);
    var nfsd = app.createNfsServer(cfg_nfs);

    barrier.on('drain', function onRunning() {
        var ma = mountd.address();
        var na = nfsd.address();

        log.info('mountd: listening on: tcp://%s:%d',
                 ma.address, ma.port);
        log.info('nfsd: listening on: tcp://%s:%d',
                 na.address, na.port);

        if (uid !== 0) {
            // On non-windows machines we run as 'nobody'.
            // On sunos we have to wait until after we're listening on the nfs
            // port since the user 'nobody' will not have the sys_nfs priv.
            // On darwin 'nobody' is -2 and we error setting the uid/gid to a
            // negative number, so use the symbolic name.
            if (os_platform === 'darwin') {
                gid = uid = 'nobody';
            }
            step_down();
        }
    });

    barrier.start('mount');
    mountd.listen(cfg_mount.port || 1892,
                  cfg_mount.host || '127.0.0.1',
                  barrier.done.bind(barrier, 'mount'));

    barrier.start('nfs');
    nfsd.listen(cfg_nfs.port || 2049,
                cfg_nfs.host || '127.0.0.1',
                barrier.done.bind(barrier, 'nfs'));
}

// Darwin uses negative numbers for 'nobody' but these get pulled out as a
// large non-negative number. Convert to twos-complement.
function convert_neg_id(id)
{
    if (id > 0x7fffffff)
        return (-(~id + 1));
    else
        return (id);
}

///--- Mainline

(function main() {
    var cfg = configure();
    var log = cfg.log;

    os_platform = os.platform();
    if (os_platform !== 'win32') {
        uid = convert_neg_id(userid.uid('nobody'));
        try {
            gid = convert_neg_id(userid.gid('nobody'));
        } catch (e1) {
            // Linux uses 'nogroup' instead of 'nobody'
            try {
                gid = convert_neg_id(userid.gid('nogroup'));
            } catch (e2) {
                gid = uid;
            }
        }
    }

    var mfs = mantafs.createClient({
        files: cfg.database.max_files,
        log: log.child({component: 'MantaFs'}, true),
        manta: cfg.manta,
        path: cfg.database.location,
        sizeMB: cfg.database.sizeMB,
        ttl: cfg.database.ttl,
        uid: cfg.nfs.uid || uid,
        gid: cfg.nfs.gid || gid
    });

    cfg.mount.fs = mfs;
    cfg.nfs.fs = mfs;
    cfg.nfs.fd_cache = LRU({
        dispose: function cache_close_fd(k, v) {
            mfs.close(v.fd, function on_close(err) {
                if (err)
                    log.debug(err, 'failed to close(fd=%d) for %s', v.fd, k);
            });
        },
        max: cfg.nfs.fd_cache.max,
        maxAge: cfg.nfs.fd_cache.ttl * 1000 // 1m TTL
    });

    cfg.nfs.cachepath = cfg.database.location;    // used by fsstat

    var mntmapping = {
        prog: 100005,
        vers: 3,
        prot: 6,
        port: 1892
    };

    var nfsmapping = {
        prog: 100003,
        vers: 3,
        prot: 6,
        port: 2049
    };
    var pmapclient;

    process.on('SIGINT', function () {
        log.info('Got SIGINT, shutting down.');
        mfs.shutdown(function (err) {
            if (err) {
                log.warn(err, 'mantafs shutdown error');
            }

            if (cfg.portmap.usehost) {
                pmapclient.unset(mntmapping, function (err1) {
                    if (err1) {
                        log.warn(err1,
                            'unable to unregister mountd from the portmapper');
                    }

                    pmapclient.unset(nfsmapping, function (err2) {
                        if (err2) {
                            log.warn(err2,
                            'unable to unregister nfsd from the portmapper');
                        }
                        log.info('Shutdown complete, exiting.');
                        process.exit(0);
                    });
                });
            } else {
                log.info('Shutdown complete, exiting.');
                process.exit(0);
            }
        });
    });

    mfs.once('error', function (err) {
        log.fatal(err, 'unable to initialize mantafs cache');
        process.exit(1);
    });
    mfs.once('ready', function () {
        // Cache exists now, ensure cache dir modes are more secure
        fs.chmodSync(mfs.path, 0700);
        fs.chmodSync(path.join(mfs.path, 'fscache'), 0700);
        fs.chmodSync(path.join(mfs.path, 'manta.db'), 0600);
        if (uid !== 0) {
            // On non-windows machines we run as 'nobody'. Tighten up now.
            fs.chownSync(mfs.path, uid, gid);
            fs.chownSync(path.join(mfs.path, 'fscache'), uid, gid);
            fs.chownSync(path.join(mfs.path, 'manta.db'), uid, gid);
        }

        // the portmapper needs to listen on all addresses, unlike our mountd
        // and nfsd which only listen on localhost by default for some basic
        // security
        cfg.portmap.host = cfg.portmap.host || '0.0.0.0';
        cfg.portmap.port = cfg.portmap.port || 111;

        // Use the system's portmapper
        function register_with_pmap() {
            cfg.portmap.url = util.format('udp://%s:%d',
                cfg.portmap.host, cfg.portmap.port);
            pmapclient = app.createPortmapClient(cfg.portmap);

            pmapclient.once('connect', function () {
                pmapclient.set(mntmapping, function (err1) {
                    if (err1) {
                        log.fatal(err1,
                            'unable to register mountd with the portmapper');
                        process.exit(1);
                    }

                    pmapclient.set(nfsmapping, function (err2) {
                        if (err2) {
                            log.fatal(err2,
                                'unable to register nfsd with the portmapper');
                            process.exit(1);
                        }

                        run_servers(cfg.log, cfg.mount, cfg.nfs);
                    });
                });
            });
        }

        if (cfg.portmap.usehost) {
            register_with_pmap();
        } else {
            // Here we run our own portmapper
            var pmapd = app.createPortmapServer(cfg.portmap);

            pmapd.on('error', function (e) {
                if (e.code == 'EADDRINUSE') {
                    log.info('Portmapper address in use, registering...');
                    register_with_pmap();
                } else {
                    log.fatal(e, 'unable to run the portmapper');
                    process.exit(1);
                }
            });

            pmapd.listen(cfg.portmap.port, cfg.portmap.host, function () {
                run_servers(cfg.log, cfg.mount, cfg.nfs);
            });
       }
    });
})();
<commit_msg>MANTA-1844 register with the portmapper using localhost<commit_after>// Copyright 2014 Joyent, Inc.  All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

var fs = require('fs');
var os = require('os');
var path = require('path');
var util = require('util');

var userid = require('userid');
var assert = require('assert-plus');
var bunyan = require('bunyan');
var clone = require('clone');
var dashdash = require('dashdash');
var LRU = require('lru-cache');
var nfs = require('nfs');
var rpc = require('oncrpc');
var mantafs = require('mantafs');
var vasync = require('vasync');

var app = require('./lib');

// uid/gid for 'nobody' on non-windows systems
var uid = 0;
var gid = 0;
var os_platform;

///--- Globals

var LOG = app.bunyan.createLogger();

var OPTIONS_PARSER = dashdash.createParser({
    options: [
        {
            names: ['file', 'f'],
            type: 'string',
            help: 'configuration file to use',
            helpArg: 'FILE'
        },
        {
            names: ['debug', 'd'],
            type: 'bool',
            help: 'turn on debug bunyan logging'
        },
        {
            names: ['verbose', 'v'],
            type: 'bool',
            help: 'turn on verbose bunyan logging'
        }
    ]
});

///--- Functions

function usage(msg) {
    var help = OPTIONS_PARSER.help({
        includeEnv: true
    }).trimRight();

    if (msg)
        console.error(util.format.apply(util, arguments));
    console.error('usage: nfsd [OPTIONS]\noptions:\n' + help);

    process.exit(msg ? 1 : 0);
}

function configure() {
    var opts;

    try {
        opts = OPTIONS_PARSER.parse(process.argv);
    } catch (e) {
        usage(e.message);
    }

    if (opts.verbose) {
        LOG = LOG.child({
            level: 'trace',
            src: true
        });
    } else if (opts.debug) {
        LOG = LOG.child({
            level: 'debug',
            src: true
        });
    } else {
        LOG = LOG.child({
            level: 'info',
            src: true
        });
    }

    if (opts.help)
        usage();

    var cfg;
    if (opts.file) {
        try {
            cfg = JSON.parse(fs.readFileSync(opts.file, 'utf8'));
        } catch (e) {
            usage('unable to load %s:\n%s\n', opts.file, e.toString());
        }
    } else {
        cfg = {};
    }

    if (cfg.manta) {
        assert.object(cfg.manta, 'config.manta');
    } else if (process.env.MANTA_USER && process.env.HOME) {
        // use the manta config in the environment
        // assume if MANTA_USER is set, all 3 are set
        cfg.manta = {
            'keyFile': path.join(process.env.HOME, '.ssh/id_rsa'),
            'keyId': process.env.MANTA_KEY_ID,
            'url': process.env.MANTA_URL,
            'user': process.env.MANTA_USER
        };
    } else {
        usage('missing manta configuration and no manta environment variables');
    }

    if (cfg.database) {
        assert.object(cfg.database, 'config.database');
    } else {
        // default local cache config
        cfg.database = {
            location: '/var/tmp/mfsdb',
            max_files: 65535,
            sizeMB: 1024,
            ttl: 3600
        };
    }

    if (cfg.portmap) {
        assert.object(cfg.portmap, 'config.portmap');
        // Normally only need to define this section if setting
        //     'usehost': 1
        // so that we always use the system's portmapper, or
        //     'host': {IP addr}
        // so that we listen on an IP address other than the loopback.
        // You can also override the prognum/vers/port for testing
    } else {
        cfg.portmap = {
            'port': 111,
            'mappings': {
                'mountd': [ {
                    'prog': 100005,
                    'vers': 3,
                    'prot': 6,
                    'port': 1892
                }, {
                    'prog': 100005,
                    'vers': 1,
                    'prot': 6,
                    'port': 1892
                }],
                'nfsd': [ {
                    'prog': 100003,
                    'vers': 3,
                    'prot': 6,
                    'port': 2049
                }],
                'portmapd': [ {
                    'prog': 100000,
                    'vers': 2,
                    'prot': 6,
                    'port': 111
                }]
            }
        };
    }

    // Can set 'host' to enable the mountd server to listen on an IP address
    // other than the loopback.
    // You can also define this if you want to query the mountd to
    // see exports. If defined, mounts are restricted to these paths. e.g.
    //     'exports': {
    //        '/user/public/foo': {},
    //        '/user/stor': {}
    //     }
    cfg.mount = cfg.mount || {};
    assert.object(cfg.mount, 'config.mount');

    // Can set 'host' to enable the nfs server to listen on an IP address
    // other than the loopback. Can set uid and gid to specify the uid/gid for
    // 'nobody' on the client. If not provided, the server's values for 'nobody'
    // will be used.
    cfg.nfs = cfg.nfs || {};
    assert.object(cfg.nfs, 'config.nfs');
    cfg.nfs.fd_cache = cfg.nfs.fd_cache || {
        max: 10000,
        ttl: 60
    };

    cfg.log = LOG;
    cfg.manta.log = LOG;
    cfg.mount.log = LOG;
    cfg.nfs.log = LOG;
    cfg.portmap.log = LOG;

    cfg.manta = app.createMantaClient(cfg.manta);
    cfg.mount.manta = cfg.manta;
    cfg.nfs.manta = cfg.manta;

    return (cfg);
}

function step_down() {
    try {
        process.setgid(gid);
        process.setuid(uid);
        LOG.info('server now running as \'nobody\'');
    } catch (e) {
        LOG.fatal(e, 'unable to setuid/setgid to nobody');
        process.exit(1);
    }
}

// Runs the mountd and nfsd servers. Called once we're registered with the
// system's portmapper or once we've started our own portmapper.
function run_servers(log, cfg_mount, cfg_nfs) {
    var barrier = vasync.barrier();
    var mountd = app.createMountServer(cfg_mount);
    var nfsd = app.createNfsServer(cfg_nfs);

    barrier.on('drain', function onRunning() {
        var ma = mountd.address();
        var na = nfsd.address();

        log.info('mountd: listening on: tcp://%s:%d',
                 ma.address, ma.port);
        log.info('nfsd: listening on: tcp://%s:%d',
                 na.address, na.port);

        if (uid !== 0) {
            // On non-windows machines we run as 'nobody'.
            // On sunos we have to wait until after we're listening on the nfs
            // port since the user 'nobody' will not have the sys_nfs priv.
            // On darwin 'nobody' is -2 and we error setting the uid/gid to a
            // negative number, so use the symbolic name.
            if (os_platform === 'darwin') {
                gid = uid = 'nobody';
            }
            step_down();
        }
    });

    barrier.start('mount');
    mountd.listen(cfg_mount.port || 1892,
                  cfg_mount.host || '127.0.0.1',
                  barrier.done.bind(barrier, 'mount'));

    barrier.start('nfs');
    nfsd.listen(cfg_nfs.port || 2049,
                cfg_nfs.host || '127.0.0.1',
                barrier.done.bind(barrier, 'nfs'));
}

// Darwin uses negative numbers for 'nobody' but these get pulled out as a
// large non-negative number. Convert to twos-complement.
function convert_neg_id(id)
{
    if (id > 0x7fffffff)
        return (-(~id + 1));
    else
        return (id);
}

///--- Mainline

(function main() {
    var cfg = configure();
    var log = cfg.log;

    os_platform = os.platform();
    if (os_platform !== 'win32') {
        uid = convert_neg_id(userid.uid('nobody'));
        try {
            gid = convert_neg_id(userid.gid('nobody'));
        } catch (e1) {
            // Linux uses 'nogroup' instead of 'nobody'
            try {
                gid = convert_neg_id(userid.gid('nogroup'));
            } catch (e2) {
                gid = uid;
            }
        }
    }

    var mfs = mantafs.createClient({
        files: cfg.database.max_files,
        log: log.child({component: 'MantaFs'}, true),
        manta: cfg.manta,
        path: cfg.database.location,
        sizeMB: cfg.database.sizeMB,
        ttl: cfg.database.ttl,
        uid: cfg.nfs.uid || uid,
        gid: cfg.nfs.gid || gid
    });

    cfg.mount.fs = mfs;
    cfg.nfs.fs = mfs;
    cfg.nfs.fd_cache = LRU({
        dispose: function cache_close_fd(k, v) {
            mfs.close(v.fd, function on_close(err) {
                if (err)
                    log.debug(err, 'failed to close(fd=%d) for %s', v.fd, k);
            });
        },
        max: cfg.nfs.fd_cache.max,
        maxAge: cfg.nfs.fd_cache.ttl * 1000 // 1m TTL
    });

    cfg.nfs.cachepath = cfg.database.location;    // used by fsstat

    var mntmapping = {
        prog: 100005,
        vers: 3,
        prot: 6,
        port: 1892
    };

    var nfsmapping = {
        prog: 100003,
        vers: 3,
        prot: 6,
        port: 2049
    };
    var pmapclient;

    process.on('SIGINT', function () {
        log.info('Got SIGINT, shutting down.');
        mfs.shutdown(function (err) {
            if (err) {
                log.warn(err, 'mantafs shutdown error');
            }

            if (cfg.portmap.usehost) {
                pmapclient.unset(mntmapping, function (err1) {
                    if (err1) {
                        log.warn(err1,
                            'unable to unregister mountd from the portmapper');
                    }

                    pmapclient.unset(nfsmapping, function (err2) {
                        if (err2) {
                            log.warn(err2,
                            'unable to unregister nfsd from the portmapper');
                        }
                        log.info('Shutdown complete, exiting.');
                        process.exit(0);
                    });
                });
            } else {
                log.info('Shutdown complete, exiting.');
                process.exit(0);
            }
        });
    });

    mfs.once('error', function (err) {
        log.fatal(err, 'unable to initialize mantafs cache');
        process.exit(1);
    });
    mfs.once('ready', function () {
        // Cache exists now, ensure cache dir modes are more secure
        fs.chmodSync(mfs.path, 0700);
        fs.chmodSync(path.join(mfs.path, 'fscache'), 0700);
        fs.chmodSync(path.join(mfs.path, 'manta.db'), 0600);
        if (uid !== 0) {
            // On non-windows machines we run as 'nobody'. Tighten up now.
            fs.chownSync(mfs.path, uid, gid);
            fs.chownSync(path.join(mfs.path, 'fscache'), uid, gid);
            fs.chownSync(path.join(mfs.path, 'manta.db'), uid, gid);
        }

        // the portmapper needs to listen on all addresses, unlike our mountd
        // and nfsd which only listen on localhost by default for some basic
        // security
        cfg.portmap.host = cfg.portmap.host || '0.0.0.0';
        cfg.portmap.port = cfg.portmap.port || 111;

        // Use the system's portmapper
        function register_with_pmap() {
            // The Linux portmapper normally rejects requests that are not
            // made to the loopback address.
            cfg.portmap.url = util.format('udp://127.0.0.1:%d',
                cfg.portmap.port);
            pmapclient = app.createPortmapClient(cfg.portmap);

            pmapclient.once('connect', function () {
                pmapclient.set(mntmapping, function (err1) {
                    if (err1) {
                        log.fatal(err1,
                            'unable to register mountd with the portmapper');
                        process.exit(1);
                    }

                    pmapclient.set(nfsmapping, function (err2) {
                        if (err2) {
                            log.fatal(err2,
                                'unable to register nfsd with the portmapper');
                            process.exit(1);
                        }

                        run_servers(cfg.log, cfg.mount, cfg.nfs);
                    });
                });
            });
        }

        if (cfg.portmap.usehost) {
            register_with_pmap();
        } else {
            // Here we run our own portmapper
            var pmapd = app.createPortmapServer(cfg.portmap);

            pmapd.on('error', function (e) {
                if (e.code == 'EADDRINUSE') {
                    log.info('Portmapper address in use, registering...');
                    register_with_pmap();
                } else {
                    log.fatal(e, 'unable to run the portmapper');
                    process.exit(1);
                }
            });

            pmapd.listen(cfg.portmap.port, cfg.portmap.host, function () {
                run_servers(cfg.log, cfg.mount, cfg.nfs);
            });
       }
    });
})();
<|endoftext|>


<commit_before>'use strict'

const express = require('express')
const Slapp = require('slapp')
const ConvoStore = require('slapp-convo-beepboop')
const Context = require('slapp-context-beepboop')

// use `PORT` env var on Beep Boop - default to 3000 locally
var port = process.env.PORT || 3000

var slapp = Slapp({
  // Beep Boop sets the SLACK_VERIFY_TOKEN env var
  verify_token: process.env.SLACK_VERIFY_TOKEN,
  convo_store: ConvoStore(),
  context: Context()
})

var HELP_TEXT = `
I will respond to the following messages:
\`help\` - to see this message.
\`hi\` - to demonstrate a conversation that tracks state.
\`thanks\` - to demonstrate a simple response.
\`<type-any-other-text>\` - to demonstrate a random emoticon response, some of the time :wink:.
\`attachment\` - to see a Slack attachment message.
`

//*********************************************
// Setup different handlers for messages
//*********************************************

// response to the user typing "help"
slapp.message('help', ['mention', 'direct_message'], (msg) => {
  msg.say(HELP_TEXT)
})

// "Conversation" flow that tracks state - kicks off when user says hi, hello or hey
slapp
  .message('^(hi|hello|hey)$', ['direct_mention', 'direct_message'], (msg, text) => {
    msg
      .say(`${text}, how are you?`)
      // sends next event from user to this route, passing along state
      .route('how-are-you', { greeting: text })
  })
  .route('how-are-you', (msg, state) => {
    var text = (msg.body.event && msg.body.event.text) || ''

    // user may not have typed text as their next action, ask again and re-route
    if (!text) {
      return msg
        .say("Whoops, I'm still waiting to hear how you're doing.")
        .say('How are you?')
        .route('how-are-you', state)
    }

    // add their response to state
    state.status = text

    msg
      .say(`Ok then. What's your favorite color?`)
      .route('color', state)
  })
  .route('color', (msg, state) => {
    var text = (msg.body.event && msg.body.event.text) || ''

    // user may not have typed text as their next action, ask again and re-route
    if (!text) {
      return msg
        .say("I'm eagerly awaiting to hear your favorite color.")
        .route('color', state)
    }

    // add their response to state
    state.color = text

    msg
      .say('Thanks for sharing.')
      .say(`Here's what you've told me so far: \`\`\`${JSON.stringify(state)}\`\`\``)
    // At this point, since we don't route anywhere, the "conversation" is over
  })

// Can use a regex as well
slapp.message(/^(thanks|thank you)/i, ['mention', 'direct_message'], (msg) => {
  // You can provide a list of responses, and a random one will be chosen
  // You can also include slack emoji in your responses
  msg.say([
    "You're welcome :smile:",
    'You bet',
    ':+1: Of course',
    'Anytime :sun_with_face: :full_moon_with_face:'
  ])
})

// demonstrate returning an attachment...
slapp.message('attachment', ['mention', 'direct_message'], (msg) => {
  msg.say({
    text: 'Check out this amazing attachment! :confetti_ball: ',
    attachments: [{
      text: 'Slapp is a robust open source library that sits on top of the Slack APIs',
      title: 'Slapp Library - Open Source',
      image_url: 'https://storage.googleapis.com/beepboophq/_assets/bot-1.22f6fb.png',
      title_link: 'https://beepboophq.com/',
      color: '#7CD197'
    }]
  })
})

// Catch-all for any other responses not handled above
slapp.message('.*', ['direct_mention', 'direct_message'], (msg) => {
  // respond only 40% of the time
  if (Math.random() < 0.4) {
    msg.say([':wave:', ':pray:', ':raised_hands:'])
  }
})

// attach Slapp to express server
var server = slapp.attachToExpress(express())

// start http server
server.listen(port, (err) => {
  if (err) {
    return console.error(err)
  }

  console.log(`Listening on port ${port}`)
})
<commit_msg>added inspire me event<commit_after>'use strict'

const express = require('express')
const Slapp = require('slapp')
const ConvoStore = require('slapp-convo-beepboop')
const Context = require('slapp-context-beepboop')

// use `PORT` env var on Beep Boop - default to 3000 locally
var port = process.env.PORT || 3000

var slapp = Slapp({
  // Beep Boop sets the SLACK_VERIFY_TOKEN env var
  verify_token: process.env.SLACK_VERIFY_TOKEN,
  convo_store: ConvoStore(),
  context: Context()
})

var HELP_TEXT = `
I will respond to the following messages:
\`help\` - to see this message.
\`hi\` - to demonstrate a conversation that tracks state.
\`thanks\` - to demonstrate a simple response.
\`<type-any-other-text>\` - to demonstrate a random emoticon response, some of the time :wink:.
\`attachment\` - to see a Slack attachment message.
`

//*********************************************
// Setup different handlers for messages
//*********************************************

// response to the user typing "inspire me"
slapp.message('inspire me', ['mention', 'direct_message'], (msg) => {
  msg.say(["Shoot for the moon, for if you miss you'll land among the stars.", ':pray:', ':raised_hands:'])
})

// "Conversation" flow that tracks state - kicks off when user says hi, hello or hey
slapp
  .message('^(hi|hello|hey)$', ['direct_mention', 'direct_message'], (msg, text) => {
    msg
      .say(`${text}, how are you?`)
      // sends next event from user to this route, passing along state
      .route('how-are-you', { greeting: text })
  })
  .route('how-are-you', (msg, state) => {
    var text = (msg.body.event && msg.body.event.text) || ''

    // user may not have typed text as their next action, ask again and re-route
    if (!text) {
      return msg
        .say("Whoops, I'm still waiting to hear how you're doing.")
        .say('How are you?')
        .route('how-are-you', state)
    }

    // add their response to state
    state.status = text

    msg
      .say(`Ok then. What's your favorite color?`)
      .route('color', state)
  })
  .route('color', (msg, state) => {
    var text = (msg.body.event && msg.body.event.text) || ''

    // user may not have typed text as their next action, ask again and re-route
    if (!text) {
      return msg
        .say("I'm eagerly awaiting to hear your favorite color.")
        .route('color', state)
    }

    // add their response to state
    state.color = text

    msg
      .say('Thanks for sharing.')
      .say(`Here's what you've told me so far: \`\`\`${JSON.stringify(state)}\`\`\``)
    // At this point, since we don't route anywhere, the "conversation" is over
  })

// Can use a regex as well
slapp.message(/^(thanks|thank you)/i, ['mention', 'direct_message'], (msg) => {
  // You can provide a list of responses, and a random one will be chosen
  // You can also include slack emoji in your responses
  msg.say([
    "You're welcome :smile:",
    'You bet',
    ':+1: Of course',
    'Anytime :sun_with_face: :full_moon_with_face:'
  ])
})

// Catch-all for any other responses not handled above
slapp.message('.*', ['direct_mention', 'direct_message'], (msg) => {
  // respond only 40% of the time
  if (Math.random() < 0.4) {
    msg.say([':wave:', ':pray:', ':raised_hands:'])
  }
})

// attach Slapp to express server
var server = slapp.attachToExpress(express())

// start http server
server.listen(port, (err) => {
  if (err) {
    return console.error(err)
  }

  console.log(`Listening on port ${port}`)
})
<|endoftext|>


<commit_before>import { h, Component } from "preact";
import * as styles from "./Joyplot.scss";
import * as d3 from "d3";

class Joyplot extends Component {
  constructor(props) {
    super(props);

    this.createChart = this.createChart.bind(this); // Bind to access within method
  }
  componentWillMount() {}

  componentDidMount() {
    this.loadData();
  }

  componentDidUpdate() {
    this.loadData();
  }

  createChart(error, dataFlat) {
    // Initial values
    let margin = { top: 30, right: 20, bottom: 60, left: 20 },
      width = parseInt(d3.select("." + styles.joyplot).style("width"), 10),
      joyplotWidth = 700,
      joyplotHeight = 76,
      labelMargin = 200,
      labelOffset = 70,
      spacing = 52,
      totalPlots = dataFlat.columns.length - 1,
      height = (totalPlots - 1) * spacing + joyplotHeight,
      joyplotFill = "rgba(0, 125, 153, 0.6",
      lineWidth = 1;

    // We are using Mike Bostock's margin conventions https://bl.ocks.org/mbostock/3019563
    width = width - margin.left - margin.right;

    // Set up a date parser
    var parseDate = d3.timeParse("%d/%m/%Y");

    // set the range scales
    var xScale = d3.scaleTime().range([labelMargin, width]);
    var yScale = d3.scaleLinear().range([joyplotHeight, 0]);

    // define the chart area
    let area = d3
      .area()
      .x(d => {
        return xScale(d.Week);
      })
      .y0(yScale(0))
      .curve(d3.curveMonotoneX);

    let lineData = [[0, 0], [width, 0]];

    let lineGenerator = d3.line();

    let pathString = lineGenerator(lineData);

    // Parse the dates to use full date format
    dataFlat.forEach(d => {
      d.Week = parseDate(d["Week"]);
    });

    // Convert the number strings to integers
    dataFlat.columns.forEach(d => {
      dataFlat.forEach(e => {
        if (d === "Week") return;
        e[d] = +e[d];
      });
    });

    // Draw the chart
    var svg = d3
      .select("." + styles.joyplot)
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
      .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    xScale.domain(
      d3.extent(dataFlat, function(d) {
        return d.Week;
      })
    );

    yScale.domain([
      0,
      d3.max(dataFlat, function(d) {
        return d["Sydney siege"];
      })
    ]);

    // Loop through data and plot the area chart
    dataFlat.columns.forEach((volume, i) => {
      if (volume === "Week") return;

      area.y1(d => {
        return yScale(d[volume]);
      });

      var downPage = spacing * (i - 1);

      console.log(spacing, i, downPage);

      let downPageText = spacing * (i - 1) + labelOffset;
      let downPageLine = spacing * (i - 1) + joyplotHeight + 1;

      svg
        .append("path")
        .attr("class", styles.singlePlot)
        .datum(dataFlat)
        .attr("fill", joyplotFill)
        .attr("transform", "translate(0, " + downPage + ")")
        .attr("d", area);

      // Draw a baseline
      svg
        .append("path")
        .attr("class", styles.singlePlot)
        .attr("d", pathString)
        .attr("stroke", joyplotFill)
        .attr("stroke-width", lineWidth + "px")
        .attr("fill", "none")
        .attr("shape-rendering", "crispEdges")
        .attr("transform", "translate(0, " + downPageLine + ")");

      svg
        .append("text")
        .text(volume)
        .style("font-size", "16px")
        .style("fill", "#444")
        .attr("transform", "translate(0, " + downPageText + ")");

      // Remove and redraw chart
      d3.select(window).on("resize", resize);

      function resize() {
        width = parseInt(d3.select("." + styles.joyplot).style("width"), 10);
        width = width - margin.left - margin.right;

        xScale = d3.scaleTime().range([labelMargin, width]);

        xScale.domain(
          d3.extent(dataFlat, function(d) {
            return d.Week;
          })
        );

        lineData = [[0, 0], [width, 0]];
        pathString = lineGenerator(lineData);

        d3.selectAll("." + styles.singlePlot).remove();

        dataFlat.columns.forEach((volume, i) => {
          if (volume === "Week") return;

          area.y1(d => {
            return yScale(d[volume]);
          });

          let downPage = spacing * (i - 1);
          let downPageLine = spacing * (i - 1) + joyplotHeight + 1;
          let downPageText = spacing * (i - 1) + 95;

          svg
            .append("path")
            .attr("class", styles.singlePlot)
            .datum(dataFlat)
            .attr("fill", "rgba(0, 125, 153, 0.6")
            .attr("transform", "translate(0, " + downPage + ")")
            .attr("d", area);

          svg
            .append("path")
            .attr("class", styles.singlePlot)
            .attr("d", pathString)
            .attr("stroke", joyplotFill)
            .attr("stroke-width", lineWidth + "px")
            .attr("fill", "none")
            .attr("transform", "translate(0, " + downPageLine + ")");
        });
      }
    });
  }

  loadData() {
    d3
      .queue(2) // Load 2 files concurrently (if there are more than 1)
      .defer(d3.csv, this.props.dataUrl)
      .await(this.createChart);
  }

  render(props, state) {
    return (

        <svg className={styles.joyplot} />

    );
  }
}

module.exports = Joyplot;
<commit_msg>Different browsers do different things sometimes ........<commit_after>import { h, Component } from "preact";
import * as styles from "./Joyplot.scss";
import * as d3 from "d3";

class Joyplot extends Component {
  constructor(props) {
    super(props);

    this.createChart = this.createChart.bind(this); // Bind to access within method
  }
  componentWillMount() {}

  componentDidMount() {
    this.loadData();
  }

  componentDidUpdate() {
    this.loadData();
  }

  createChart(error, dataFlat) {
    // Initial values
    let margin = { top: 30, right: 20, bottom: 60, left: 20 },
      width = parseInt(d3.select("." + styles.joyplot).style("width"), 10),
      joyplotWidth = 700,
      joyplotHeight = 76,
      labelMargin = 200,
      labelOffset = 70,
      spacing = 52,
      totalPlots = dataFlat.columns.length - 1,
      height = (totalPlots - 1) * spacing + joyplotHeight,
      joyplotFill = "rgba(0, 125, 153, 0.6",
      lineWidth = 1,
      shapeRendering = "crispEdges";

    // We are using Mike Bostock's margin conventions https://bl.ocks.org/mbostock/3019563
    width = width - margin.left - margin.right;

    // Due to a weird Firefox bug we need to sniff user agent
    var chrome = navigator.userAgent.indexOf("Chrome") > -1;
    var explorer = navigator.userAgent.indexOf("MSIE") > -1;
    var firefox = navigator.userAgent.indexOf("Firefox") > -1;
    var safari = navigator.userAgent.indexOf("Safari") > -1;
    var camino = navigator.userAgent.indexOf("Camino") > -1;
    var opera = navigator.userAgent.toLowerCase().indexOf("op") > -1;
    if (chrome && safari) safari = false;
    if (chrome && opera) chrome = false;

    // Set up a date parser
    var parseDate = d3.timeParse("%d/%m/%Y");

    // set the range scales
    var xScale = d3.scaleTime().range([labelMargin, width]);
    var yScale = d3.scaleLinear().range([joyplotHeight, 0]);

    // define the chart area
    let area = d3
      .area()
      .x(d => {
        return xScale(d.Week);
      })
      .y0(yScale(0))
      .curve(d3.curveMonotoneX);

    let lineData = [[0, 0], [width, 0]];

    let lineGenerator = d3.line();

    let pathString = lineGenerator(lineData);

    // Parse the dates to use full date format
    dataFlat.forEach(d => {
      d.Week = parseDate(d["Week"]);
    });

    // Convert the number strings to integers
    dataFlat.columns.forEach(d => {
      dataFlat.forEach(e => {
        if (d === "Week") return;
        e[d] = +e[d];
      });
    });

    // Draw the chart
    var svg = d3
      .select("." + styles.joyplot)
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
      .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    xScale.domain(
      d3.extent(dataFlat, function(d) {
        return d.Week;
      })
    );

    yScale.domain([
      0,
      d3.max(dataFlat, function(d) {
        return d["Sydney siege"];
      })
    ]);

    // Loop through data and plot the area chart
    dataFlat.columns.forEach((volume, i) => {
      if (volume === "Week") return;

      area.y1(d => {
        return yScale(d[volume]);
      });

      let downPage = spacing * (i - 1);
      let downPageText = spacing * (i - 1) + labelOffset;
      let downPageLine = spacing * (i - 1) + joyplotHeight;

      // Firefox and Opera render these lines 1px down so
      if (firefox || opera) downPageLine--;

      svg
        .append("path")
        .attr("class", styles.singlePlot)
        .datum(dataFlat)
        .attr("fill", joyplotFill)
        .attr("transform", "translate(0, " + downPage + ")")
        .attr("d", area);

      // Draw a baseline
      svg
        .append("path")
        .attr("class", styles.singlePlot)
        .attr("d", pathString)
        .attr("stroke", joyplotFill)
        .attr("stroke-width", lineWidth + "px")
        .attr("fill", "none")
        .attr("shape-rendering", shapeRendering)
        .attr("transform", "translate(0, " + downPageLine + ")");

      svg
        .append("text")
        .text(volume)
        .style("font-size", "16px")
        .style("fill", "#444")
        .attr("transform", "translate(0, " + downPageText + ")");

      // Remove and redraw chart
      d3.select(window).on("resize", resize);

      function resize() {
        width = parseInt(d3.select("." + styles.joyplot).style("width"), 10);
        width = width - margin.left - margin.right;

        xScale = d3.scaleTime().range([labelMargin, width]);

        xScale.domain(
          d3.extent(dataFlat, function(d) {
            return d.Week;
          })
        );

        lineData = [[0, 0], [width, 0]];
        pathString = lineGenerator(lineData);

        d3.selectAll("." + styles.singlePlot).remove();

        dataFlat.columns.forEach((volume, i) => {
          if (volume === "Week") return;

          area.y1(d => {
            return yScale(d[volume]);
          });

          let downPage = spacing * (i - 1);
          let downPageLine = spacing * (i - 1) + joyplotHeight;
          let downPageText = spacing * (i - 1) + 95;

          // Firefox and Opera render these lines 1px down so
          if (firefox || opera) downPageLine--;

          svg
            .append("path")
            .attr("class", styles.singlePlot)
            .datum(dataFlat)
            .attr("fill", "rgba(0, 125, 153, 0.6")
            .attr("transform", "translate(0, " + downPage + ")")
            .attr("d", area);

          svg
            .append("path")
            .attr("class", styles.singlePlot)
            .attr("d", pathString)
            .attr("stroke", joyplotFill)
            .attr("stroke-width", lineWidth + "px")
            .attr("fill", "none")
            .attr("shape-rendering", shapeRendering)
            .attr("transform", "translate(0, " + downPageLine + ")");
        });
      }
    });
  }

  loadData() {
    d3
      .queue(2) // Load 2 files concurrently (if there are more than 1)
      .defer(d3.csv, this.props.dataUrl)
      .await(this.createChart);
  }

  render(props, state) {
    return (

        <svg className={styles.joyplot} />

    );
  }
}

module.exports = Joyplot;
<|endoftext|>


<commit_before>/*
 The MIT License (MIT)

 Copyright (c) 2013 Piotr Raczynski, pio[dot]raczynski[at]gmail[dot]com

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the 'Software'), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in all
 copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 SOFTWARE.
 */

var inherits = require('super'),
    fs = require('fs'),
    Promise = require('bluebird'),
    SqueezeRequest = require('./squeezerequest'),
    SqueezePlayer = require('./squeezeplayer');

function SqueezeServer(address, port, username, password) {
    var self = this,
        defaultPlayer = '00:00:00:00:00:00';

    SqueezeServer.super_.apply(self, arguments);

    self.players = {};
    self.apps = {};
    self.playerUpdateInterval = 2000;

    self.getPlayerCount = function () {
        return self.request(defaultPlayer, ['player', 'count', '?']);
    };

    self.getPlayerId = function (id) {
        return self.request(defaultPlayer, ['player', 'id', id, '?']);
    };

    self.getPlayerIp = function (playerId) {
        return self.request(defaultPlayer, ['player', 'ip', playerId, '?']);
    };

    self.getPlayerName = function (playerId) {
        return self.request(defaultPlayer, ['player', 'name', playerId, '?']);
    };

    self.getSyncGroups = function () {
        return self.request(defaultPlayer, ['syncgroups', '?']);
    };

    self.getApps = function () {
        return self.request(defaultPlayer, ['apps', 0, 100000]);
    };

    self.getPlayers = function () {
        return self.request(defaultPlayer, ['players', 0, 100000]).then(
            function (reply) {
                if (reply.ok) {
                    reply.count = reply.result.count;
                    reply.result = reply.result.players_loop;
                }
                return reply;
            });
    };

    self.totals = function () {
        return Promise.all([
            self.request(defaultPlayer, ['info', 'total', 'artists', '?']),
            self.request(defaultPlayer, ['info', 'total', 'albums', '?']),
            self.request(defaultPlayer, ['info', 'total', 'songs', '?']),
            self.request(defaultPlayer, ['info', 'total', 'genres', '?'])])
            .spread(function (artists, albums, songs, genres) {
                var response = {};
                response.artists = (artists.ok) ? artists.result._artists : 0;
                response.albums = (albums.ok) ? albums.result._albums : 0;
                response.songs = (songs.ok) ? songs.result._songs : 0;
                response.genres = (genres.ok) ? genres.result._genres : 0;
                return response;
            });
    };

    /**
     * Search for artists given artist name
     * Returns {id, artist}
     * @param artistName String search criteria or all artists if null
     * @param skip Number start at
     * @param take Number take this many
     * @return {*}
     */
    self.artists = function (artistName, skip, take) {
        var s = !Number.isNaN(skip) && skip >= 0 ? skip : '_',
            t = !Number.isNaN(take) && take >= 1 ? take : '_',
            params = ['artists', s, t];
        if (!!artistName) {
            params.push('search:' + artistName);
        }
        return self.request(defaultPlayer, params).then(
            function (reply) {
                if (reply.ok) {
                    reply.count = reply.result.count;
                    reply.result = reply.result.artists_loop;
                }
                return reply;
            });
    };

    /**
     * Search for albums given album name
     * Returns {id, title, artist_id, artist_ids}
     * @param albumName String search criteria or all albums if null
     * @param skip Number start at
     * @param take Number take this many
     * @return {*}
     */
    self.albums = function (albumName, skip, take) {
        var s = !Number.isNaN(skip) && skip >= 0 ? skip : '_',
            t = !Number.isNaN(take) && take >= 1 ? take : '_',
            params = ['albums', s, t, 'tags:tSS'];
        if (!!albumName) {
            params.push('search:' + albumName);
        }
        return self.request(defaultPlayer, params).then(
            function (reply) {
                if (reply.ok) {
                    reply.count = reply.result.count;
                    reply.result = reply.result.albums_loop;
                }
                return reply;
            });
    };

    /**
     * Search for songs given song name
     * Returns {id, title, artist_id, artist_ids, band_ids, composer_ids, album_id, url, genre_id}
     * @param songName String search criteria or all songs if null
     * @param skip Number start at
     * @param take Number take this many
     * @return {*}
     */
    self.songs = function (songName, skip, take) {
        var s = !Number.isNaN(skip) && skip >= 0 ? skip : '_',
            t = !Number.isNaN(take) && take >= 1 ? take : '_',
            params = ['albums', s, t, 'tags:seuSp'];
        if (!!songName) {
            params.push('search:' + songName);
        }
        return self.request(defaultPlayer, params).then(
            function (reply) {
                if (reply.ok) {
                    reply.count = reply.result.count;
                    reply.result = reply.result.titles_loop;
                }
                return reply;
            });
    };

    /**
     * Search for genres given genre name
     * Returns {id, genre}
     * @param genreName String search criteria or all genres if null
     * @param skip Number start at
     * @param take Number take this many
     * @return {*}
     */
    self.genres = function (genreName, skip, take) {
        var s = !Number.isNaN(skip) && skip >= 0 ? skip : '_',
            t = !Number.isNaN(take) && take >= 1 ? take : '_',
            params = ['genres', s, t];
        if (!!genreName) {
            params.push('search:' + genreName);
        }
        return self.request(defaultPlayer, params).then(
            function (reply) {
                if (reply.ok) {
                    reply.count = reply.result.count;
                    reply.result = reply.result.genres_loop;
                }
                return reply;
            });
    };

    /**
     * Search for playlists given playlist name
     * Returns {id, playlist, url}
     * @param playlistName String search criteria or all playlists if null
     * @param skip Number start at
     * @param take Number take this many
     * @return {*}
     */
    self.playlists = function (playlistName, skip, take) {
        var s = !Number.isNaN(skip) && skip >= 0 ? skip : 0,
            t = !Number.isNaN(take) && take >= 1 ? take : 100000,
            params = ['playlists', s, t, 'tags:u'];
        if (!!playlistName) {
            params.push('search:' + playlistName);
        }
        return self.request(defaultPlayer, params).then(
            function (reply) {
                if (reply.ok) {
                    reply.count = reply.result.count;
                    reply.result = reply.result.playlists_loop;
                }
                return reply;
            });
    };

    /**
     * Search for albums given artist id
     * Returns {id, title, artist_id, artist_ids}
     * @param artist_id
     * @param skip
     * @param take
     * @return {*}
     */
    self.albumsByArtist = function (artist_id, skip, take) {
        skip = !Number.isNaN(skip) && skip >= 0 ? skip : '_';
        take = !Number.isNaN(take) && take >= 1 ? take : '_';
        return self.request(defaultPlayer, ['albums', skip, take, 'artist_id:' + artist_id, 'tags:tSS']).then(
            function (reply) {
                if (reply.ok) {
                    reply.count = reply.result.count;
                    reply.result = reply.result.albums_loop;
                }
                return reply;
            });
    };

    /**
     * Search for songs given album id
     * Returns {id, title, artist_id, artist_ids, band_ids, composer_ids, album_id, url, genre_id}
     * @param album_id
     * @param skip
     * @param take
     * @return {*}
     */
    self.songsByAlbum = function (album_id, skip, take) {
        skip = !Number.isNaN(skip) && skip >= 0 ? skip : '_';
        take = !Number.isNaN(take) && take >= 1 ? take : '_';
        return self.request(defaultPlayer, ['songs', skip, take, 'album_id:' + album_id, 'tags:seuSp']).then(
            function (reply) {
                if (reply.ok) {
                    reply.count = reply.result.count;
                    reply.result = reply.result.titles_loop;
                }
                return reply;
            });
    };

    /**
     * Search for songs given artist id
     * Returns {id, title, artist_id, artist_ids, band_ids, composer_ids, album_id, url, genre_id}
     * @param artist_id
     * @param skip
     * @param take
     * @return {*}
     */
    self.songsByArtist = function (artist_id, skip, take) {
        skip = !Number.isNaN(skip) && skip >= 0 ? skip : '_';
        take = !Number.isNaN(take) && take >= 1 ? take : '_';
        return self.request(defaultPlayer, ['songs', skip, take, 'artist_id:' + artist_id, 'tags:seuSp']).then(
            function (reply) {
                if (reply.ok) {
                    reply.count = reply.result.count;
                    reply.result = reply.result.titles_loop;
                }
                return reply;
            });
    };

    /**
     * Search for songs given genre id
     * Returns {id, title, artist_id, artist_ids, band_ids, composer_ids, album_id, url, genre_id}
     * @param genre_id
     * @param skip
     * @param take
     * @return {*}
     */
    self.songsByGenre = function (genre_id, skip, take) {
        skip = !Number.isNaN(skip) && skip >= 0 ? skip : '_';
        take = !Number.isNaN(take) && take >= 1 ? take : '_';
        return self.request(defaultPlayer, ['songs', skip, take, 'genre_id:' + genre_id, 'tags:seuSp']).then(
            function (reply) {
                if (reply.ok) {
                    reply.count = reply.result.count;
                    reply.result = reply.result.titles_loop;
                }
                return reply;
            });
    };

    self.register = function () {
        return new Promise(function (resolve, reject) {
            self.getPlayers().then(function (reply) {
                var players = reply.result;

                // clear players and apps before filling
                self.players = {};
                self.apps = {};

                // set players
                if (reply.ok) {
                    players.forEach(function (player) {
                        if (!self.players[player.playerid]) {
                            // player not on the list, add it
                            self.players[player.playerid] = new SqueezePlayer(player.playerid,
                                player.name, self.address, self.port, self.username, self.password);
                        }
                    });

                    self.getApps().then(function (reply) {
                        // set apps
                        if (reply.ok) {
                            var apps = reply.result.appss_loop,
                                dir = __dirname + '/';
                            fs.readdir(dir, function (err, files) {
                                files.forEach(function (file) {
                                    var app,
                                        fil = file.substr(0, file.lastIndexOf('.'));

                                    apps.forEach(function (player) {
                                        if (fil === player.cmd) {
                                            app = require(dir + file);
                                            self.apps[player.cmd] = new app(defaultPlayer, player.name, player.cmd,
                                                self.address, self.port, self.username, self.password);
                                            /* workaround, app needs existing player id so first is used here */
                                        }
                                    });
                                });
                                resolve();
                            });
                        } else {
                            reject(reply);
                        }
                    });
                } else {
                    reject(reply);
                }
            });
        });
    };
}

inherits(SqueezeServer, SqueezeRequest);

module.exports = SqueezeServer;
<commit_msg>fix api call<commit_after>/*
 The MIT License (MIT)

 Copyright (c) 2013 Piotr Raczynski, pio[dot]raczynski[at]gmail[dot]com

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the 'Software'), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in all
 copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 SOFTWARE.
 */

var inherits = require('super'),
    fs = require('fs'),
    Promise = require('bluebird'),
    SqueezeRequest = require('./squeezerequest'),
    SqueezePlayer = require('./squeezeplayer');

function SqueezeServer(address, port, username, password) {
    var self = this,
        defaultPlayer = '00:00:00:00:00:00';

    SqueezeServer.super_.apply(self, arguments);

    self.players = {};
    self.apps = {};
    self.playerUpdateInterval = 2000;

    self.getPlayerCount = function () {
        return self.request(defaultPlayer, ['player', 'count', '?']);
    };

    self.getPlayerId = function (id) {
        return self.request(defaultPlayer, ['player', 'id', id, '?']);
    };

    self.getPlayerIp = function (playerId) {
        return self.request(defaultPlayer, ['player', 'ip', playerId, '?']);
    };

    self.getPlayerName = function (playerId) {
        return self.request(defaultPlayer, ['player', 'name', playerId, '?']);
    };

    self.getSyncGroups = function () {
        return self.request(defaultPlayer, ['syncgroups', '?']);
    };

    self.getApps = function () {
        return self.request(defaultPlayer, ['apps', 0, 100000]);
    };

    self.getPlayers = function () {
        return self.request(defaultPlayer, ['players', 0, 100000]).then(
            function (reply) {
                if (reply.ok) {
                    reply.count = reply.result.count;
                    reply.result = reply.result.players_loop;
                }
                return reply;
            });
    };

    self.totals = function () {
        return Promise.all([
            self.request(defaultPlayer, ['info', 'total', 'artists', '?']),
            self.request(defaultPlayer, ['info', 'total', 'albums', '?']),
            self.request(defaultPlayer, ['info', 'total', 'songs', '?']),
            self.request(defaultPlayer, ['info', 'total', 'genres', '?'])])
            .spread(function (artists, albums, songs, genres) {
                var response = {};
                response.artists = (artists.ok) ? artists.result._artists : 0;
                response.albums = (albums.ok) ? albums.result._albums : 0;
                response.songs = (songs.ok) ? songs.result._songs : 0;
                response.genres = (genres.ok) ? genres.result._genres : 0;
                return response;
            });
    };

    /**
     * Search for artists given artist name
     * Returns {id, artist}
     * @param artistName String search criteria or all artists if null
     * @param skip Number start at
     * @param take Number take this many
     * @return {*}
     */
    self.artists = function (artistName, skip, take) {
        var s = !Number.isNaN(skip) && skip >= 0 ? skip : '_',
            t = !Number.isNaN(take) && take >= 1 ? take : '_',
            params = ['artists', s, t];
        if (!!artistName) {
            params.push('search:' + artistName);
        }
        return self.request(defaultPlayer, params).then(
            function (reply) {
                if (reply.ok) {
                    reply.count = reply.result.count;
                    reply.result = reply.result.artists_loop;
                }
                return reply;
            });
    };

    /**
     * Search for albums given album name
     * Returns {id, title, artist_id, artist_ids}
     * @param albumName String search criteria or all albums if null
     * @param skip Number start at
     * @param take Number take this many
     * @return {*}
     */
    self.albums = function (albumName, skip, take) {
        var s = !Number.isNaN(skip) && skip >= 0 ? skip : '_',
            t = !Number.isNaN(take) && take >= 1 ? take : '_',
            params = ['albums', s, t, 'tags:tSS'];
        if (!!albumName) {
            params.push('search:' + albumName);
        }
        return self.request(defaultPlayer, params).then(
            function (reply) {
                if (reply.ok) {
                    reply.count = reply.result.count;
                    reply.result = reply.result.albums_loop;
                }
                return reply;
            });
    };

    /**
     * Search for songs given song name
     * Returns {id, title, artist_id, artist_ids, band_ids, composer_ids, album_id, url, genre_id}
     * @param songName String search criteria or all songs if null
     * @param skip Number start at
     * @param take Number take this many
     * @return {*}
     */
    self.songs = function (songName, skip, take) {
        var s = !Number.isNaN(skip) && skip >= 0 ? skip : '_',
            t = !Number.isNaN(take) && take >= 1 ? take : '_',
            params = ['songs', s, t, 'tags:seuSp'];
        if (!!songName) {
            params.push('search:' + songName);
        }
        return self.request(defaultPlayer, params).then(
            function (reply) {
                if (reply.ok) {
                    reply.count = reply.result.count;
                    reply.result = reply.result.titles_loop;
                }
                return reply;
            });
    };

    /**
     * Search for genres given genre name
     * Returns {id, genre}
     * @param genreName String search criteria or all genres if null
     * @param skip Number start at
     * @param take Number take this many
     * @return {*}
     */
    self.genres = function (genreName, skip, take) {
        var s = !Number.isNaN(skip) && skip >= 0 ? skip : '_',
            t = !Number.isNaN(take) && take >= 1 ? take : '_',
            params = ['genres', s, t];
        if (!!genreName) {
            params.push('search:' + genreName);
        }
        return self.request(defaultPlayer, params).then(
            function (reply) {
                if (reply.ok) {
                    reply.count = reply.result.count;
                    reply.result = reply.result.genres_loop;
                }
                return reply;
            });
    };

    /**
     * Search for playlists given playlist name
     * Returns {id, playlist, url}
     * @param playlistName String search criteria or all playlists if null
     * @param skip Number start at
     * @param take Number take this many
     * @return {*}
     */
    self.playlists = function (playlistName, skip, take) {
        var s = !Number.isNaN(skip) && skip >= 0 ? skip : 0,
            t = !Number.isNaN(take) && take >= 1 ? take : 100000,
            params = ['playlists', s, t, 'tags:u'];
        if (!!playlistName) {
            params.push('search:' + playlistName);
        }
        return self.request(defaultPlayer, params).then(
            function (reply) {
                if (reply.ok) {
                    reply.count = reply.result.count;
                    reply.result = reply.result.playlists_loop;
                }
                return reply;
            });
    };

    /**
     * Search for albums given artist id
     * Returns {id, title, artist_id, artist_ids}
     * @param artist_id
     * @param skip
     * @param take
     * @return {*}
     */
    self.albumsByArtist = function (artist_id, skip, take) {
        skip = !Number.isNaN(skip) && skip >= 0 ? skip : '_';
        take = !Number.isNaN(take) && take >= 1 ? take : '_';
        return self.request(defaultPlayer, ['albums', skip, take, 'artist_id:' + artist_id, 'tags:tSS']).then(
            function (reply) {
                if (reply.ok) {
                    reply.count = reply.result.count;
                    reply.result = reply.result.albums_loop;
                }
                return reply;
            });
    };

    /**
     * Search for songs given album id
     * Returns {id, title, artist_id, artist_ids, band_ids, composer_ids, album_id, url, genre_id}
     * @param album_id
     * @param skip
     * @param take
     * @return {*}
     */
    self.songsByAlbum = function (album_id, skip, take) {
        skip = !Number.isNaN(skip) && skip >= 0 ? skip : '_';
        take = !Number.isNaN(take) && take >= 1 ? take : '_';
        return self.request(defaultPlayer, ['songs', skip, take, 'album_id:' + album_id, 'tags:seuSp']).then(
            function (reply) {
                if (reply.ok) {
                    reply.count = reply.result.count;
                    reply.result = reply.result.titles_loop;
                }
                return reply;
            });
    };

    /**
     * Search for songs given artist id
     * Returns {id, title, artist_id, artist_ids, band_ids, composer_ids, album_id, url, genre_id}
     * @param artist_id
     * @param skip
     * @param take
     * @return {*}
     */
    self.songsByArtist = function (artist_id, skip, take) {
        skip = !Number.isNaN(skip) && skip >= 0 ? skip : '_';
        take = !Number.isNaN(take) && take >= 1 ? take : '_';
        return self.request(defaultPlayer, ['songs', skip, take, 'artist_id:' + artist_id, 'tags:seuSp']).then(
            function (reply) {
                if (reply.ok) {
                    reply.count = reply.result.count;
                    reply.result = reply.result.titles_loop;
                }
                return reply;
            });
    };

    /**
     * Search for songs given genre id
     * Returns {id, title, artist_id, artist_ids, band_ids, composer_ids, album_id, url, genre_id}
     * @param genre_id
     * @param skip
     * @param take
     * @return {*}
     */
    self.songsByGenre = function (genre_id, skip, take) {
        skip = !Number.isNaN(skip) && skip >= 0 ? skip : '_';
        take = !Number.isNaN(take) && take >= 1 ? take : '_';
        return self.request(defaultPlayer, ['songs', skip, take, 'genre_id:' + genre_id, 'tags:seuSp']).then(
            function (reply) {
                if (reply.ok) {
                    reply.count = reply.result.count;
                    reply.result = reply.result.titles_loop;
                }
                return reply;
            });
    };

    self.register = function () {
        return new Promise(function (resolve, reject) {
            self.getPlayers().then(function (reply) {
                var players = reply.result;

                // clear players and apps before filling
                self.players = {};
                self.apps = {};

                // set players
                if (reply.ok) {
                    players.forEach(function (player) {
                        if (!self.players[player.playerid]) {
                            // player not on the list, add it
                            self.players[player.playerid] = new SqueezePlayer(player.playerid,
                                player.name, self.address, self.port, self.username, self.password);
                        }
                    });

                    self.getApps().then(function (reply) {
                        // set apps
                        if (reply.ok) {
                            var apps = reply.result.appss_loop,
                                dir = __dirname + '/';
                            fs.readdir(dir, function (err, files) {
                                files.forEach(function (file) {
                                    var app,
                                        fil = file.substr(0, file.lastIndexOf('.'));

                                    apps.forEach(function (player) {
                                        if (fil === player.cmd) {
                                            app = require(dir + file);
                                            self.apps[player.cmd] = new app(defaultPlayer, player.name, player.cmd,
                                                self.address, self.port, self.username, self.password);
                                            /* workaround, app needs existing player id so first is used here */
                                        }
                                    });
                                });
                                resolve();
                            });
                        } else {
                            reject(reply);
                        }
                    });
                } else {
                    reject(reply);
                }
            });
        });
    };
}

inherits(SqueezeServer, SqueezeRequest);

module.exports = SqueezeServer;
<|endoftext|>