<commit_before>/**
 * Module dependencies
 */

var path = require('path');
var fs = require('fs');
var _ = require('@sailshq/lodash');
var chalk = require('chalk');
var COMMON_JS_FILE_EXTENSIONS = require('common-js-file-extensions');
var flaverr = require('flaverr');
var Process = require('machinepack-process');
var machineAsScript = require('machine-as-script');
var Sails = require('../lib/app');

/**
 * Module constants
 */

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Supported file extensions for imperative code files such as hooks:
//  • 'js' (.js)
//  • 'ts' (.ts)
//  • 'es6' (.es6)
//  • ...etc.
//
// > For full list, see:
// > https://github.com/luislobo/common-js-file-extensions/blob/210fd15d89690c7aaa35dba35478cb91c693dfa8/README.md#code-file-extensions
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
var BASIC_SUPPORTED_FILE_EXTENSIONS = COMMON_JS_FILE_EXTENSIONS.code;

/**
 * `sails run`
 *
 * Run a script for the Sails app in the current working directory.
 *
 * This matches either a JavaScript file in the `scripts/` directory, or one of the command-line scripts
 * declared within the `scripts: {}` dictionary in the package.json file.
 *
 * @see https://sailsjs.com/documentation/reference/command-line-interface/sails-run
 */

module.exports = function(scriptName) {

  // If there is only one argument, it means there is actually no scriptName at all.
  // (A detail of how commander works.)
  if (arguments.length === 1) {
    scriptName = undefined;
  }

  // Sanitize the script name, for comfort.
  if (!scriptName) {
    console.error('Which one?  (To run a script, provide its name.)');
    console.error('For example:');
    console.error('    sails run add-customer');
    console.error();
    console.error('^ runs `scripts/add-customer.js`.');
    console.error();
    console.error('(For more help, visit '+chalk.underline('http://sailsjs.com/support')+'.)');
    return process.exit(1);
  }

  scriptName = _.trim(scriptName);
  scriptName = scriptName.replace(/^scripts\//, '');
  if (scriptName.match(/\//)) {
    console.error('Cannot run `'+scriptName+'`.  Script name should never contain any slashes.');
    return process.exit(1);
  }//-•

  // Examine the script name and determine if it has a file extension included.
  // If so, we'll rip it out of the script name, but keep a reference to it.
  // Otherwise, we'll always assume that we're looking for a normal `.js` file.
  var X_BASIC_SUPPORTED_FILE_EXTENSION = new RegExp('^([^.]+)\\.(' + BASIC_SUPPORTED_FILE_EXTENSIONS.join('|') + ')$');
  var matchedFileExtension = scriptName.match(X_BASIC_SUPPORTED_FILE_EXTENSION);
  var fileExtension;
  if (matchedFileExtension) {
    fileExtension = matchedFileExtension[2];
    scriptName = scriptName.replace(X_BASIC_SUPPORTED_FILE_EXTENSION, '$1');
  }
  else {
    fileExtension = 'js';
  }

  // console.log(scriptName);
  // console.log(fileExtension);
  // return;

  // First, we need to determine the appropriate script to run.
  // (either a terminal command or a specially-formatted Node.js/Sails.js module)

  // We begin by figuring out whether this is a command-line script or a script (MaS) definition.
  var commandToRun;

  // Check the package.json file.
  try {
    var pathToLocalPackageJson = path.resolve(process.cwd(), 'package.json');
    var packageJson;
    try {
      packageJson = require(pathToLocalPackageJson);
    } catch (e) {
      switch (e.code) {
        case 'MODULE_NOT_FOUND': throw flaverr('E_NO_PACKAGE_JSON', new Error('No package.json file.  Are you sure you\'re in the root directory of a Node.js/Sails.js app?'));
        default: throw e;
      }
    }

    if (!_.isUndefined(packageJson.scripts) && (!_.isObject(packageJson.scripts) || _.isArray(packageJson.scripts))) {
      throw flaverr('E_MALFORMED_PACKAGE_JSON', new Error('This package.json file has an invalid `scripts` property -- should be a dictionary (plain JS object).'));
    }

    commandToRun = packageJson.scripts[scriptName];

  } catch (e) {
    switch (e.code) {
      case 'E_NO_PACKAGE_JSON':
      case 'E_MALFORMED_PACKAGE_JSON':
        console.error('--');
        console.error(chalk.red(e.message));
        return process.exit(1);

      default:
        console.error('--');
        console.error(chalk.bold('Oops, something unexpected happened:'));
        console.error(chalk.red(e.stack));
        console.error('--');
        console.error('Please read the error message above and troubleshoot accordingly.');
        console.error('(You can report suspected bugs at '+chalk.underline('http://sailsjs.com/bugs')+'.)');
        return process.exit(1);
    }
  }

  // Now check the `scripts/` directory to see if the file exists.
  var relativePathToScript = 'scripts/'+scriptName+'.'+fileExtension;
  var doesScriptFileExist = fs.existsSync(path.resolve(relativePathToScript));

  // Ensure that this script is not defined in BOTH places.
  if (commandToRun && doesScriptFileExist) {
    console.error('Cannot run `'+scriptName+'` because it is too ambiguous.');
    console.error('A script should only be defined once, but that script is defined in both the package.json file');
    console.error('AND as a file in the `scripts/` directory.');
    return process.exit(1);
  }

  // Ensure that this script exists one place or the other.
  if (!commandToRun && !doesScriptFileExist) {
    console.error('Unknown script: `'+scriptName+'`');
    console.error('No matching script is defined at `'+relativePathToScript+'`.');
    console.error('(And there is no matching NPM script in the package.json file.)');
    return process.exit(1);
  }

  // If this is a Node.js/Sails.js script (machine def), then require the script file
  // to get the module definition, then run it using MaS.
  if (!commandToRun) {
    try {
      var pathToScriptDef = path.resolve(process.cwd(), 'scripts/'+scriptName);
      var scriptDef;
      try {
        scriptDef = require(pathToScriptDef);
      } catch (e) {
        switch (e.code) {
          case 'MODULE_NOT_FOUND': throw flaverr('E_FAILED_TO_REQUIRE_SCRIPT_DEF', new Error('Encountered an error while loading the script definition.  Are you sure this is a well-formed Node.js/Sails.js script definition?  Error details:\n'+e.stack));
          default: throw e;
        }
      }

      // Make sure the script is at least basically valid.
      // (MaS will check it more later -- this is just preliminary -- and also to make sure that it's not `{}`,
      // the special indicator that the script definition didn't export _ANYTHING_ at all.)
      if (!_.isObject(scriptDef) || _.isArray(scriptDef) || _.isEqual(scriptDef, {})) {
        console.error('');
        console.error('');
        console.error('Invalid script: `'+scriptName+'`');
        console.error('');
        console.error('A well-formed Node.js/Sails.js script should export a script definition.');
        console.error('In other words, it should be defined more or less like this:');
        console.error('');
        console.error('    ```````````````````````````````````````````````````````````');
        console.error('    module.exports = {');
        console.error('      description: \'Do a thing given some stuff.\',');
        console.error('      inputs: {');
        console.error('        someStuff: { type: \'string\', required: true }');
        console.error('      },');
        console.error('      fn: function (inputs, exits) {');
        console.error('        // ...');
        console.error('        sails.log(\'Hello world!\');');
        console.error('        return exits.success();');
        console.error('      }');
        console.error('    };');
        console.error('    ```````````````````````````````````````````````````````````');
        console.error('');
        return process.exit(1);
      }

      // Modify the script definition to add `sails: require('sails')` and `habitat: 'sails'`
      // (unless it explicitly disables this behavior with `sails: false` or by explicitly
      // declaring some other habitat)
      var isLifecycleMgmtExplicitlyDisabled = (
        scriptDef.sails === false || (
          !_.isUndefined(scriptDef.habitat) && scriptDef.habitat !== 'sails'
        )
      );
      if (!isLifecycleMgmtExplicitlyDisabled) {
        scriptDef.habitat = 'sails';
        scriptDef.sails = Sails();
      }

      // Now actually run the script.
      machineAsScript(scriptDef).exec();

    } catch (e) {
      console.error(e);
      return process.exit(1);
    }
  }
  // Otherwise, this is an NPM script of some kind, from the package.json file.
  else {

    // So execute the command like you would on the terminal.

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    // FUTURE: Consider pulling this boilerplate setup code into spawnChildProcess() machine
    // as a way of leveraging a subshell to remove the need to pass in CLI args directly.
    // Maybe as an option at least.
    //
    // > Also, we should also consider adding a notifier function to optionally provide
    // > special instructions of what to do when the current (parent) process receives a SIGINT.
    // > (Otherwise, by default, the SIGINT behavior implemented below could be used instead.)
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    //
    // -AND/OR-
    //
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    // FUTURE: Consider exposing an optional `onData` input to the more basic `executeCommand()`
    // machine.  That way, you can just pass in a notifier function that handles the child's
    // writes to its stdout and stderr streams without having to dig into all of these
    // annoying complexities.  Also, it'd then be possible to add another input: a flag that
    // allows you to choose whether or not to store output and pass it to the callback
    // (e.g. `bufferOutput`).
    //
    // > Finally, we should also consider adding the same SIGINT notifier function mentioned above.
    //
    // Here's an example of how we might put it all together:
    // ```
    // Process.executeCommand({
    //   command: commandToRun,
    //   bufferOutput: false,
    //   killOnParentSigint: false,
    //   onData: function (data, stdStreamName){
    //     process[stdStreamName].write(data);
    //   }
    // }).exec(function (err) {
    //   if (err) {
    //     console.error('Error occured running `'+ commandToRun+ '`');
    //     console.error('Please resolve any issues and try `sails run '+scriptName+'` again.');
    //     console.error('Details:');
    //     console.error(err);
    //     return process.exit(1);
    //   }//-•
    //
    //   return process.exit(0);
    // });//< Process.executeCommand().exec() > _∏_
    // ```
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    // Determine an appropriate name for our shell.
    // > This is mainly just so we don't have to try and do any fancy parsing of the command,
    // > allowing for more platform-specific customization.  (Mirroring the NPM CLI here)
    var shProcName;
    var shFlag;
    if (process.platform === 'win32') {
      shProcName = process.env.comspec || 'cmd';
      shFlag = '/d /s /c';
    }
    else {
      shProcName = 'sh';
      shFlag = '-c';
    }

    var childProcess = Process.spawnChildProcess({
      command: shProcName,
      cliArgs: [ shFlag, commandToRun ]
    }).execSync();

    // Pipe output from the child process to the current (parent) process.
    childProcess.stdout.pipe(process.stdout);
    childProcess.stderr.pipe(process.stderr);

    // Set up CTRL+C listener on the parent process that will force-kill this child process.
    // (Note that we define the event listener as a named function so we can unbind it below.)
    var onSigTerm = function (){
      Process.killChildProcess({ childProcess: childProcess, force: true }).exec(function (_forceKillErr){
        if (_forceKillErr) {
          console.error('There was a problem terminating this script:\n'+_forceKillErr.stack+'\nHere are some details which might be helpful:\n' + _forceKillErr.stack);
        }
      });
    };
    process.once('SIGTERM', onSigTerm);

    var spinlocked;
    (function (proceed){

      childProcess.on('error', function (err) { return proceed(err); });
      childProcess.stderr.on('error', function (err) { return proceed(err); });
      childProcess.stdout.on('error', function (err) { return proceed(err); });
      childProcess.on('close', function (code, signal) {
        // log.silly('lifecycle', logid(pkg, stage), 'Returned: code:', code, ' signal:', signal)
        // If a signal was received, terminate the current parent process (i.e. `sails run`).
        if (signal) {
          // Note that, in this case, `proceed()` is never called.
          // (But it doesn't actually matter, because we'll have killed the process.)
          return process.kill(process.pid, signal);
        }

        // Otherwise if we got a non-zero exit code, then consider this an error.
        if (code !== 0) {
          return proceed(new Error('Exit status '+code));
        }

        // Otherwise, consider it a success.
        return proceed();
      });

    })(function(err){
      if (err) {

        if (spinlocked) {
          console.error(err);
          return;
        }
        spinlocked = true;

        console.error('- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ');
        console.error('Error occured running `'+ commandToRun+ '`');
        console.error('Please resolve any issues and try `sails run '+scriptName+'` again.');
        console.error('Details:');
        console.error(err);

        process.removeListener('SIGTERM', onSigTerm);
        return process.exit(1);
      }//-•

      return process.exit(0);

    });//</ self-calling function > _∏_

  }//</ else >

};

<commit_msg>Avoid unnecessary requiring to optimize the load time a bit<commit_after>/**
 * Module dependencies
 */

var path = require('path');
var fs = require('fs');
var _ = require('@sailshq/lodash');
var chalk = require('chalk');
var COMMON_JS_FILE_EXTENSIONS = require('common-js-file-extensions');
var flaverr = require('flaverr');
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Note that `machine-as-script`, `machinepack-process`, and `../lib/app` are
// conditionally required below, only in the cases where they are actually used.
// (That way you don't have to wait for them to load if you're not using them.)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

/**
 * Module constants
 */

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Supported file extensions for imperative code files such as hooks:
//  • 'js' (.js)
//  • 'ts' (.ts)
//  • 'es6' (.es6)
//  • ...etc.
//
// > For full list, see:
// > https://github.com/luislobo/common-js-file-extensions/blob/210fd15d89690c7aaa35dba35478cb91c693dfa8/README.md#code-file-extensions
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
var BASIC_SUPPORTED_FILE_EXTENSIONS = COMMON_JS_FILE_EXTENSIONS.code;

/**
 * `sails run`
 *
 * Run a script for the Sails app in the current working directory.
 *
 * This matches either a JavaScript file in the `scripts/` directory, or one of the command-line scripts
 * declared within the `scripts: {}` dictionary in the package.json file.
 *
 * @see https://sailsjs.com/documentation/reference/command-line-interface/sails-run
 */

module.exports = function(scriptName) {

  // If there is only one argument, it means there is actually no scriptName at all.
  // (A detail of how commander works.)
  if (arguments.length === 1) {
    scriptName = undefined;
  }

  // Sanitize the script name, for comfort.
  if (!scriptName) {
    console.error('Which one?  (To run a script, provide its name.)');
    console.error('For example:');
    console.error('    sails run add-customer');
    console.error();
    console.error('^ runs `scripts/add-customer.js`.');
    console.error();
    console.error('(For more help, visit '+chalk.underline('http://sailsjs.com/support')+'.)');
    return process.exit(1);
  }

  scriptName = _.trim(scriptName);
  scriptName = scriptName.replace(/^scripts\//, '');
  if (scriptName.match(/\//)) {
    console.error('Cannot run `'+scriptName+'`.  Script name should never contain any slashes.');
    return process.exit(1);
  }//-•

  // Examine the script name and determine if it has a file extension included.
  // If so, we'll rip it out of the script name, but keep a reference to it.
  // Otherwise, we'll always assume that we're looking for a normal `.js` file.
  var X_BASIC_SUPPORTED_FILE_EXTENSION = new RegExp('^([^.]+)\\.(' + BASIC_SUPPORTED_FILE_EXTENSIONS.join('|') + ')$');
  var matchedFileExtension = scriptName.match(X_BASIC_SUPPORTED_FILE_EXTENSION);
  var fileExtension;
  if (matchedFileExtension) {
    fileExtension = matchedFileExtension[2];
    scriptName = scriptName.replace(X_BASIC_SUPPORTED_FILE_EXTENSION, '$1');
  }
  else {
    fileExtension = 'js';
  }

  // console.log(scriptName);
  // console.log(fileExtension);
  // return;

  // First, we need to determine the appropriate script to run.
  // (either a terminal command or a specially-formatted Node.js/Sails.js module)

  // We begin by figuring out whether this is a command-line script or a script (MaS) definition.
  var commandToRun;

  // Check the package.json file.
  try {
    var pathToLocalPackageJson = path.resolve(process.cwd(), 'package.json');
    var packageJson;
    try {
      packageJson = require(pathToLocalPackageJson);
    } catch (e) {
      switch (e.code) {
        case 'MODULE_NOT_FOUND': throw flaverr('E_NO_PACKAGE_JSON', new Error('No package.json file.  Are you sure you\'re in the root directory of a Node.js/Sails.js app?'));
        default: throw e;
      }
    }

    if (!_.isUndefined(packageJson.scripts) && (!_.isObject(packageJson.scripts) || _.isArray(packageJson.scripts))) {
      throw flaverr('E_MALFORMED_PACKAGE_JSON', new Error('This package.json file has an invalid `scripts` property -- should be a dictionary (plain JS object).'));
    }

    commandToRun = packageJson.scripts[scriptName];

  } catch (e) {
    switch (e.code) {
      case 'E_NO_PACKAGE_JSON':
      case 'E_MALFORMED_PACKAGE_JSON':
        console.error('--');
        console.error(chalk.red(e.message));
        return process.exit(1);

      default:
        console.error('--');
        console.error(chalk.bold('Oops, something unexpected happened:'));
        console.error(chalk.red(e.stack));
        console.error('--');
        console.error('Please read the error message above and troubleshoot accordingly.');
        console.error('(You can report suspected bugs at '+chalk.underline('http://sailsjs.com/bugs')+'.)');
        return process.exit(1);
    }
  }

  // Now check the `scripts/` directory to see if the file exists.
  var relativePathToScript = 'scripts/'+scriptName+'.'+fileExtension;
  var doesScriptFileExist = fs.existsSync(path.resolve(relativePathToScript));

  // Ensure that this script is not defined in BOTH places.
  if (commandToRun && doesScriptFileExist) {
    console.error('Cannot run `'+scriptName+'` because it is too ambiguous.');
    console.error('A script should only be defined once, but that script is defined in both the package.json file');
    console.error('AND as a file in the `scripts/` directory.');
    return process.exit(1);
  }

  // Ensure that this script exists one place or the other.
  if (!commandToRun && !doesScriptFileExist) {
    console.error('Unknown script: `'+scriptName+'`');
    console.error('No matching script is defined at `'+relativePathToScript+'`.');
    console.error('(And there is no matching NPM script in the package.json file.)');
    return process.exit(1);
  }

  // If this is a Node.js/Sails.js script (machine def), then require the script file
  // to get the module definition, then run it using MaS.
  if (!commandToRun) {
    try {
      var pathToScriptDef = path.resolve(process.cwd(), 'scripts/'+scriptName);
      var scriptDef;
      try {
        scriptDef = require(pathToScriptDef);
      } catch (e) {
        switch (e.code) {
          case 'MODULE_NOT_FOUND': throw flaverr('E_FAILED_TO_REQUIRE_SCRIPT_DEF', new Error('Encountered an error while loading the script definition.  Are you sure this is a well-formed Node.js/Sails.js script definition?  Error details:\n'+e.stack));
          default: throw e;
        }
      }

      // Make sure the script is at least basically valid.
      // (MaS will check it more later -- this is just preliminary -- and also to make sure that it's not `{}`,
      // the special indicator that the script definition didn't export _ANYTHING_ at all.)
      if (!_.isObject(scriptDef) || _.isArray(scriptDef) || _.isEqual(scriptDef, {})) {
        console.error('');
        console.error('');
        console.error('Invalid script: `'+scriptName+'`');
        console.error('');
        console.error('A well-formed Node.js/Sails.js script should export a script definition.');
        console.error('In other words, it should be defined more or less like this:');
        console.error('');
        console.error('    ```````````````````````````````````````````````````````````');
        console.error('    module.exports = {');
        console.error('      description: \'Do a thing given some stuff.\',');
        console.error('      inputs: {');
        console.error('        someStuff: { type: \'string\', required: true }');
        console.error('      },');
        console.error('      fn: function (inputs, exits) {');
        console.error('        // ...');
        console.error('        sails.log(\'Hello world!\');');
        console.error('        return exits.success();');
        console.error('      }');
        console.error('    };');
        console.error('    ```````````````````````````````````````````````````````````');
        console.error('');
        return process.exit(1);
      }

      // Modify the script definition to add `sails: require('sails')` and `habitat: 'sails'`
      // (unless it explicitly disables this behavior with `sails: false` or by explicitly
      // declaring some other habitat)
      var isLifecycleMgmtExplicitlyDisabled = (
        scriptDef.sails === false || (
          !_.isUndefined(scriptDef.habitat) && scriptDef.habitat !== 'sails'
        )
      );
      if (!isLifecycleMgmtExplicitlyDisabled) {
        // (Only require the rest of the Sails framework if it's needed.)
        var Sails = require('../lib/app');
        scriptDef.habitat = 'sails';
        scriptDef.sails = Sails();
      }

      // (Only require machine-as-script if it's needed.)
      var machineAsScript = require('machine-as-script');

      // Now actually run the script.
      machineAsScript(scriptDef).exec();

    } catch (e) {
      console.error(e);
      return process.exit(1);
    }
  }
  // Otherwise, this is an NPM script of some kind, from the package.json file.
  else {

    // So execute the command like you would on the terminal.

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    // FUTURE: Consider pulling this boilerplate setup code into spawnChildProcess() machine
    // as a way of leveraging a subshell to remove the need to pass in CLI args directly.
    // Maybe as an option at least.
    //
    // > Also, we should also consider adding a notifier function to optionally provide
    // > special instructions of what to do when the current (parent) process receives a SIGINT.
    // > (Otherwise, by default, the SIGINT behavior implemented below could be used instead.)
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    //
    // -AND/OR-
    //
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    // FUTURE: Consider exposing an optional `onData` input to the more basic `executeCommand()`
    // machine.  That way, you can just pass in a notifier function that handles the child's
    // writes to its stdout and stderr streams without having to dig into all of these
    // annoying complexities.  Also, it'd then be possible to add another input: a flag that
    // allows you to choose whether or not to store output and pass it to the callback
    // (e.g. `bufferOutput`).
    //
    // > Finally, we should also consider adding the same SIGINT notifier function mentioned above.
    //
    // Here's an example of how we might put it all together:
    // ```
    // Process.executeCommand({
    //   command: commandToRun,
    //   bufferOutput: false,
    //   killOnParentSigint: false,
    //   onData: function (data, stdStreamName){
    //     process[stdStreamName].write(data);
    //   }
    // }).exec(function (err) {
    //   if (err) {
    //     console.error('Error occured running `'+ commandToRun+ '`');
    //     console.error('Please resolve any issues and try `sails run '+scriptName+'` again.');
    //     console.error('Details:');
    //     console.error(err);
    //     return process.exit(1);
    //   }//-•
    //
    //   return process.exit(0);
    // });//< Process.executeCommand().exec() > _∏_
    // ```
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    // (Only require machinepack-process if it's needed.)
    var Process = require('machinepack-process');

    // Determine an appropriate name for our shell.
    // > This is mainly just so we don't have to try and do any fancy parsing of the command,
    // > allowing for more platform-specific customization.  (Mirroring the NPM CLI here)
    var shProcName;
    var shFlag;
    if (process.platform === 'win32') {
      shProcName = process.env.comspec || 'cmd';
      shFlag = '/d /s /c';
    }
    else {
      shProcName = 'sh';
      shFlag = '-c';
    }

    var childProcess = Process.spawnChildProcess({
      command: shProcName,
      cliArgs: [ shFlag, commandToRun ]
    }).execSync();

    // Pipe output from the child process to the current (parent) process.
    childProcess.stdout.pipe(process.stdout);
    childProcess.stderr.pipe(process.stderr);

    // Set up CTRL+C listener on the parent process that will force-kill this child process.
    // (Note that we define the event listener as a named function so we can unbind it below.)
    var onSigTerm = function (){
      Process.killChildProcess({ childProcess: childProcess, force: true }).exec(function (_forceKillErr){
        if (_forceKillErr) {
          console.error('There was a problem terminating this script:\n'+_forceKillErr.stack+'\nHere are some details which might be helpful:\n' + _forceKillErr.stack);
        }
      });
    };
    process.once('SIGTERM', onSigTerm);

    var spinlocked;
    (function (proceed){

      childProcess.on('error', function (err) { return proceed(err); });
      childProcess.stderr.on('error', function (err) { return proceed(err); });
      childProcess.stdout.on('error', function (err) { return proceed(err); });
      childProcess.on('close', function (code, signal) {
        // log.silly('lifecycle', logid(pkg, stage), 'Returned: code:', code, ' signal:', signal)
        // If a signal was received, terminate the current parent process (i.e. `sails run`).
        if (signal) {
          // Note that, in this case, `proceed()` is never called.
          // (But it doesn't actually matter, because we'll have killed the process.)
          return process.kill(process.pid, signal);
        }

        // Otherwise if we got a non-zero exit code, then consider this an error.
        if (code !== 0) {
          return proceed(new Error('Exit status '+code));
        }

        // Otherwise, consider it a success.
        return proceed();
      });

    })(function(err){
      if (err) {

        if (spinlocked) {
          console.error(err);
          return;
        }
        spinlocked = true;

        console.error('- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ');
        console.error('Error occured running `'+ commandToRun+ '`');
        console.error('Please resolve any issues and try `sails run '+scriptName+'` again.');
        console.error('Details:');
        console.error(err);

        process.removeListener('SIGTERM', onSigTerm);
        return process.exit(1);
      }//-•

      return process.exit(0);

    });//</ self-calling function > _∏_

  }//</ else >

};

<|endoftext|>


<commit_before>#!/usr/bin/env node
'use strict';

var program = require('commander'),
    meta = require('../package.json');

var exitCode = 0;
    // lint = require('../index');

program
  .version(meta.version)
  .parse(process.argv);

// if (program.version) {
//   console.log('v' + program.version);
// }

// console.log(userArgs);
<commit_msg>Add working CLI code<commit_after>#!/usr/bin/env node
'use strict';

var program = require('commander'),
    meta = require('../package.json'),
    lint = require('../index');

var detects;

program
  .version(meta.version)
  .usage('[options] \'<file or glob>\'')
  .option('-q, --no-exit', 'do not exit on errors')
  .parse(process.argv);

detects = lint.lintFiles(program.args[0]);
detects = lint.format(detects);

lint.outputResults(detects);

if (program.exit) {
  lint.failOnError(detects);
}
<|endoftext|>


<commit_before>(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');

ga('create', 'UA-74906812-2', 'auto');
ga('require', 'linkid');
ga('send', 'pageview');

/**
* From https://support.google.com/analytics/answer/1136920?hl=en
* Function that tracks a click on an outbound link in Analytics.
* This function takes a valid URL string as an argument, and uses that URL string
* as the event label. Setting the transport method to 'beacon' lets the hit be sent
* using 'navigator.sendBeacon' in browsers that support it.
*/
var trackOutboundLink = function(url) {

  // GA
  ga('send', 'event', 'outbound', 'click', url, {
    'transport': 'beacon',
    'hitCallback': function(){ document.location = url; }
  });

  // Keen.io
  window.keen.addEvent('outbound', {
    item: url,
    page: window.location.pathname,
    host: window.location.hostname,
    keen: {
      timestamp: new Date().toISOString()
    }
  }, function(err, res){});

}
<commit_msg>Don't redirect after tracking external links<commit_after>(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');

ga('create', 'UA-74906812-2', 'auto');
ga('require', 'linkid');
ga('send', 'pageview');

/**
* From https://support.google.com/analytics/answer/1136920?hl=en
* Function that tracks a click on an outbound link in Analytics.
* This function takes a valid URL string as an argument, and uses that URL string
* as the event label. Setting the transport method to 'beacon' lets the hit be sent
* using 'navigator.sendBeacon' in browsers that support it.
*/
var trackOutboundLink = function(url) {

  // GA
  ga('send', 'event', 'outbound', 'click', url, {
    'transport': 'beacon',
  });

  // Keen.io
  window.keen.addEvent('outbound', {
    item: url,
    page: window.location.pathname,
    host: window.location.hostname,
    keen: {
      timestamp: new Date().toISOString()
    }
  }, function(err, res){});

}
<|endoftext|>


<commit_before>#!/usr/bin/env node --harmony

var program = require('commander');
var fs = require('fs');
var chalk = require('chalk');
var JSONStream = require('JSONStream');
var crypto = require('crypto');

exports.program = program;
exports.performDataStripping = performDataStripping;
exports.printOptions = printOptions;
exports.splitDeviceId = splitDeviceId;
exports.hashIDsForData = hashIDsForData;

program
	.version('0.0.1')
	.option('-i, --input <input>', 'path/to/input.json')
	.option('-o, --output <output>', 'path/to/output.json')
	.option('--stripModels <stripModels>',
		'Strip model name for these models. e.g. Anonymous Pump', list, [])
	.option('--stripSNs <stripSNs>',
		'Strip serial number for these models.', list, [])
	.option('--leaveModels <leaveModels>',
		'Leave model for these models. Takes precedence over strip.', list, [])
	.option('--leaveSNs <leaveSNs>',
		'Leave serial number for these models. Takes precedence over strip.', list, [])
	.option('--stripAll',
		'Strip all of the data, except for what is explicitly left.')
	.option('--removeTypes <removeTypes>',
		'Remove these data types.', list, [])
	.option('--leaveTypes <leaveTypes>',
		'Leave these data types. Takes precedence over removal.', list, [])
	.option('--removeAll',
		'Remove all data types, except for what is explicitly left.')
	.option('--hashIDs',
		'Pass IDs (such as _groupId and uploadId) through a one-way hash.')
	.option('--removeSource',
		'Remove the source of the data, e.g. carelink.')
	.option('--removeTransmitter',
		'Remove the transmitter id, e.g. the transmitter id for a Dexcom.')
	.option('-v, --verbose',
		'Verbose output.')
	.parse(process.argv);

performDataStripping(function() {});

function performDataStripping(callback) {
	checkOptions();
	if (program.verbose) {
		printOptions();
	}

	var ifs = makeInFileStream();

	var jsonStream = JSONStream.parse('*');

	var ofs = makeOutstream();

	var first = true;
	writeToOutstream(ofs, '[');

	// Perform the parsing
	ifs
		.pipe(jsonStream)
		.on('data', function (chunk) {

			if ((program.removeAll
				|| program.removeTypes
					.indexOf(chunk.type) >= 0)
				&& program.leaveTypes
					.indexOf(chunk.type) < 0) {
				// Do NOT add this event to output
				return;
			}

			if (first)
				first = false;
			else
				writeToOutstream(ofs, ',');

			var cleanData = chunk;

			stripModelAndSNForData(cleanData);

			hashIDsForData(cleanData);

			removeSourceForData(cleanData);

			removeTransmitterIdForData(cleanData);

			writeToOutstream(ofs, JSON.stringify(cleanData));
		})
		.on('end', function() {
			writeToOutstream(ofs, ']');
			if (program.verbose) {
				console.log(chalk.yellow.bold('Done writing to output.'));
			}
			callback();
		});
}

function list(val) {
	return val
		.split(',');
}

function splitDeviceId(deviceId) {
	var retlist=deviceId.split('-');
	if (retlist.length === 1) {
		// Probably split by '_'
		retlist=deviceId.split('_');
	} else if (retlist.length > 2) {
		// Split into more than two pieces
		var model=retlist.slice(0,-1).join('-');
		var serial=retlist[retlist.length-1];
		retlist=[];
		retlist.push(model);
		retlist.push(serial);
	}
	// Index 0 has model, 1 has serial
	return retlist;
}

function stripModelAndSNForData(data) {

	var deviceId = splitDeviceId(data.deviceId);
	var deviceComp = deviceId[0];

	if ((program.stripAll
		|| program.stripModels
			.indexOf(deviceComp) >= 0)
		&& program.leaveModels
			.indexOf(deviceComp) < 0) {
		if (data.type !== 'upload') {
			deviceId[0]=data.type + ' device';
		} else {
			// This probably isn't the best way to
			// go about scrubbing an upload but I
			// can't discern a better way to go
			// about it.
			delete data.deviceManufacturers;
			if (data.payload)
				delete data.payload.devices;
			if (data.deviceModel)
				data.deviceModel = data.deviceTags[0]
										+ ' model';
			if (data.deviceSerialNumber)
				data.deviceSerialNumber = 'Serial Number';
		}
	}

	if ((program.stripAll
		|| program.stripSNs
			.indexOf(deviceComp) >= 0)
		&& program.leaveSNs
			.indexOf(deviceComp) < 0) {
		deviceId[1]='Serial Number';
	}

	data.deviceId = deviceId.join('-');
}

function hashIDsForData(data) {
	if (program.hashIDs) {
		if (data._groupId)
			data.hash_groupId =
				crypto.createHash('sha256')
					.update(data._groupId.toString())
					.digest('hex');
		delete data._groupId;
		if (data.uploadId)
			data.hash_uploadId =
				crypto.createHash('sha256')
					.update(data.uploadId.toString())
					.digest('hex');
		delete data.uploadId;
		if (data.byUser)
			data.hash_byUser =
				crypto.createHash('sha256')
					.update(data.byUser.toString())
					.digest('hex');
		delete data.hash_byUser;
	}
}

function removeSourceForData(data) {
	if (program.removeSource) {
		delete data.source;
	}
}

function removeTransmitterIdForData(data) {
	if (program.removeTransmitter) {
		delete data.transmitterId;
	}
}

function checkOptions() {
	if (!program.stripAll) {program.stripAll = false;}
	if (!program.removeAll) {program.removeAll = false;}
	if (!program.hashIDs) {program.hashIDs = false;}
	if (!program.removeSource) {program.removeSource = false;}
	if (!program.verbose) {program.verbose = false;}
}

function printOptions() {
	console.log(chalk.blue.bold('input: ') + program.input);
	console.log(chalk.blue.bold('output: ') + program.output);
	console.log(chalk.blue.bold('stripModels: ') + program.stripModels);
	console.log(chalk.blue.bold('stripSNs: ') + program.stripSNs);
	console.log(chalk.blue.bold('leaveModels: ') + program.leaveModels);
	console.log(chalk.blue.bold('leaveSNs: ') + program.leaveSNs);
	console.log(chalk.blue.bold('stripAll: ') + program.stripAll);
	console.log(chalk.blue.bold('removeTypes: ') + program.removeTypes);
	console.log(chalk.blue.bold('leaveTypes: ') + program.leaveTypes);
	console.log(chalk.blue.bold('removeAll: ') + program.removeAll);
	console.log(chalk.blue.bold('hashIDs: ') + program.hashIDs);
	console.log(chalk.blue.bold('removeSource: ') + program.removeSource);
	console.log(chalk.blue.bold('verbose: ') + program.verbose);
}

function makeInFileStream() {
	var ifs;
	if (program.input) {
		ifs = fs.createReadStream(program.input, {encoding: 'utf8'});
	} else {
		ifs = process.stdin;
	}
	return ifs;
}

function makeOutstream() {
	var ofs;
	if (program.output) {
		ofs = fs.createWriteStream(program.output);
	} else {
		ofs = process.stdout;
	}
	return ofs
}

function writeToOutstream(ofs, info) {
	if (program.output) {
		ofs.write(info);
	} else {
		console.log(info);
	}
}<commit_msg>Updates to stripdata to properly anonymize<commit_after>#!/usr/bin/env node --harmony

var program = require('commander');
var fs = require('fs');
var chalk = require('chalk');
var JSONStream = require('JSONStream');
var crypto = require('crypto');

exports.program = program;
exports.performDataStripping = performDataStripping;
exports.printOptions = printOptions;
exports.splitDeviceId = splitDeviceId;
exports.hashIDsForData = hashIDsForData;

program
	.version('0.0.1')
	.option('-i, --input <input>', 'path/to/input.json')
	.option('-o, --output <output>', 'path/to/output.json')
	.option('--stripModels <stripModels>',
		'Strip model name for these models. e.g. Anonymous Pump', list, [])
	.option('--stripSNs <stripSNs>',
		'Strip serial number for these models.', list, [])
	.option('--leaveModels <leaveModels>',
		'Leave model for these models. Takes precedence over strip.', list, [])
	.option('--leaveSNs <leaveSNs>',
		'Leave serial number for these models. Takes precedence over strip.', list, [])
	.option('--stripAll',
		'Strip all of the data, except for what is explicitly left.')
	.option('--removeTypes <removeTypes>',
		'Remove these data types.', list, [])
	.option('--leaveTypes <leaveTypes>',
		'Leave these data types. Takes precedence over removal.', list, [])
	.option('--removeAll',
		'Remove all data types, except for what is explicitly left.')
	.option('--hashIDs',
		'Pass IDs (such as _groupId and uploadId) through a one-way hash.')
	.option('--removeSource',
		'Remove the source of the data, e.g. carelink.')
	.option('--removeTransmitter',
		'Remove the transmitter id, e.g. the transmitter id for a Dexcom.')
	.option('-v, --verbose',
		'Verbose output.')
	.parse(process.argv);

performDataStripping(function() {});

function performDataStripping(callback) {
	checkOptions();
	if (program.verbose) {
		printOptions();
	}

	var ifs = makeInFileStream();

	var jsonStream = JSONStream.parse('*');

	var ofs = makeOutstream();

	var first = true;
	writeToOutstream(ofs, '[');

	// Perform the parsing
	ifs
		.pipe(jsonStream)
		.on('data', function (chunk) {

			if ((program.removeAll
				|| program.removeTypes
					.indexOf(chunk.type) >= 0)
				&& program.leaveTypes
					.indexOf(chunk.type) < 0) {
				// Do NOT add this event to output
				return;
			}

			if (first)
				first = false;
			else
				writeToOutstream(ofs, ',');

			var cleanData = chunk;

			removeIDsAndPayload(cleanData);

			stripModelAndSNForData(cleanData);

			hashIDsForData(cleanData);

			removeSourceForData(cleanData);

			removeTransmitterIdForData(cleanData);

			writeToOutstream(ofs, JSON.stringify(cleanData));
		})
		.on('end', function() {
			writeToOutstream(ofs, ']');
			if (program.verbose) {
				console.log(chalk.yellow.bold('Done writing to output.'));
			}
			callback();
		});
}

function list(val) {
	return val
		.split(',');
}

function splitDeviceId(deviceId) {
	var retlist=deviceId.split('-');
	if (retlist.length === 1) {
		// Probably split by '_'
		retlist=deviceId.split('_');
	} else if (retlist.length > 2) {
		// Split into more than two pieces
		var model=retlist.slice(0,-1).join('-');
		var serial=retlist[retlist.length-1];
		retlist=[];
		retlist.push(model);
		retlist.push(serial);
	}
	// Index 0 has model, 1 has serial
	return retlist;
}

function removeIDsAndPayload(data) {
	if (program.stripAll) {
		if (data.payload)
			delete data.payload;
		if (data.id)
			delete data.id;
		if (data.guid)
			delete data.guid;
		if (data.bolus)
			delete data.bolus;
		if (data.suppressed)
			delete data.suppressed;
	}
}

function stripModelAndSNForData(data) {

	var deviceId = splitDeviceId(data.deviceId);
	var deviceComp = deviceId[0];

	if ((program.stripAll
		|| program.stripModels
			.indexOf(deviceComp) >= 0)
		&& program.leaveModels
			.indexOf(deviceComp) < 0) {
		if (data.type !== 'upload') {
			deviceId[0]=data.type + ' device';
		} else {
			// This probably isn't the best way to
			// go about scrubbing an upload but I
			// can't discern a better way to go
			// about it.
			delete data.deviceManufacturers;
			if (data.payload)
				delete data.payload.devices;
			if (data.deviceModel)
				data.deviceModel = data.deviceTags[0]
										+ ' model';
			if (data.deviceSerialNumber)
				data.deviceSerialNumber = 'Serial Number';
		}
	}

	if ((program.stripAll
		|| program.stripSNs
			.indexOf(deviceComp) >= 0)
		&& program.leaveSNs
			.indexOf(deviceComp) < 0) {
		deviceId[1]='Serial Number';
	}

	data.deviceId = deviceId.join('-');
}

function hashIDsForData(data) {
	if (program.hashIDs) {
		if (data._groupId)
			data.hash_groupId =
				crypto.createHash('sha256')
					.update(data._groupId.toString())
					.digest('hex');
		delete data._groupId;
		if (data.uploadId)
			data.hash_uploadId =
				crypto.createHash('sha256')
					.update(data.uploadId.toString())
					.digest('hex');
		delete data.uploadId;
		if (data.byUser)
			data.hash_byUser =
				crypto.createHash('sha256')
					.update(data.byUser.toString())
					.digest('hex');
		delete data.byUser;
	}
}

function removeSourceForData(data) {
	if (program.removeSource) {
		delete data.source;
	}
}

function removeTransmitterIdForData(data) {
	if (program.removeTransmitter) {
		delete data.transmitterId;
	}
}

function checkOptions() {
	if (!program.stripAll) {program.stripAll = false;}
	if (!program.removeAll) {program.removeAll = false;}
	if (!program.hashIDs) {program.hashIDs = false;}
	if (!program.removeSource) {program.removeSource = false;}
	if (!program.verbose) {program.verbose = false;}
}

function printOptions() {
	console.log(chalk.blue.bold('input: ') + program.input);
	console.log(chalk.blue.bold('output: ') + program.output);
	console.log(chalk.blue.bold('stripModels: ') + program.stripModels);
	console.log(chalk.blue.bold('stripSNs: ') + program.stripSNs);
	console.log(chalk.blue.bold('leaveModels: ') + program.leaveModels);
	console.log(chalk.blue.bold('leaveSNs: ') + program.leaveSNs);
	console.log(chalk.blue.bold('stripAll: ') + program.stripAll);
	console.log(chalk.blue.bold('removeTypes: ') + program.removeTypes);
	console.log(chalk.blue.bold('leaveTypes: ') + program.leaveTypes);
	console.log(chalk.blue.bold('removeAll: ') + program.removeAll);
	console.log(chalk.blue.bold('hashIDs: ') + program.hashIDs);
	console.log(chalk.blue.bold('removeSource: ') + program.removeSource);
	console.log(chalk.blue.bold('verbose: ') + program.verbose);
}

function makeInFileStream() {
	var ifs;
	if (program.input) {
		ifs = fs.createReadStream(program.input, {encoding: 'utf8'});
	} else {
		ifs = process.stdin;
	}
	return ifs;
}

function makeOutstream() {
	var ofs;
	if (program.output) {
		ofs = fs.createWriteStream(program.output);
	} else {
		ofs = process.stdout;
	}
	return ofs
}

function writeToOutstream(ofs, info) {
	if (program.output) {
		ofs.write(info);
	} else {
		console.log(info);
	}
}
<|endoftext|>


<commit_before>const Discord = require("discord.js");
var mysql = require('mysql');
var fs = require("fs");
var config = JSON.parse(fs.readFileSync("config.json", "utf8"));
var sqlConnection = mysql.createConnection(config.mysql);
var discordClient = null;
sqlConnection.connect();
var kue = require('kue'),
    queue = kue.createQueue({
        prefix: 'q',
        redis: {
            port: 6379,
            host: '127.0.0.1'
        }
    });
var triggerWords = {

};
var clientState = {
    "online": false,
    "loginName": null,
    "onlineSince": null
};
queue.on( 'error', function( err ) {
    console.log( 'Oops... ', err );
});
function biotmp(token) {
    discordClient = new Discord.Client();
    discordClient.on('ready', function () {
        console.log("Logged in as " + discordClient.user.tag);
        console.log("https://discordapp.com/oauth2/authorize?client_id=" + config.clientID + "&scope=bot&permissions=0")
        clientState.online = true;
        clientState.loginName = discordClient.user.tag;
        clientState.online = Date.now();
    });

    discordClient.on('message', function (msg) {
        if (triggerWords[msg.channel.guild.id] === undefined && msg.content.indexOf("biotmp ") === 0) {
            // triggered - default
            // add triggerword to msg object for further processing
            console.log("Triggered");
            msg.triggerWord = "biotmp ";
            //and queue processing
            var job = queue.create('msg_process', {
                "content": msg.content
            }).priority("low").save( function(err){
                if( !err ) console.log( job.id );
            });
        } else if (triggerWords[msg.channel.guild.id] !== undefined) {
            if (msg.content.indexOf(triggerWords[msg.channel.guild.id] + " ") === 0) {
                // triggered - custom triggerword
                // add triggerword to msg object for further processing
                msg.triggerWord = triggerWords[msg.channel.guild.id] + " ";
                //and queue processing
                var job = queue.create('msg_process', msg).priority("low").save( function(err){
                    if( !err ) console.log( job.id );
                });

            }
        }

    });

    discordClient.login(token);
}
function updateTriggerWords() {
    sqlConnection.query("SELECT id, server_id, triggerword FROM triggerword", function (err, results) {
       if (err) throw err;
       triggerWords = {};
       results.forEach(function (currentEntry) {
           triggerWords[currentEntry.server_id] = currentEntry.triggerword;
       });
    });
}
setInterval(updateTriggerWords, 1000);
biotmp(config.token);<commit_msg>Finished Message Queueing<commit_after>const Discord = require("discord.js");
var mysql = require('mysql');
var fs = require("fs");
var config = JSON.parse(fs.readFileSync("config.json", "utf8"));
var sqlConnection = mysql.createConnection(config.mysql);
var discordClient = null;
sqlConnection.connect();
var kue = require('kue'),
    queue = kue.createQueue({
        prefix: 'q',
        redis: {
            port: 6379,
            host: '127.0.0.1'
        }
    });
var triggerWords = {

};
var clientState = {
    "online": false,
    "loginName": null,
    "onlineSince": null
};
queue.on( 'error', function( err ) {
    console.log( 'Oops... ', err );
});
function biotmp(token) {
    function queueMSG(msg) {
        var job = queue.create('msg_process', {
            "title": "Discord Message Processing",
            "content": JSON.stringify({
                "message": msg.content,
                "channel": {
                    "type": msg.channel.type,
                    "id": msg.channel.id,
                    "name": msg.channel.name
                },
                "server": {
                    "id": msg.channel.guild.id,
                    "name": msg.channel.guild.name
                },
                "author": msg.author,
                "tts": msg.tts,
                "system": msg.system,
                "nonce": msg.nonce,
                "mentions": JSON.stringify(msg.mentions)
            })

        }).priority("low").save( function(err){
            if( !err ) console.log( job.id );
        });
    }
    discordClient = new Discord.Client();
    discordClient.on('ready', function () {
        console.log("Logged in as " + discordClient.user.tag);
        console.log("https://discordapp.com/oauth2/authorize?client_id=" + config.clientID + "&scope=bot&permissions=0")
        clientState.online = true;
        clientState.loginName = discordClient.user.tag;
        clientState.online = Date.now();
    });

    discordClient.on('message', function (msg) {
        if (triggerWords[msg.channel.guild.id] === undefined && msg.content.indexOf("biotmp ") === 0) {
            // triggered - default
            // add triggerword to msg object for further processing
            console.log("Triggered");
            msg.triggerWord = "biotmp ";
            //and queue processing
            queueMSG(msg);
        } else if (triggerWords[msg.channel.guild.id] !== undefined) {
            if (msg.content.indexOf(triggerWords[msg.channel.guild.id] + " ") === 0) {
                // triggered - custom triggerword
                // add triggerword to msg object for further processing
                msg.triggerWord = triggerWords[msg.channel.guild.id] + " ";
                //and queue processing
                queueMSG(msg);

            }
        }

    });

    discordClient.login(token);
}
function updateTriggerWords() {
    sqlConnection.query("SELECT id, server_id, triggerword FROM triggerword", function (err, results) {
       if (err) throw err;
       triggerWords = {};
       results.forEach(function (currentEntry) {
           triggerWords[currentEntry.server_id] = currentEntry.triggerword;
       });
    });
}
setInterval(updateTriggerWords, 1000);
biotmp(config.token);<|endoftext|>


<commit_before>//This code assumes var derivations has been set prior

var colorMap = {
		"default" : "gray",
		"ProcessorBasic" : 'green',
		"ProcessorDerived" : 'blue',
		"Rating Model" : 'red',
		"Statistic/Computation" : 'orange'
}

var shapeMap = {
		"default" : 'ellipse',
		"ProcessorBasic" : 'triangle',
		"ProcessorDerived" : 'rectangle'
}

var processorMap = {
		"Rating Model" : 'ratingModel',
		"Statistic/Computation" : 'statDerived'
}

var getTimePeriodEdges = function(nodes) {
	var dateMap = {};
	var dateList = [];

	for(var i = 0; i < derivations.length; i++) {
		var periodStartTime = derivations[i].periodStartTime;
		var periodEndTime = derivations[i].periodEndTime;

		if(!dateMap[periodStartTime]) {
			dateMap[periodStartTime] = periodStartTime;
			dateList.push(periodStartTime);
		}

		if(!dateMap[periodEndTime]) {
			dateMap[periodEndTime] = periodEndTime;
			dateList.push(periodEndTime);
		}
	}

	dateList.sort();

	return dateList;
}

var makeNode = function(nodeData) {
	var col = colorMap[nodeData.type || "default"];
	var shape = shapeMap[nodeData.type || "default"];

	return {
		data: {
			id: nodeData.uniqueId,
			name: nodeData.identifier,
			parameter: nodeData.parameter,
			sublocation: nodeData.sublocation,
			type: nodeData.type,
			computation: nodeData.computation,
			processor: nodeData.processedByType,
			weight: 50,
			faveColor: col,
			faveShape: shape } }
}

var insertEdges = function(edgeList, nodeData, traversedEdgeMap) {
	for(var i = 0; i < nodeData.inputSeriesUid.length; i++) {
		var fromId = nodeData.inputSeriesUid[i];
		var toId = nodeData.uniqueId;
		var edgeKey = fromId + "-" + toId;

		if(!traversedEdgeMap[edgeKey]) {
			var color = colorMap[nodeData.processedByType || "default"];
			var edge = { data: { source: fromId, target: toId, faveColor: color, strength: 20 } }

			var procType = processorMap[nodeData.processedByType]
			if(procType) {
				edge.classes = procType;
			}
			edgeList.push(edge);
			traversedEdgeMap[edgeKey] = true; //mark this node as created so it's not added to the graph again
		}
	}
}

//returns true if the processor date contains the date
var nodeIncludesDate = function(node, dateString) {
	var nodeStartDate = new Date(node.periodStartTime)
	var nodeEndDate = new Date(node.periodEndTime)
	var date = new Date(dateString)

	return date <= nodeEndDate && date > nodeStartDate;
}

var makeDerivationCurve = function(forDateString) {
	var nodes = [];
	var edges = [];
	var traversedEdgeMap = {};

	for(var i = 0; i < derivations.length; i++) {
		var n = derivations[i]
		if(nodeIncludesDate(n, forDateString)) {
			nodes.push(makeNode(n))
			insertEdges(edges, n, traversedEdgeMap);
		}
	}

	return cytoscape({
		container: document.getElementById('cy'),

		layout: {
			padding: 10,
			name: 'breadthfirst',
			directed: true,
		},

		style: cytoscape.stylesheet()
		.selector('node')
		.css({
			'shape': 'data(faveShape)',
			'width': 'mapData(weight, 40, 80, 20, 60)',
			'content': 'data(name)',
			'text-valign': 'center',
			'text-outline-width': 2,
			'text-outline-color': 'data(faveColor)',
			'background-color': 'data(faveColor)',
			'color': '#fff'
		})
		.selector(':selected')
		.css({
			'border-width': 3,
			'border-color': '#333'
		})
		.selector('edge')
		.css({
			'curve-style': 'bezier',
			'opacity': 0.666,
			'width': 'mapData(strength, 70, 100, 2, 6)',
			'target-arrow-shape': 'triangle',
			'source-arrow-shape': 'circle',
			'line-color': 'data(faveColor)',
			'source-arrow-color': 'data(faveColor)',
			'target-arrow-color': 'data(faveColor)'
		})
		.selector('edge.ratingModel')
		.css({
			'line-style': 'solid',
			'target-arrow-shape': 'triangle'
		})
		.selector('edge.statDerived')
		.css({
			'line-style': 'dotted',
			'target-arrow-shape': 'diamond'
		})
		.selector('.faded')
		.css({
			'opacity': 0.25,
			'text-opacity': 0
		}),

		elements: {
			nodes: nodes,
			edges: edges
		},

		ready: function(){
			var cy = window.cy = this;

			cy.nodes().forEach(function(n){
				n.qtip({
					content: [
						{ display: "Parameter", value: n.data('parameter')  },
						{ display: "Sublocation", value: n.data('sublocation')  },
						{ display: "Type", value: n.data('type')  },
						{ display: "Computation", value: n.data('computation')  },
						{ display: "Processor", value: n.data('processor')  }
						].map(function( link ){
							return '' + link.display + ' : ' + link.value + '';
						}).join('
\n'),
						position: {
							my: 'top center',
							at: 'bottom center'
						},
						style: {
							classes: 'qtip-bootstrap',
							tip: {
								width: 16,
								height: 8
							}
						}
				});
			});
		}
	});
}

var periodMarkers = getTimePeriodEdges(derivations);

var cy = makeDerivationCurve(periodMarkers[periodMarkers.length-1]);

function attachPeriodChangeHandler(newButton, inDateSelected) {
	var dateSelected = inDateSelected;
	newButton.click(function() {
		if(cy) {
			cy.destroy();
			$("#cy").html();
		}
		cy = makeDerivationCurve(dateSelected);
	})
}

var dateSelector = $("#dateSelector");
for(var i = periodMarkers.length - 1; i > 0 ; i--) {
	var newButton = $("");
	newButton.addClass("btn");
	newButton.addClass("btn-default");
	newButton.html("<input type=\"radio\" value=\"" + periodMarkers[i] + "\"> " + new Date(periodMarkers[i-1]) + " thru " + new Date(periodMarkers[i]))
	if(i == periodMarkers.length - 1) {
		newButton.addClass("active");
	}
	var periodSelected = periodMarkers[i];
	attachPeriodChangeHandler(newButton, periodSelected);
	dateSelector.append(newButton);
}<commit_msg>minor change to display of period selectors<commit_after>//This code assumes var derivations has been set prior

var colorMap = {
		"default" : "gray",
		"ProcessorBasic" : 'green',
		"ProcessorDerived" : 'blue',
		"Rating Model" : 'red',
		"Statistic/Computation" : 'orange'
}

var shapeMap = {
		"default" : 'ellipse',
		"ProcessorBasic" : 'triangle',
		"ProcessorDerived" : 'rectangle'
}

var processorMap = {
		"Rating Model" : 'ratingModel',
		"Statistic/Computation" : 'statDerived'
}

var getTimePeriodEdges = function(nodes) {
	var dateMap = {};
	var dateList = [];

	for(var i = 0; i < derivations.length; i++) {
		var periodStartTime = derivations[i].periodStartTime;
		var periodEndTime = derivations[i].periodEndTime;

		if(!dateMap[periodStartTime]) {
			dateMap[periodStartTime] = periodStartTime;
			dateList.push(periodStartTime);
		}

		if(!dateMap[periodEndTime]) {
			dateMap[periodEndTime] = periodEndTime;
			dateList.push(periodEndTime);
		}
	}

	dateList.sort();

	return dateList;
}

var makeNode = function(nodeData) {
	var col = colorMap[nodeData.type || "default"];
	var shape = shapeMap[nodeData.type || "default"];

	return {
		data: {
			id: nodeData.uniqueId,
			name: nodeData.identifier,
			parameter: nodeData.parameter,
			sublocation: nodeData.sublocation,
			type: nodeData.type,
			computation: nodeData.computation,
			processor: nodeData.processedByType,
			weight: 50,
			faveColor: col,
			faveShape: shape } }
}

var insertEdges = function(edgeList, nodeData, traversedEdgeMap) {
	for(var i = 0; i < nodeData.inputSeriesUid.length; i++) {
		var fromId = nodeData.inputSeriesUid[i];
		var toId = nodeData.uniqueId;
		var edgeKey = fromId + "-" + toId;

		if(!traversedEdgeMap[edgeKey]) {
			var color = colorMap[nodeData.processedByType || "default"];
			var edge = { data: { source: fromId, target: toId, faveColor: color, strength: 20 } }

			var procType = processorMap[nodeData.processedByType]
			if(procType) {
				edge.classes = procType;
			}
			edgeList.push(edge);
			traversedEdgeMap[edgeKey] = true; //mark this node as created so it's not added to the graph again
		}
	}
}

//returns true if the processor date contains the date
var nodeIncludesDate = function(node, dateString) {
	var nodeStartDate = new Date(node.periodStartTime)
	var nodeEndDate = new Date(node.periodEndTime)
	var date = new Date(dateString)

	return date <= nodeEndDate && date > nodeStartDate;
}

var makeDerivationCurve = function(forDateString) {
	var nodes = [];
	var edges = [];
	var traversedEdgeMap = {};

	for(var i = 0; i < derivations.length; i++) {
		var n = derivations[i]
		if(nodeIncludesDate(n, forDateString)) {
			nodes.push(makeNode(n))
			insertEdges(edges, n, traversedEdgeMap);
		}
	}

	return cytoscape({
		container: document.getElementById('cy'),

		layout: {
			padding: 10,
			name: 'breadthfirst',
			directed: true,
		},

		style: cytoscape.stylesheet()
		.selector('node')
		.css({
			'shape': 'data(faveShape)',
			'width': 'mapData(weight, 40, 80, 20, 60)',
			'content': 'data(name)',
			'text-valign': 'center',
			'text-outline-width': 2,
			'text-outline-color': 'data(faveColor)',
			'background-color': 'data(faveColor)',
			'color': '#fff'
		})
		.selector(':selected')
		.css({
			'border-width': 3,
			'border-color': '#333'
		})
		.selector('edge')
		.css({
			'curve-style': 'bezier',
			'opacity': 0.666,
			'width': 'mapData(strength, 70, 100, 2, 6)',
			'target-arrow-shape': 'triangle',
			'source-arrow-shape': 'circle',
			'line-color': 'data(faveColor)',
			'source-arrow-color': 'data(faveColor)',
			'target-arrow-color': 'data(faveColor)'
		})
		.selector('edge.ratingModel')
		.css({
			'line-style': 'solid',
			'target-arrow-shape': 'triangle'
		})
		.selector('edge.statDerived')
		.css({
			'line-style': 'dotted',
			'target-arrow-shape': 'diamond'
		})
		.selector('.faded')
		.css({
			'opacity': 0.25,
			'text-opacity': 0
		}),

		elements: {
			nodes: nodes,
			edges: edges
		},

		ready: function(){
			var cy = window.cy = this;

			cy.nodes().forEach(function(n){
				n.qtip({
					content: [
						{ display: "Parameter", value: n.data('parameter')  },
						{ display: "Sublocation", value: n.data('sublocation')  },
						{ display: "Type", value: n.data('type')  },
						{ display: "Computation", value: n.data('computation')  },
						{ display: "Processor", value: n.data('processor')  }
						].map(function( link ){
							return '' + link.display + ' : ' + link.value + '';
						}).join('
\n'),
						position: {
							my: 'top center',
							at: 'bottom center'
						},
						style: {
							classes: 'qtip-bootstrap',
							tip: {
								width: 16,
								height: 8
							}
						}
				});
			});
		}
	});
}

var periodMarkers = getTimePeriodEdges(derivations);

var cy = makeDerivationCurve(periodMarkers[periodMarkers.length-1]);

function attachPeriodChangeHandler(newButton, inDateSelected) {
	var dateSelected = inDateSelected;
	newButton.click(function() {
		if(cy) {
			cy.destroy();
			$("#cy").html();
		}
		cy = makeDerivationCurve(dateSelected);
	})
}

var dateSelector = $("#dateSelector");
for(var i = periodMarkers.length - 1; i > 0 ; i--) {
	var newButton = $("");
	newButton.addClass("btn");
	newButton.addClass("btn-default");
	newButton.html("<input type=\"radio\" value=\"" + periodMarkers[i] + "\"> " + new Date(periodMarkers[i-1]).toLocaleString() + " thru " + new Date(periodMarkers[i]).toLocaleString())
	if(i == periodMarkers.length - 1) {
		newButton.addClass("active");
	}
	var periodSelected = periodMarkers[i];
	attachPeriodChangeHandler(newButton, periodSelected);
	dateSelector.append(newButton);
}<|endoftext|>


<commit_before>//You really need body parser for things to work correctly
var express = require('express'),
    mongoose = require('mongoose'),
    Schema = mongoose.Schema,
    bodyParser = require('body-parser'),
    http = require('http'),
    models = require('../models/models.js'),
    restify = require('express-restify-mongoose'),
    methodOverride = require('method-override'),
    compress = require('compression'),
    cors = require('cors'),
    config = require('get-config').sync(__dirname + '/config');

mongoose.connect('mongodb://localhost/lcbo');

var InventoryModel = mongoose.model('inventory', models.schema.inventory);
var StoreModel = mongoose.model('store', models.schema.store);
var ProductModel = mongoose.model('product', models.schema.product);

var apiQueries = {
    storesNear: function (long, lat) {
        return {
            location: {
                $near: {
                    $geometry: {
                        type: "Point",
                        coordinates: [long, lat]
                    },
                    $maxDistance: 50000,
                    $minDistance: 0
                }
            }
        };
    },
    getInventoryByStore: function (store_id) {
        return {store_id: store_id};
    },
    getProductsFromIDs: function (ids, primaryCategory, producerExclusions) {
        return {
            id: {
                $in: ids
            },
            producer_name: {
                $nin: producerExclusions
            },
            primary_category: primaryCategory,
            secondary_category: {
                $nin: ['Specialty']
            }
        };
    }
};

var app = express();
app.use(compress());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(methodOverride('X-HTTP-Method-Override'));
app.use(cors());

var access_control = {
    prereq: function(req) {
        // Disallow POST PUT DELETE
        return false;
    }
};

var router = express.Router();
restify.serve(router, InventoryModel, access_control);
restify.serve(router, StoreModel, access_control);
restify.serve(router, ProductModel, access_control);

app.use(router);

app.get('/api/v1/storesNear', function(req, res) {
    StoreModel.geoNear({
            type: "Point",
            coordinates: [parseFloat(req.query.long), parseFloat(req.query.lat)]
        },
        { maxDistance: 50000, spherical: true }, function(err,docs){
            var results = []
            docs.forEach(function(doc) {
                doc.obj.location.distance_from_me = doc.dis;
                results.push(doc.obj);
            });

            res.send(results);
    });
});

app.get('/api/v1/inventoryByStore', function(req, res) {
    InventoryModel.find(apiQueries.getInventoryByStore(req.query.store_id), function(err,docs){
        res.send(docs);
    });
});

app.get('/api/v1/productIdByStore', function(req, res) {
    InventoryModel.find(apiQueries.getInventoryByStore(req.query.store_id), {
        '_id': 0,
        'product_id': 1
    }, function(err,docs){
        res.send(docs);
    });
});

app.get('/api/v1/productsAtStore', function(req, res) {
    InventoryModel.find(apiQueries.getInventoryByStore(req.query.store_id), function(err,docs){
        var arrayIds = [];
        var arrayInventories = [];

        for(var index in docs){
            arrayIds.push(docs[index].product_id);
            arrayInventories[docs[index].product_id] = docs[index];
        }

        ProductModel.find(apiQueries.getProductsFromIDs(arrayIds, 'Beer', config.api.brewery_exclusions), function(err,products){
            for(var index in products){
                var product = products[index];
                product.inventory.quantity = arrayInventories[product.id].quantity;
            }
            res.send(products);
        });
    });
});

app.listen(3000, function() {
    console.log("Express server listening on port 3000");
    console.log(config);
});<commit_msg>updated css<commit_after>//You really need body parser for things to work correctly
var express = require('express'),
    mongoose = require('mongoose'),
    Schema = mongoose.Schema,
    bodyParser = require('body-parser'),
    http = require('http'),
    models = require('../models/models.js'),
    restify = require('express-restify-mongoose'),
    methodOverride = require('method-override'),
    compress = require('compression'),
    cors = require('cors'),
    config = require('get-config').sync(__dirname + '/config');

mongoose.connect('mongodb://localhost/lcbo');

var InventoryModel = mongoose.model('inventory', models.schema.inventory);
var StoreModel = mongoose.model('store', models.schema.store);
var ProductModel = mongoose.model('product', models.schema.product);

var apiQueries = {
    storesNear: function (long, lat) {
        return {
            location: {
                $near: {
                    $geometry: {
                        type: "Point",
                        coordinates: [long, lat]
                    },
                    $maxDistance: 50000,
                    $minDistance: 0
                }
            }
        };
    },
    getInventoryByStore: function (store_id) {
        return {store_id: store_id};
    },
    getProductsFromIDs: function (ids, primaryCategory, producerExclusions) {
        return {
            id: {
                $in: ids
            },
            producer_name: {
                $nin: producerExclusions
            },
            primary_category: primaryCategory,
            secondary_category: {
                $nin: ['Specialty']
            }
        };
    }
};

var app = express();
app.use(compress());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(methodOverride('X-HTTP-Method-Override'));
app.use(cors());

var access_control = {
    prereq: function(req) {
        // Disallow POST PUT DELETE
        return false;
    }
};

var router = express.Router();
restify.serve(router, InventoryModel, access_control);
restify.serve(router, StoreModel, access_control);
restify.serve(router, ProductModel, access_control);

app.use(router);

app.get('/api/v1/storesNear', function(req, res) {
    StoreModel.geoNear({
            type: "Point",
            coordinates: [parseFloat(req.query.long), parseFloat(req.query.lat)]
        },
        { maxDistance: 50000, spherical: true }, function(err,docs){
            var results = []
            docs.forEach(function(doc) {
                doc.obj.location.distance_from_me = doc.dis;
                results.push(doc.obj);
            });

            res.send(results);
    });
});

app.get('/api/v1/inventoryByStore', function(req, res) {
    InventoryModel.find(apiQueries.getInventoryByStore(req.query.store_id), function(err,docs){
        res.send(docs);
    });
});

app.get('/api/v1/productIdByStore', function(req, res) {
    InventoryModel.find(apiQueries.getInventoryByStore(req.query.store_id), {
        '_id': 0,
        'product_id': 1
    }, function(err,docs){
        res.send(docs);
    });
});

app.get('/api/v1/productsAtStore', function(req, res) {
    InventoryModel.find(apiQueries.getInventoryByStore(req.query.store_id), function(err,docs){
        var arrayIds = [];
        var arrayInventories = [];

        for(var index in docs){
            arrayIds.push(docs[index].product_id);
            arrayInventories[docs[index].product_id] = docs[index];
        }

        ProductModel.find(apiQueries.getProductsFromIDs(arrayIds, 'Beer', config.api.brewery_exclusions), function(err,products){
            for(var index in products){
                var product = products[index];
                product.inventory.quantity = arrayInventories[product.id].quantity;
            }
            res.send(products);
        });
    });
});

app.listen(3000, function() {
    console.log("Express server listening on port 3000");
});<|endoftext|>


<commit_before>/**
  Copyright 2018 LNFWebsite
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
      http://www.apache.org/licenses/LICENSE-2.0
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
**/

// * This function interprets the type of URL (or whether it isn't a URL)
// * It then specifies how to interpret this URL in the function below

function urlValidate(url) {
  var output = false;

  var youtubeRegex = /(?:youtube\..+\/watch.+?v=|youtu\.be\/|youtube\..+\/embed\/)([^?&]+)(&list=[^?&]+)?/i;
  var streamlyRegex = /.*#(.+)/i;

  var youtubeMatch = url.match(youtubeRegex);
  if (youtubeMatch) {
    if (youtubeMatch[1] && youtubeMatch[2]) {
      output = [youtubeMatch[1], youtubeMatch[2].replace("&list=", "")];
      output = ["playlist", output];
    }
    else if (youtubeMatch[1]) {
      output = youtubeMatch[1];
      output = ["youtube", output];
    }
  }

  var streamlyMatch = url.match(streamlyRegex);
  if (streamlyMatch && streamlyMatch[1]) {
    output = streamlyMatch[1];
    output = ["streamly", output];
  }

  return output;
}

// * This function handles all user inputs
// * It has changed minimally throughout the history of Streamly
// * Its 'type' parameter specifies where the input is coming from (which I'm eventually going to change)
// * The playlist name box type number is 2

// * If a YouTube video URL load video to playlist, if a Streamly playlist append it to the current one, if none of the above load search

function input(type) {
  var inputBox = $("#inputBox").val();
  //if playlist input
  if (type === 2) {
    var playlistNameBox = $("#playlistNameBox").val();
    sendStation("playlistnamechange," + playlistNameBox);
    if (playlistNameBox !== "") {
      videos[0] = encodeURIComponent(playlistNameBox).replace(/%20/g, " ");
    }
    else {
      videos[0] = undefined;
    }
    setPlaylist();
  }
  else {
    if (inputBox !== "") {
      var isUrl = urlValidate(inputBox);
      var option = inputBox.match(/^-option (.+?)( .+?)?$/i);

      //var ua = navigator.userAgent.toLowerCase();
      //var isAndroid = ua.indexOf("android") > -1;

      if (option) {
        switch (option[1]) {
          case "hidevideo":
            $("#youtubeContainer").addClass("hideVideo");
            break;
          case "showvideo":
            $("#youtubeContainer").removeClass("hideVideo");
            break;
          case "background":
            if (typeof option[2] != 'undefined') {
              $("body, #blurBackground").css("background", option[2]);
            }
            else {
              alert("No background color or image specified");
            }
            break;
          case "radio":
            autoplayListOverride = true;
            break;
          default:
            alert("Sorry, but that option does not exist\n\nCheck with the list of Streamly options on GitHub");
        }
      }
      else if (isUrl) {
        if (isUrl[0] === "youtube") {
          inputBox = isUrl[1];
          getVideoData(inputBox);
          $("#inputBox").val("").attr("placeholder", loadingPlaceholder);
          /***
          if (typeof popup !== "undefined") {
            if (popupClose === true) {
              dropOverlay.close();
              popup.close();
              if (hotkeyPopupClose) {
                hotkeyPopupClose = false;
                togglePopupClose();
              }
            }
            else {
              popup.focus();
            }
          }
          ***/
        }
        else if (isUrl[0] === "streamly") {
          appendPlaylist(isUrl[1]);
          $("#inputBox").val("").attr("placeholder", placeholder);
        }
        else if (isUrl[0] === "playlist") {
          //turn on pause so that getVideoData doesn't try to play each video while loop-loading
          videoPaused = true;
          if (playlistAutoplay) {
            playlistFeatures.autoplay();
          }
          autoplayList = isUrl[1];
          playlistFeatures.autoplay();
          $("#inputBox").val("").attr("placeholder", placeholder);
        }
      }
      else if (inputBox.indexOf("\\") === -1) {
        if (inputBox.slice(-2) === " l") {
          inputBox = inputBox + "yric";
        }
        /***
        popup = window.open("https://www.youtube.com/results?search_query=" + inputBox.replace(/ /g, "+"), "YouTube", "height=500,width=800");
        dropOverlay.open();

        function checkIfClosed() {
            if (popup.closed) {
              dropOverlay.close();
              clearInterval(checkIfClosedTimer);
            }
        }
        var checkIfClosedTimer = setInterval(checkIfClosed, 500);
        ***/
        inBoxSearch = true;
        quickSearch(inputBox);
        //$("#inputBox").val("").attr("placeholder", loadingPlaceholder).blur();
        $("#inputBox").blur().focus();
      }
      else {
        inputBox = inputBox.replace("\\", "");
        if (inputBox.slice(-2) === " l") {
          inputBox = inputBox + "yric";
        }
        quickSearch(inputBox);
      }
    }
  }
}
<commit_msg>clear box once option recognized<commit_after>/**
  Copyright 2018 LNFWebsite
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
      http://www.apache.org/licenses/LICENSE-2.0
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
**/

// * This function interprets the type of URL (or whether it isn't a URL)
// * It then specifies how to interpret this URL in the function below

function urlValidate(url) {
  var output = false;

  var youtubeRegex = /(?:youtube\..+\/watch.+?v=|youtu\.be\/|youtube\..+\/embed\/)([^?&]+)(&list=[^?&]+)?/i;
  var streamlyRegex = /.*#(.+)/i;

  var youtubeMatch = url.match(youtubeRegex);
  if (youtubeMatch) {
    if (youtubeMatch[1] && youtubeMatch[2]) {
      output = [youtubeMatch[1], youtubeMatch[2].replace("&list=", "")];
      output = ["playlist", output];
    }
    else if (youtubeMatch[1]) {
      output = youtubeMatch[1];
      output = ["youtube", output];
    }
  }

  var streamlyMatch = url.match(streamlyRegex);
  if (streamlyMatch && streamlyMatch[1]) {
    output = streamlyMatch[1];
    output = ["streamly", output];
  }

  return output;
}

// * This function handles all user inputs
// * It has changed minimally throughout the history of Streamly
// * Its 'type' parameter specifies where the input is coming from (which I'm eventually going to change)
// * The playlist name box type number is 2

// * If a YouTube video URL load video to playlist, if a Streamly playlist append it to the current one, if none of the above load search

function input(type) {
  var inputBox = $("#inputBox").val();
  //if playlist input
  if (type === 2) {
    var playlistNameBox = $("#playlistNameBox").val();
    sendStation("playlistnamechange," + playlistNameBox);
    if (playlistNameBox !== "") {
      videos[0] = encodeURIComponent(playlistNameBox).replace(/%20/g, " ");
    }
    else {
      videos[0] = undefined;
    }
    setPlaylist();
  }
  else {
    if (inputBox !== "") {
      var isUrl = urlValidate(inputBox);
      var option = inputBox.match(/^-option (.+?)( .+?)?$/i);

      //var ua = navigator.userAgent.toLowerCase();
      //var isAndroid = ua.indexOf("android") > -1;

      if (option) {
        switch (option[1]) {
          case "hidevideo":
            $("#youtubeContainer").addClass("hideVideo");
            break;
          case "showvideo":
            $("#youtubeContainer").removeClass("hideVideo");
            break;
          case "background":
            if (typeof option[2] != 'undefined') {
              $("body, #blurBackground").css("background", option[2]);
            }
            else {
              alert("No background color or image specified");
            }
            break;
          case "radio":
            autoplayListOverride = true;
            break;
          default:
            alert("Sorry, but that option does not exist\n\nCheck with the list of Streamly options on GitHub");
        }
        $("#inputBox").val("").attr("placeholder", placeholder);
      }
      else if (isUrl) {
        if (isUrl[0] === "youtube") {
          inputBox = isUrl[1];
          getVideoData(inputBox);
          $("#inputBox").val("").attr("placeholder", loadingPlaceholder);
          /***
          if (typeof popup !== "undefined") {
            if (popupClose === true) {
              dropOverlay.close();
              popup.close();
              if (hotkeyPopupClose) {
                hotkeyPopupClose = false;
                togglePopupClose();
              }
            }
            else {
              popup.focus();
            }
          }
          ***/
        }
        else if (isUrl[0] === "streamly") {
          appendPlaylist(isUrl[1]);
          $("#inputBox").val("").attr("placeholder", placeholder);
        }
        else if (isUrl[0] === "playlist") {
          //turn on pause so that getVideoData doesn't try to play each video while loop-loading
          videoPaused = true;
          if (playlistAutoplay) {
            playlistFeatures.autoplay();
          }
          autoplayList = isUrl[1];
          playlistFeatures.autoplay();
          $("#inputBox").val("").attr("placeholder", placeholder);
        }
      }
      else if (inputBox.indexOf("\\") === -1) {
        if (inputBox.slice(-2) === " l") {
          inputBox = inputBox + "yric";
        }
        /***
        popup = window.open("https://www.youtube.com/results?search_query=" + inputBox.replace(/ /g, "+"), "YouTube", "height=500,width=800");
        dropOverlay.open();

        function checkIfClosed() {
            if (popup.closed) {
              dropOverlay.close();
              clearInterval(checkIfClosedTimer);
            }
        }
        var checkIfClosedTimer = setInterval(checkIfClosed, 500);
        ***/
        inBoxSearch = true;
        quickSearch(inputBox);
        //$("#inputBox").val("").attr("placeholder", loadingPlaceholder).blur();
        $("#inputBox").blur().focus();
      }
      else {
        inputBox = inputBox.replace("\\", "");
        if (inputBox.slice(-2) === " l") {
          inputBox = inputBox + "yric";
        }
        quickSearch(inputBox);
      }
    }
  }
}
<|endoftext|>


<commit_before>MapStyle = {
  displayRules: [new OpenLayers.Rule({
      symbolizer: {"Line" : { strokeWidth: 8,
                              strokeColor: '#00ff00',
                              strokeOpacity: 0.8 },
                    "Point" : { pointRadius: 8,
                                strokeColor: '#004400',
                                strokeOpacity: 0.9,
                                strokeWidth: 2,
                                fillOpacity: 0.3,
                                fillColor: '#00ff00' },
                    "Polygon" : { strokeWidth: 2.5,
                                  strokeOpacity: 0.8,
                                  strokeColor: '#004400',
                                  fillColor: '#00ff00' }
      },
      elseFilter: true
  })],

  editRules: [new OpenLayers.Rule({
      symbolizer: {"Line" : { strokeWidth: 2,
                              strokeColor: '#000000',
                              strokeOpacity: 0.8 },
                    "Point" : { pointRadius: 8,
                                strokeColor: '#000000',
                                strokeOpacity: 0.9,
                                strokeWidth: 2,
                                fillOpacity: 0.3,
                                fillColor: '#000000' },
                    "Polygon" : { strokeWidth: 2.5,
                                  strokeOpacity: 0.8,
                                  strokeColor: '#000000',
                                  fillColor: '#000000' }
      },
      elseFilter: true
  })],

  editStyle: function() {
    var styleMap = new OpenLayers.StyleMap();
    styleMap.styles["default"].addRules(this.displayRules);
    styleMap.styles["select"].addRules(this.displayRules);
    styleMap.styles["temporary"].addRules(this.editRules);
    return styleMap;
  },

  displayStyle: function() {
    var styleMap = new OpenLayers.StyleMap();
    styleMap.styles["default"].addRules(this.displayRules);
    styleMap.styles["select"].addRules(this.displayRules);
    return styleMap;
  }
}
<commit_msg>Move to black-and-white theme from designers<commit_after>MapStyle = {
  displayRules: [new OpenLayers.Rule({
      symbolizer: {"Line" : { strokeWidth: 8,
                              strokeColor: '#333333',
                              strokeOpacity: 0.9 },
                    "Point" : { pointRadius: 8,
                                strokeColor: '#333333',
                                strokeOpacity: 0.9,
                                strokeWidth: 2,
                                fillOpacity: 0.4,
                                fillColor: '#ffffff' },
                    "Polygon" : { strokeWidth: 2.5,
                                  strokeOpacity: 0.9,
                                  strokeColor: '#333333',
                                  fillOpacity: 0.5,
                                  fillColor: '#ffffff' }
      },
      elseFilter: true
  })],

  editRules: [new OpenLayers.Rule({
      symbolizer: {"Line" : { strokeWidth: 2,
                              strokeColor: '#000000',
                              strokeOpacity: 0.8 },
                    "Point" : { pointRadius: 8,
                                strokeColor: '#000000',
                                strokeOpacity: 0.9,
                                strokeWidth: 2,
                                fillOpacity: 0.3,
                                fillColor: '#ffffff' },
                    "Polygon" : { strokeWidth: 2.5,
                                  strokeOpacity: 0.8,
                                  strokeColor: '#000000',
                                  fillColor: '#ffffff' }
      },
      elseFilter: true
  })],

  editStyle: function() {
    var styleMap = new OpenLayers.StyleMap();
    styleMap.styles["default"].addRules(this.displayRules);
    styleMap.styles["select"].addRules(this.displayRules);
    styleMap.styles["temporary"].addRules(this.editRules);
    return styleMap;
  },

  displayStyle: function() {
    var styleMap = new OpenLayers.StyleMap();
    styleMap.styles["default"].addRules(this.displayRules);
    styleMap.styles["select"].addRules(this.displayRules);
    return styleMap;
  }
}
<|endoftext|>


<commit_before>#!/usr/bin/env node

/**
 * Copyright 2014 Netsend.
 *
 * This file is part of Mastersync.
 *
 * Mastersync is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Affero General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * Mastersync is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License along
 * with Mastersync. If not, see <https://www.gnu.org/licenses/>.
 */

'use strict';

var program = require('commander');

var _db = require('./_db');

var syncAttr = require('../lib/sync_attr');

program
  .version('0.0.1')
  .usage('[-v] -a database [-b database] -c collection [-d collection] attr')
  .description('synchronize attr on items in a.c from corresponding items in b.d')
  .option('-a, --database1 <database>', 'name of the database for collection1')
  .option('-b, --database2 <database>', 'name of the database for collection2 if different from database1')
  .option('-c, --collection1 <collection>', 'name of the collection to report about')
  .option('-d, --collection2 <collection>', 'name of the collection to compare against if different from collection1')
  .option('-m, --match <attrs>', 'comma separated list of attributes to should match', function(val) { return val.split(','); })
  .option('-i, --include <attrs>', 'comma separated list of attributes to include in comparison', function(val) { return val.split(','); })
  .option('-e, --exclude <attrs>', 'comma separated list of attributes to exclude in comparison', function(val) { return val.split(','); })
  .option('-v, --verbose', 'verbose')
  .parse(process.argv);

// get config path from environment
var config = require(process.env.CONFIG || '../config/development.json');

if (!program.database1) { program.help(); }
if (!program.database2) { program.database2 = program.database1; }
if (!program.collection1) { program.help(); }
if (!program.collection2) { program.collection2 = program.collection1; }

if (!program.args[0]) { program.help(); }

var attr = program.args[0];

var excludeAttrs = {};
(program.exclude || []).forEach(function(attr) {
  excludeAttrs[attr] = true;
});

var includeAttrs = {};
(program.include || []).forEach(function(attr) {
  includeAttrs[attr] = true;
});

var matchAttrs = {};
(program.match || []).forEach(function(attr) {
  matchAttrs[attr] = true;
});

var debug = !!program.verbose;

if (debug && Object.keys(includeAttrs).length) { console.log('include:', program.include); }
if (debug && Object.keys(excludeAttrs).length) { console.log('exclude:', program.exclude); }
if (debug && Object.keys(matchAttrs).length) { console.log('match:', program.match); }

//// phase 1: sync version numbers on equal objects if the rest of the object has equal attribute values
//// phase 2: treat all items in collection 2 with equal ids and different objects as parents of collection 1
function run(db) {
  var coll1 = db.db(program.database1).collection(program.collection1);
  var coll2 = db.db(program.database2).collection(program.collection2);
  var tmpColl = db.db(program.database1).collection(program.collection1 + '.tmp');

  var opts = {
    includeAttrs: includeAttrs,
    excludeAttrs: excludeAttrs,
    matchAttrs: matchAttrs,
    debug: debug
  };

  syncAttr(coll1, coll2, tmpColl, attr, opts, function(err, updated) {
    if (err) { throw err; }
    console.log('updated', updated);
    db.close();
  });
}

// open database
_db(config, function(err, db) {
  if (err) { throw err; }
  run(db);
});
<commit_msg>sync_attr.js with ini config<commit_after>#!/usr/bin/env node

/**
 * Copyright 2014 Netsend.
 *
 * This file is part of Mastersync.
 *
 * Mastersync is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Affero General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * Mastersync is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License along
 * with Mastersync. If not, see <https://www.gnu.org/licenses/>.
 */

'use strict';

var program = require('commander');

var _db = require('./_db');
var properties = require('properties');
var fs = require('fs');

var syncAttr = require('../lib/sync_attr');

program
  .version('0.0.1')
  .usage('[-v] -a database [-b database] -c collection [-d collection] -f config attr')
  .description('synchronize attr on items in a.c from corresponding items in b.d')
  .option('-a, --database1 <database>', 'name of the database for collection1')
  .option('-b, --database2 <database>', 'name of the database for collection2 if different from database1')
  .option('-c, --collection1 <collection>', 'name of the collection to report about')
  .option('-d, --collection2 <collection>', 'name of the collection to compare against if different from collection1')
  .option('-f, --config <config>', 'an ini config file')
  .option('-m, --match <attrs>', 'comma separated list of attributes to should match', function(val) { return val.split(','); })
  .option('-i, --include <attrs>', 'comma separated list of attributes to include in comparison', function(val) { return val.split(','); })
  .option('-e, --exclude <attrs>', 'comma separated list of attributes to exclude in comparison', function(val) { return val.split(','); })
  .option('-v, --verbose', 'verbose')
  .parse(process.argv);

console.log(program.config);
// get config path from environment
if (!program.config) {
  program.help();
}

var config = program.config;

// if relative, prepend current working dir
if (config[0] !== '/') {
  config = process.cwd() + '/' + config;
}

config = properties.parse(fs.readFileSync(config, { encoding: 'utf8' }), { sections: true, namespaces: true });

if (!program.database1) { program.help(); }
if (!program.database2) { program.database2 = program.database1; }
if (!program.collection1) { program.help(); }
if (!program.collection2) { program.collection2 = program.collection1; }

if (!program.args[0]) { program.help(); }

var attr = program.args[0];

var excludeAttrs = {};
(program.exclude || []).forEach(function(attr) {
  excludeAttrs[attr] = true;
});

var includeAttrs = {};
(program.include || []).forEach(function(attr) {
  includeAttrs[attr] = true;
});

var matchAttrs = {};
(program.match || []).forEach(function(attr) {
  matchAttrs[attr] = true;
});

var debug = !!program.verbose;

if (debug && Object.keys(includeAttrs).length) { console.log('include:', program.include); }
if (debug && Object.keys(excludeAttrs).length) { console.log('exclude:', program.exclude); }
if (debug && Object.keys(matchAttrs).length) { console.log('match:', program.match); }

//// phase 1: sync version numbers on equal objects if the rest of the object has equal attribute values
//// phase 2: treat all items in collection 2 with equal ids and different objects as parents of collection 1
function run(db) {
  var coll1 = db.db(program.database1).collection(program.collection1);
  var coll2 = db.db(program.database2).collection(program.collection2);
  var tmpColl = db.db(program.database1).collection(program.collection1 + '.tmp');

  var opts = {
    includeAttrs: includeAttrs,
    excludeAttrs: excludeAttrs,
    matchAttrs: matchAttrs,
    debug: debug
  };

  syncAttr(coll1, coll2, tmpColl, attr, opts, function(err, updated) {
    if (err) { throw err; }
    console.log('updated', updated);
    db.close();
  });
}

var database = config.database;
var dbCfg = {
  dbName: database.name || 'local',
  dbHost: database.path || database.host,
  dbPort: database.port,
  dbUser: database.username,
  dbPass: database.password,
  adminDb: database.adminDb
};

// open database
_db(dbCfg, function(err, db) {
  if (err) { throw err; }
  run(db);
});
<|endoftext|>