<commit_before>'use strict'

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// Testing
slapp.command('/bible', /.*/, (msg, text) => {
  console.log('received bible command');
  msg.say('Received slash command for Bible. Command entered:' + text);
  sendRequest(text);
})

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

// Send HTTP Request
function sendRequest(text) {
  var body;
  var options = {
    host: 'labs.bible.org',
    path: '/api/?passage=John+3:16-17',
  }

  var request = http.get(options, function(response){
    console.log('STATUS: ' + response.statusCode);
    console.log('HEADERS: ' + JSON.stringify(response.headers));

    // Buffer the body entirely for processing as a whole.
    var bodyStream = [];
    response.on('data', function(chunk) {
      // Partially streamed body
      console.log('-----got chunk-----');
      bodyStream.push(chunk);
    }).on('end', function() {
      // Completely streamed body
      console.log('-----finished body-----');
      body = Buffer.concat(bodyStream);
      console.log('BODY: ' + body);
      reply(body);
    })
  });

  request.on('error', function(e) {
    console.log('error occurred in HTTP GET request: ', e.message);
  });
}

function reply(body) {
  var verse = body;
  console.log('got this from sendRequest():', verse);
  msg.say('Here\'s your verse!\n' + verse);
}

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

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

  console.log(`Listening on port ${port}`)
})
<commit_msg>passing msg along, adding toString<commit_after>'use strict'

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// Testing
slapp.command('/bible', /.*/, (msg, text) => {
  console.log('received bible command');
  msg.say('Received slash command for Bible. Command entered:' + text);
  sendRequest(text);
})

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

// Send HTTP Request
function sendRequest(text, msg) {
  var body;
  var options = {
    host: 'labs.bible.org',
    path: '/api/?passage=John+3:16-17',
  }

  var request = http.get(options, function(response){
    console.log('STATUS: ' + response.statusCode);
    console.log('HEADERS: ' + JSON.stringify(response.headers));

    // Buffer the body entirely for processing as a whole.
    var bodyStream = [];
    response.on('data', function(chunk) {
      // Partially streamed body
      console.log('-----got chunk-----');
      bodyStream.push(chunk);
    }).on('end', function() {
      // Completely streamed body
      console.log('-----finished body-----');
      body = Buffer.concat(bodyStream).toString();
      console.log('BODY: ' + body);
      reply(body, msg);
    })
  });

  request.on('error', function(e) {
    console.log('error occurred in HTTP GET request: ', e.message);
  });
}

function reply(body, msg) {
  var verse = body;
  console.log('got this from sendRequest():', verse);
  msg.say('Here\'s your verse!\n' + verse);
}

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

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

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


<commit_before>'use babel';

export default {
  config: require('./config'),

  activate() {
    if (!/^win/.test(process.platform)) {
      // Manually append /usr/local/bin as it may not be set on some systems,
      // and it's common to have node installed here. Keep it at end so it won't
      // accidentially override any other node installation
      process.env.PATH += ':/usr/local/bin';
    }

    require('atom-package-deps').install('build');

    this.tools = [ require('./atom-build') ];
    this.linter = null;

    this.setupTargetManager();
    this.setupBuildView();
    this.setupErrorMatcher();

    atom.commands.add('atom-workspace', 'build:trigger', () => this.build('trigger'));
    atom.commands.add('atom-workspace', 'build:stop', () => this.stop());
    atom.commands.add('atom-workspace', 'build:confirm', () => {
      require('./google-analytics').sendEvent('build', 'confirmed');
      document.activeElement.click();
    });
    atom.commands.add('atom-workspace', 'build:no-confirm', () => {
      if (this.saveConfirmView) {
        require('./google-analytics').sendEvent('build', 'not confirmed');
        this.saveConfirmView.cancel();
      }
    });

    atom.workspace.observeTextEditors((editor) => {
      editor.onDidSave(() => {
        if (atom.config.get('build.buildOnSave')) {
          this.build('save');
        }
      });
    });

    atom.workspace.onDidChangeActivePaneItem(() => this.updateStatusBar());
    atom.packages.onDidActivateInitialPackages(() => this.targetManager.refreshTargets());
  },

  setupTargetManager() {
    const TargetManager = require('./target-manager');
    this.targetManager = new TargetManager();
    this.targetManager.setTools(this.tools);
    this.targetManager.on('refresh-complete', () => {
      this.updateStatusBar();
    });
    this.targetManager.on('new-active-target', (path, target) => {
      this.updateStatusBar();

      if (atom.config.get('build.selectTriggers')) {
        this.build('trigger');
      }
    });
    this.targetManager.on('trigger', atomCommandName => this.build('trigger', atomCommandName));
  },

  setupBuildView() {
    const BuildView = require('./build-view');
    this.buildView = new BuildView();
  },

  setupErrorMatcher() {
    const ErrorMatcher = require('./error-matcher');
    this.errorMatcher = new ErrorMatcher();
    this.errorMatcher.on('error', (message) => {
      atom.notifications.addError('Error matching failed!', { detail: message });
    });
    this.errorMatcher.on('matched', (match) => {
      match[0] && this.buildView.scrollTo(match[0]);
    });
  },

  deactivate() {
    if (this.child) {
      this.child.removeAllListeners();
      require('tree-kill')(this.child.pid, 'SIGKILL');
      this.child = null;
    }

    this.statusBarView && this.statusBarView.destroy();
    this.buildView && this.buildView.destroy();
    this.saveConfirmView && this.saveConfirmView.destroy();
    this.linter && this.linter.destroy();
    this.targetManager.destroy();

    clearTimeout(this.finishedTimer);
  },

  updateStatusBar() {
    const path = require('./utils').activePath();
    const activeTarget = this.targetManager.getActiveTarget(path);
    this.statusBarView && activeTarget && this.statusBarView.setTarget(activeTarget.name);
  },

  startNewBuild(source, atomCommandName) {
    const BuildError = require('./build-error');
    const path = require('./utils').activePath();
    let buildTitle = '';
    this.linter && this.linter.clear();

    Promise.resolve(this.targetManager.getTargets(path)).then(targets => {
      if (!targets || 0 === targets.length) {
        throw new BuildError('No eligible build target.', 'No configuration to build this project exists.');
      }

      let target = targets.find(t => t.atomCommandName === atomCommandName);
      if (!target) {
        target = this.targetManager.getActiveTarget(path);
      }
      require('./google-analytics').sendEvent('build', 'triggered');

      if (!target.exec) {
        throw new BuildError('Invalid build file.', 'No executable command specified.');
      }

      this.statusBarView && this.statusBarView.buildStarted();
      this.busyRegistry && this.busyRegistry.begin(`build.${target.name}`, `${target.name}`);
      this.buildView.buildStarted();
      this.buildView.setHeading('Running preBuild...');

      return Promise.resolve(target.preBuild ? target.preBuild() : null).then(() => target);
    }).then(target => {
      const replace = require('./utils').replace;
      const env = Object.assign({}, process.env, target.env);
      Object.keys(env).forEach(key => {
        env[key] = replace(env[key], target.env);
      });

      const exec = replace(target.exec, target.env);
      const args = target.args.map(arg => replace(arg, target.env));
      const cwd = replace(target.cwd, target.env);
      const isWin = process.platform === 'win32';
      const shCmd = isWin ? 'cmd' : '/bin/sh';
      const shCmdArg = isWin ? '/C' : '-c';

      // Store this as we need to re-set it after postBuild
      buildTitle = [ (target.sh ? `${shCmd} ${shCmdArg} ${exec}` : exec ), ...args, '\n'].join(' ');

      this.buildView.setHeading(buildTitle);
      if (target.sh) {
        this.child = require('child_process').spawn(
          shCmd,
          [ shCmdArg, [ exec ].concat(args).join(' ')],
          { cwd: cwd, env: env }
        );
      } else {
        this.child = require('cross-spawn-async').spawn(
          exec,
          args,
          { cwd: cwd, env: env }
        );
      }

      let stdout = '';
      let stderr = '';
      this.child.stdout.setEncoding('utf8');
      this.child.stderr.setEncoding('utf8');
      this.child.stdout.on('data', d => (stdout += d));
      this.child.stderr.on('data', d => (stderr += d));
      this.child.stdout.pipe(this.buildView.terminal);
      this.child.stderr.pipe(this.buildView.terminal);

      this.child.on('error', (err) => {
        this.buildView.terminal.write((target.sh ? 'Unable to execute with shell: ' : 'Unable to execute: ') + exec + '\n');

        if (/\s/.test(exec) && !target.sh) {
          this.buildView.terminal.write('`cmd` cannot contain space. Use `args` for arguments.\n');
        }

        if ('ENOENT' === err.code) {
          this.buildView.terminal.write(`Make sure cmd:'${exec}' and cwd:'${cwd}' exists and have correct access permissions.\n`);
          this.buildView.terminal.write(`Binaries are found in these folders: ${process.env.PATH}\n`);
        }
      });

      this.child.on('close', (exitCode) => {
        this.child = null;
        this.errorMatcher.set(target, cwd, stdout + stderr);

        let success = (0 === exitCode);
        if (atom.config.get('build.matchedErrorFailsBuild')) {
          success = success && !this.errorMatcher.getMatches().some(match => match.type && match.type.toLowerCase() === 'error');
        }

        this.linter && this.linter.processMessages(this.errorMatcher.getMatches(), cwd);

        if (atom.config.get('build.beepWhenDone')) {
          atom.beep();
        }

        this.buildView.setHeading('Running postBuild...');
        return Promise.resolve(target.postBuild ? target.postBuild(success) : null).then(() => {
          this.buildView.setHeading(buildTitle);

          this.busyRegistry && this.busyRegistry.end(`build.${target.name}`, success);
          this.buildView.buildFinished(success);
          this.statusBarView && this.statusBarView.setBuildSuccess(success);
          if (success) {
            require('./google-analytics').sendEvent('build', 'succeeded');
            this.finishedTimer = setTimeout(() => {
              this.buildView.detach();
            }, 1200);
          } else {
            if (atom.config.get('build.scrollOnError')) {
              this.errorMatcher.matchFirst();
            }
            require('./google-analytics').sendEvent('build', 'failed');
          }
        });
      });
    }).catch((err) => {
      if (err instanceof BuildError) {
        if (source === 'save') {
          // If there is no eligible build tool, and cause of build was a save, stay quiet.
          return;
        }

        atom.notifications.addWarning(err.name, { detail: err.message });
      } else {
        atom.notifications.addError('Failed to build.', { detail: err.message });
      }
    });
  },

  abort(cb) {
    this.child.on('exit', () => {
      this.child = null;
      cb && cb();
    });

    try {
      require('tree-kill')(this.child.pid, this.child.killed ? 'SIGKILL' : 'SIGTERM');
    } catch (e) {
      /* Something may have happened to the child (e.g. terminated by itself). Ignore this. */
    }

    this.child.killed = true;
  },

  build(source, event) {
    clearTimeout(this.finishedTimer);

    this.doSaveConfirm(this.unsavedTextEditors(), () => {
      const next = this.startNewBuild.bind(this, source, event ? event.type : null);
      this.child ? this.abort(next) : next();
    });
  },

  doSaveConfirm(modifiedTextEditors, continuecb, cancelcb) {
    const saveAndContinue = (save) => {
      modifiedTextEditors.forEach((textEditor) => save && textEditor.save());
      continuecb();
    };

    if (0 === modifiedTextEditors.length || atom.config.get('build.saveOnBuild')) {
      saveAndContinue(true);
      return;
    }

    if (this.saveConfirmView) {
      this.saveConfirmView.destroy();
    }

    const SaveConfirmView = require('./save-confirm-view');
    this.saveConfirmView = new SaveConfirmView();
    this.saveConfirmView.show(saveAndContinue, cancelcb);
  },

  unsavedTextEditors() {
    return atom.workspace.getTextEditors().filter((textEditor) => {
      return textEditor.isModified() && (undefined !== textEditor.getPath());
    });
  },

  stop() {
    clearTimeout(this.finishedTimer);
    if (this.child) {
      if (!this.child.killed) {
        this.buildView.buildAbortInitiated();
      }
      this.abort(() => {
        this.buildView.buildAborted();
        this.statusBarView && this.statusBarView.buildAborted();
      });
    } else {
      this.buildView.reset();
    }
  },

  consumeLinterRegistry(registry) {
    this.linter && this.linter.destroy();
    const Linter = require('./linter-integration');
    this.linter = new Linter(registry);
  },

  consumeBuilder(builder) {
    this.tools.push(builder);
    this.targetManager.setTools(this.tools);
    const Disposable = require('atom').Disposable;
    return new Disposable(() => {
      this.tools = this.tools.filter(tool => tool !== builder);
      this.targetManager.setTools(this.tools);
    });
  },

  consumeStatusBar(statusBar) {
    const StatusBarView = require('./status-bar-view');
    this.statusBarView = new StatusBarView(statusBar);
    this.statusBarView.onClick(() => this.targetManager.selectActiveTarget());
    this.statusBarView.attach();
  },

  consumeBusy(registry) {
    this.busyRegistry = registry;
    this.targetManager.setBusyRegistry(registry);
  }
};
<commit_msg>Allow consumeBuilder to accept an array of builders<commit_after>'use babel';

export default {
  config: require('./config'),

  activate() {
    if (!/^win/.test(process.platform)) {
      // Manually append /usr/local/bin as it may not be set on some systems,
      // and it's common to have node installed here. Keep it at end so it won't
      // accidentially override any other node installation
      process.env.PATH += ':/usr/local/bin';
    }

    require('atom-package-deps').install('build');

    this.tools = [ require('./atom-build') ];
    this.linter = null;

    this.setupTargetManager();
    this.setupBuildView();
    this.setupErrorMatcher();

    atom.commands.add('atom-workspace', 'build:trigger', () => this.build('trigger'));
    atom.commands.add('atom-workspace', 'build:stop', () => this.stop());
    atom.commands.add('atom-workspace', 'build:confirm', () => {
      require('./google-analytics').sendEvent('build', 'confirmed');
      document.activeElement.click();
    });
    atom.commands.add('atom-workspace', 'build:no-confirm', () => {
      if (this.saveConfirmView) {
        require('./google-analytics').sendEvent('build', 'not confirmed');
        this.saveConfirmView.cancel();
      }
    });

    atom.workspace.observeTextEditors((editor) => {
      editor.onDidSave(() => {
        if (atom.config.get('build.buildOnSave')) {
          this.build('save');
        }
      });
    });

    atom.workspace.onDidChangeActivePaneItem(() => this.updateStatusBar());
    atom.packages.onDidActivateInitialPackages(() => this.targetManager.refreshTargets());
  },

  setupTargetManager() {
    const TargetManager = require('./target-manager');
    this.targetManager = new TargetManager();
    this.targetManager.setTools(this.tools);
    this.targetManager.on('refresh-complete', () => {
      this.updateStatusBar();
    });
    this.targetManager.on('new-active-target', (path, target) => {
      this.updateStatusBar();

      if (atom.config.get('build.selectTriggers')) {
        this.build('trigger');
      }
    });
    this.targetManager.on('trigger', atomCommandName => this.build('trigger', atomCommandName));
  },

  setupBuildView() {
    const BuildView = require('./build-view');
    this.buildView = new BuildView();
  },

  setupErrorMatcher() {
    const ErrorMatcher = require('./error-matcher');
    this.errorMatcher = new ErrorMatcher();
    this.errorMatcher.on('error', (message) => {
      atom.notifications.addError('Error matching failed!', { detail: message });
    });
    this.errorMatcher.on('matched', (match) => {
      match[0] && this.buildView.scrollTo(match[0]);
    });
  },

  deactivate() {
    if (this.child) {
      this.child.removeAllListeners();
      require('tree-kill')(this.child.pid, 'SIGKILL');
      this.child = null;
    }

    this.statusBarView && this.statusBarView.destroy();
    this.buildView && this.buildView.destroy();
    this.saveConfirmView && this.saveConfirmView.destroy();
    this.linter && this.linter.destroy();
    this.targetManager.destroy();

    clearTimeout(this.finishedTimer);
  },

  updateStatusBar() {
    const path = require('./utils').activePath();
    const activeTarget = this.targetManager.getActiveTarget(path);
    this.statusBarView && activeTarget && this.statusBarView.setTarget(activeTarget.name);
  },

  startNewBuild(source, atomCommandName) {
    const BuildError = require('./build-error');
    const path = require('./utils').activePath();
    let buildTitle = '';
    this.linter && this.linter.clear();

    Promise.resolve(this.targetManager.getTargets(path)).then(targets => {
      if (!targets || 0 === targets.length) {
        throw new BuildError('No eligible build target.', 'No configuration to build this project exists.');
      }

      let target = targets.find(t => t.atomCommandName === atomCommandName);
      if (!target) {
        target = this.targetManager.getActiveTarget(path);
      }
      require('./google-analytics').sendEvent('build', 'triggered');

      if (!target.exec) {
        throw new BuildError('Invalid build file.', 'No executable command specified.');
      }

      this.statusBarView && this.statusBarView.buildStarted();
      this.busyRegistry && this.busyRegistry.begin(`build.${target.name}`, `${target.name}`);
      this.buildView.buildStarted();
      this.buildView.setHeading('Running preBuild...');

      return Promise.resolve(target.preBuild ? target.preBuild() : null).then(() => target);
    }).then(target => {
      const replace = require('./utils').replace;
      const env = Object.assign({}, process.env, target.env);
      Object.keys(env).forEach(key => {
        env[key] = replace(env[key], target.env);
      });

      const exec = replace(target.exec, target.env);
      const args = target.args.map(arg => replace(arg, target.env));
      const cwd = replace(target.cwd, target.env);
      const isWin = process.platform === 'win32';
      const shCmd = isWin ? 'cmd' : '/bin/sh';
      const shCmdArg = isWin ? '/C' : '-c';

      // Store this as we need to re-set it after postBuild
      buildTitle = [ (target.sh ? `${shCmd} ${shCmdArg} ${exec}` : exec ), ...args, '\n'].join(' ');

      this.buildView.setHeading(buildTitle);
      if (target.sh) {
        this.child = require('child_process').spawn(
          shCmd,
          [ shCmdArg, [ exec ].concat(args).join(' ')],
          { cwd: cwd, env: env }
        );
      } else {
        this.child = require('cross-spawn-async').spawn(
          exec,
          args,
          { cwd: cwd, env: env }
        );
      }

      let stdout = '';
      let stderr = '';
      this.child.stdout.setEncoding('utf8');
      this.child.stderr.setEncoding('utf8');
      this.child.stdout.on('data', d => (stdout += d));
      this.child.stderr.on('data', d => (stderr += d));
      this.child.stdout.pipe(this.buildView.terminal);
      this.child.stderr.pipe(this.buildView.terminal);

      this.child.on('error', (err) => {
        this.buildView.terminal.write((target.sh ? 'Unable to execute with shell: ' : 'Unable to execute: ') + exec + '\n');

        if (/\s/.test(exec) && !target.sh) {
          this.buildView.terminal.write('`cmd` cannot contain space. Use `args` for arguments.\n');
        }

        if ('ENOENT' === err.code) {
          this.buildView.terminal.write(`Make sure cmd:'${exec}' and cwd:'${cwd}' exists and have correct access permissions.\n`);
          this.buildView.terminal.write(`Binaries are found in these folders: ${process.env.PATH}\n`);
        }
      });

      this.child.on('close', (exitCode) => {
        this.child = null;
        this.errorMatcher.set(target, cwd, stdout + stderr);

        let success = (0 === exitCode);
        if (atom.config.get('build.matchedErrorFailsBuild')) {
          success = success && !this.errorMatcher.getMatches().some(match => match.type && match.type.toLowerCase() === 'error');
        }

        this.linter && this.linter.processMessages(this.errorMatcher.getMatches(), cwd);

        if (atom.config.get('build.beepWhenDone')) {
          atom.beep();
        }

        this.buildView.setHeading('Running postBuild...');
        return Promise.resolve(target.postBuild ? target.postBuild(success) : null).then(() => {
          this.buildView.setHeading(buildTitle);

          this.busyRegistry && this.busyRegistry.end(`build.${target.name}`, success);
          this.buildView.buildFinished(success);
          this.statusBarView && this.statusBarView.setBuildSuccess(success);
          if (success) {
            require('./google-analytics').sendEvent('build', 'succeeded');
            this.finishedTimer = setTimeout(() => {
              this.buildView.detach();
            }, 1200);
          } else {
            if (atom.config.get('build.scrollOnError')) {
              this.errorMatcher.matchFirst();
            }
            require('./google-analytics').sendEvent('build', 'failed');
          }
        });
      });
    }).catch((err) => {
      if (err instanceof BuildError) {
        if (source === 'save') {
          // If there is no eligible build tool, and cause of build was a save, stay quiet.
          return;
        }

        atom.notifications.addWarning(err.name, { detail: err.message });
      } else {
        atom.notifications.addError('Failed to build.', { detail: err.message });
      }
    });
  },

  abort(cb) {
    this.child.on('exit', () => {
      this.child = null;
      cb && cb();
    });

    try {
      require('tree-kill')(this.child.pid, this.child.killed ? 'SIGKILL' : 'SIGTERM');
    } catch (e) {
      /* Something may have happened to the child (e.g. terminated by itself). Ignore this. */
    }

    this.child.killed = true;
  },

  build(source, event) {
    clearTimeout(this.finishedTimer);

    this.doSaveConfirm(this.unsavedTextEditors(), () => {
      const next = this.startNewBuild.bind(this, source, event ? event.type : null);
      this.child ? this.abort(next) : next();
    });
  },

  doSaveConfirm(modifiedTextEditors, continuecb, cancelcb) {
    const saveAndContinue = (save) => {
      modifiedTextEditors.forEach((textEditor) => save && textEditor.save());
      continuecb();
    };

    if (0 === modifiedTextEditors.length || atom.config.get('build.saveOnBuild')) {
      saveAndContinue(true);
      return;
    }

    if (this.saveConfirmView) {
      this.saveConfirmView.destroy();
    }

    const SaveConfirmView = require('./save-confirm-view');
    this.saveConfirmView = new SaveConfirmView();
    this.saveConfirmView.show(saveAndContinue, cancelcb);
  },

  unsavedTextEditors() {
    return atom.workspace.getTextEditors().filter((textEditor) => {
      return textEditor.isModified() && (undefined !== textEditor.getPath());
    });
  },

  stop() {
    clearTimeout(this.finishedTimer);
    if (this.child) {
      if (!this.child.killed) {
        this.buildView.buildAbortInitiated();
      }
      this.abort(() => {
        this.buildView.buildAborted();
        this.statusBarView && this.statusBarView.buildAborted();
      });
    } else {
      this.buildView.reset();
    }
  },

  consumeLinterRegistry(registry) {
    this.linter && this.linter.destroy();
    const Linter = require('./linter-integration');
    this.linter = new Linter(registry);
  },

  consumeBuilder(builder) {
    if (Array.isArray(builder)) this.tools.push(...builder); else this.tools.push(builder);
    this.targetManager.setTools(this.tools);
    const Disposable = require('atom').Disposable;
    return new Disposable(() => {
      this.tools = this.tools.filter(Array.isArray(builder) ? tool => builder.indexOf(tool) === -1 : tool => tool !== builder);
      this.targetManager.setTools(this.tools);
    });
  },

  consumeStatusBar(statusBar) {
    const StatusBarView = require('./status-bar-view');
    this.statusBarView = new StatusBarView(statusBar);
    this.statusBarView.onClick(() => this.targetManager.selectActiveTarget());
    this.statusBarView.attach();
  },

  consumeBusy(registry) {
    this.busyRegistry = registry;
    this.targetManager.setBusyRegistry(registry);
  }
};
<|endoftext|>


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

module.exports = {
  httpPort: 8080,
  streamPort: 8082,
  wsPort: 8084,
  staticFolder: path.join(__dirname + '/../../../client')
};<commit_msg>Delete server.js<commit_after><|endoftext|>


<commit_before>var Schema  = require('./schema')
var TIMEOUT = 100

module.exports = function (schema, id, open, onCache) {
  var local = cached.local = {}
  schema = Schema(schema, id)
  if('string' != typeof id)
    throw new Error('id must be string')
  if('function' !== typeof open)
    throw new Error('open must be function')
  function cached (name, tail, cb) {
    if('function' == typeof tail)
      cb = tail, tail = true

    //user *must not* pass a Scuttlebutt instance to cached open.
    if('string' !== typeof name)
      throw new Error('name must be string')

    //so if this is passed a ready instance...
    //and there is a cached instance... then pipe them together.
    //hmm, but the caching should be ontop of the other layer...
    //will this work?
    //ah, if a scuttlebutt is passed, and there isn't one in the cache
    //clone it and put the clone in the cache!
    //else, pipe it to the cached instace.

    //actually... should combine this into level-scuttlebutt
    //then only one cache will be necessary.

    //which will work better for reconnections.

    //...so, need lots of tests here.

    //yes, only one cache, the outer most open does not support
    //opening with a scuttlebutt - but remote, and
    //level-scuttlebutt do!

    //then there is only one cache...
    //so, you always control the point of caching.
    //no "russian doll" caching.

    var cached = local[name]
    if(cached && 'function' === typeof cached.clone) {
      var n = cached.clone()
      n.name = name
      cb(null, n)
      return n
    }

    var clone
    var scuttlebutt = local[name] = schema(name)
    scuttlebutt.name = name

    open(scuttlebutt, tail, function (err, scuttlebutt) {
      if(err) return cb(err)
      cb(null, clone)
    })

    //will callback an error
    if(!scuttlebutt) return

    scuttlebutt.name = name

    //only scuttlebutts with clone can be cleanly cached.
    if('function' === typeof scuttlebutt.clone) {
      local[name] = scuttlebutt
      clone = scuttlebutt.clone()
      clone._parent = scuttlebutt
      clone.name = name
      if(onCache) onCache('clone', scuttlebutt.name)
      //okay... have something to dispose the scuttlebutt when there are 0 streams.
      //hmm, count streams... and emit an event 'unstream' or something?
      //okay, if all the steams have closed but this one, then it means no one is using this,
      //so close...
      //TODO add this to level-scuttlebutt.

      //OH, hang on... maybe DOMAINS is the right thing to use here...

      var timer = null
      scuttlebutt.on('unstream', function (n) {
        if(n === 1) {
          clearTimeout(timer)
          timer = setTimeout(function () {
            scuttlebutt.dispose()
            if(onCache) onCache('uncache', scuttlebutt.name)
          }, TIMEOUT*1.5)
            //if an emitter was passed, imet
        } else if(n > 1)
          clearTimeout(timer)
      })
      scuttlebutt.on('dispose', function () {
        delete local[name]
      })
    }

    return scuttlebutt
  }

  return cached
}

<commit_msg>use unclone event, not unstream<commit_after>var Schema  = require('./schema')
var TIMEOUT = 100

module.exports = function (schema, id, open, onCache) {
  var local = cached.local = {}
  schema = Schema(schema, id)
  if('string' != typeof id)
    throw new Error('id must be string')
  if('function' !== typeof open)
    throw new Error('open must be function')
  function cached (name, tail, cb) {
    if('function' == typeof tail)
      cb = tail, tail = true

    //user *must not* pass a Scuttlebutt instance to cached open.
    if('string' !== typeof name)
      throw new Error('name must be string')

    //so if this is passed a ready instance...
    //and there is a cached instance... then pipe them together.
    //hmm, but the caching should be ontop of the other layer...
    //will this work?
    //ah, if a scuttlebutt is passed, and there isn't one in the cache
    //clone it and put the clone in the cache!
    //else, pipe it to the cached instace.

    //actually... should combine this into level-scuttlebutt
    //then only one cache will be necessary.

    //which will work better for reconnections.

    //...so, need lots of tests here.

    //yes, only one cache, the outer most open does not support
    //opening with a scuttlebutt - but remote, and
    //level-scuttlebutt do!

    //then there is only one cache...
    //so, you always control the point of caching.
    //no "russian doll" caching.

    var cached = local[name]
    if(cached && 'function' === typeof cached.clone) {
      var n = cached.clone()
      n.name = name
      cb(null, n)
      return n
    }

    var clone
    var scuttlebutt = local[name] = schema(name)
    scuttlebutt.name = name

    open(scuttlebutt, tail, function (err, scuttlebutt) {
      if(err) return cb(err)
      cb(null, clone)
    })

    //will callback an error
    if(!scuttlebutt) return

    scuttlebutt.name = name

    //only scuttlebutts with clone can be cleanly cached.
    if('function' === typeof scuttlebutt.clone) {
      local[name] = scuttlebutt
      clone = scuttlebutt.clone()
      clone._parent = scuttlebutt
      clone.name = name
      if(onCache) onCache('clone', scuttlebutt.name)
      //okay... have something to dispose the scuttlebutt when there are 0 streams.
      //hmm, count streams... and emit an event 'unstream' or something?
      //okay, if all the steams have closed but this one, then it means no one is using this,
      //so close...
      //TODO add this to level-scuttlebutt.

      //OH, hang on... maybe DOMAINS is the right thing to use here...

      var timer = null
      scuttlebutt.on('unclone', function (n) {
        if(n === 0) {
          clearTimeout(timer)
          timer = setTimeout(function () {
            if(scuttlebutt._clones) return
            scuttlebutt.dispose()
            if(onCache) onCache('uncache', scuttlebutt.name)
          }, TIMEOUT*1.5)
            //if an emitter was passed, imet
        } else if(n > 1)
          clearTimeout(timer)
      })
      scuttlebutt.on('dispose', function () {
        delete local[name]
      })
    }

    return scuttlebutt
  }

  return cached
}

<|endoftext|>


<commit_before>var url = require('url'),
	https = require('https'),
	assert = require('assert');

exports.api = function(login, password, config) {
	"use strict";
	assert.equal(typeof(login), 'string', "argument 'login' must be a string");
	assert.equal(typeof(password), 'string', "argument 'password' must be a string");

	var SDK_VERSION = "1.1";

	// allow api url to be changed
	this.apiUrl = "https://api.callr.com/json-rpc/v1.1/";

	// Callback class
	var Callback = function() {
		this.success = false;
		this.error = false;
	};

	// Send a request to THECALLR webservice
	this.call = function(method) {
		assert.equal(typeof(method), 'string', "argument 'method' must be a string");

		var args = Array.prototype.slice.call(arguments);
		return this.send(method, args.slice(1, args.length));
	};

	// Send a request to THECALLR webservice
	this.send = function(method, params, id) {
		assert.equal(typeof(method), 'string', "argument 'method' must be a string");
		assert.ok(params instanceof(Array), "argument 'params' must be an array");

		var json = JSON.stringify({
			id: id === undefined || isNaN(parseInt(id)) ? Math.floor(Math.random() * (999 - 100)) + 100 : id,
			jsonrpc: "2.0",
			method: method,
			params: params instanceof Array ? params : []
		});

		var options = url.parse(this.apiUrl);
		options.port = 443;
		options.method = "POST";
		options.auth = login + ':' + password;
		options.headers = {
			"Content-Type": "application/json-rpc; charset=utf-8",
			"User-Agent": "sdk=NODE; sdk-version="+SDK_VERSION+"; lang-version="+process.version+"; platform="+process.platform,
			"Content-Length": Buffer.byteLength(json)
		};

		// Proxy agent support
		if (config && config.hasOwnProperty('proxyAgent')) {
			options.agent = config.proxyAgent;
		}

		this.callback = new Callback();

		// Annonymous Closure to keep data untouched on successive call
		(function(options, json, callback) {
			// make new request
			var req = https.request(options, function(res) {
				var buf = "";
				if (res.statusCode != 200) {
					doCallback(callback.error, error("HTTP_CODE_ERROR", -1, {
						http_code: res.statusCode
					}));
				}
				res.on('data', function(data) {
					  buf += data;
				});
				res.on('end', function() {
					  parseData(buf.toString(), callback);
				});
			});

			req.on('error', function(e) {
				doCallback(callback.error, error("HTTP_EXCEPTION", -1, {
					exception: e
				}));
			}).on('end', function() {
				console.log('request end');
			}).end(json);
		})(options, json, this.callback);

		return this;
	};

	// set success callback
	this.success = function(cb) {
		this.callback.success = cb;
		return this;
	};

	// set error callback
	this.error = function(cb) {
		this.callback.error = cb;
		return this;
	};

	// Response analysis
	function parseData(json, callback) {
		try {
			var data = JSON.parse(json);
			if (data && data.hasOwnProperty('result'))
				doCallback(callback.success, data.result);
			else if (data && data.hasOwnProperty('error') && data.error)
				doCallback(callback.error, error(data.error.message, data.error.code, null));
			else
				doCallback(callback.error, error("INVALID_RESPONSE", -1, {
					responses: json.toString()
				}));
		}
		catch (e) {
			doCallback(callback.error, error("INVALID_RESPONSE", -1, {
				exception: e,
				response: json.toString()
			}));
		}
	}

	function doCallback(callback, result) {
		if (typeof(callback) == 'function')
			callback(result);
	}

	function error(msg, code, data) {
		var err = new Error(msg);
		err.code = code;
		err.data = data;
		return err;
	}
};
<commit_msg>feat(logas): add LogAs support to sdk, passed in options to api.auth<commit_after>var url = require('url'),
	https = require('https'),
	assert = require('assert');

exports.api = function(login, password, config) {
	"use strict";
	assert.equal(typeof(login), 'string', "argument 'login' must be a string");
	assert.equal(typeof(password), 'string', "argument 'password' must be a string");

	var SDK_VERSION = "1.1";

	// var LogAs types
	var loginAsTypes = {
		user: 'user.login',
		account: 'account.hash'
	}

	// allow api url to be changed
	this.apiUrl = "https://api.callr.com/json-rpc/v1.1/";

	// Callback class
	var Callback = function() {
		this.success = false;
		this.error = false;
	};

	// Send a request to THECALLR webservice
	this.call = function(method) {
		assert.equal(typeof(method), 'string', "argument 'method' must be a string");

		var args = Array.prototype.slice.call(arguments);
		return this.send(method, args.slice(1, args.length));
	};

	// Send a request to THECALLR webservice
	this.send = function(method, params, id) {
		assert.equal(typeof(method), 'string', "argument 'method' must be a string");
		assert.ok(params instanceof(Array), "argument 'params' must be an array");

		var json = JSON.stringify({
			id: id === undefined || isNaN(parseInt(id)) ? Math.floor(Math.random() * (999 - 100)) + 100 : id,
			jsonrpc: "2.0",
			method: method,
			params: params instanceof Array ? params : []
		});

		var options = url.parse(this.apiUrl);
		options.port = 443;
		options.method = "POST";
		options.auth = login + ':' + password;
		options.headers = {
			"Content-Type": "application/json-rpc; charset=utf-8",
			"User-Agent": "sdk=NODE; sdk-version="+SDK_VERSION+"; lang-version="+process.version+"; platform="+process.platform,
			"Content-Length": Buffer.byteLength(json)
		};

		// Login As support
		if (config && config.hasOwnProperty('loginas')) {
			assert.equal(typeof (config.loginas.type), 'string', "loginas.type must be a string");
			assert.ok(config.loginas.type.toLowerCase() in loginAsTypes, `loginas type must be one of "${Object.keys(loginAsTypes)}"`);
			assert.equal(typeof (config.loginas.target), 'string', "loginas.target must be a string")

			options.headers['CALLR-Login-As'] = `${loginAsTypes[config.loginas.type.toLowerCase()]} ${config.loginas.target}`;
		}

		// Proxy agent support
		if (config && config.hasOwnProperty('proxyAgent')) {
			options.agent = config.proxyAgent;
		}

		this.callback = new Callback();

		// Annonymous Closure to keep data untouched on successive call
		(function(options, json, callback) {
			// make new request
			var req = https.request(options, function(res) {
				var buf = "";
				if (res.statusCode != 200) {
					doCallback(callback.error, error("HTTP_CODE_ERROR", -1, {
						http_code: res.statusCode
					}));
				}
				res.on('data', function(data) {
					buf += data;
				});
				res.on('end', function() {
					parseData(buf.toString(), callback);
				});
			});

			req.on('error', function(e) {
				doCallback(callback.error, error("HTTP_EXCEPTION", -1, {
					exception: e
				}));
			}).on('end', function() {
				console.log('request end');
			}).end(json);
		})(options, json, this.callback);

		return this;
	};

	// set success callback
	this.success = function(cb) {
		this.callback.success = cb;
		return this;
	};

	// set error callback
	this.error = function(cb) {
		this.callback.error = cb;
		return this;
	};

	// Response analysis
	function parseData(json, callback) {
		try {
			var data = JSON.parse(json);
			if (data && data.hasOwnProperty('result'))
				doCallback(callback.success, data.result);
			else if (data && data.hasOwnProperty('error') && data.error)
				doCallback(callback.error, error(data.error.message, data.error.code, null));
			else
				doCallback(callback.error, error("INVALID_RESPONSE", -1, {
					responses: json.toString()
				}));
		}
		catch (e) {
			doCallback(callback.error, error("INVALID_RESPONSE", -1, {
				exception: e,
				response: json.toString()
			}));
		}
	}

	function doCallback(callback, result) {
		if (typeof(callback) == 'function')
			callback(result);
	}

	function error(msg, code, data) {
		var err = new Error(msg);
		err.code = code;
		err.data = data;
		return err;
	}
};
<|endoftext|>


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

/**
 * Module dependencies.
 */

var app = require('./app');
var debug = require('debug')('node-edison-server:server');
var http = require('http');

/**
 * Get port from environment and store in Express.
 */

var port = normalizePort(process.env.PORT || '4222');
app.set('port', port);

/**
 * Create HTTP server.
 */

console.log("TestKey: " + process.env.TestKey);
console.log("RedisHostName: " + process.env.RedisHostName);
console.log("RedisKey: " + process.env.RedisKey);

var server = http.createServer(app);

/**
 * Listen on provided port, on all network interfaces.
 */

server.on('error', onError);
server.on('listening', onListening);

var io = require('socket.io')(server);
var redishostname = process.env.RedisHostName;
var rediskey = process.env.RedisKey;
var pub = require('redis').createClient(6379,redishostname, {auth_pass: rediskey, return_buffers: true});
var sub = require('redis').createClient(6379,redishostname, {auth_pass: rediskey, return_buffers: true});

var redis = require('socket.io-redis');
io.adapter(redis({pubClient: pub, subClient: sub}));

var webClientRepo = require('./models/webclientrepo');
var eddyClientRepo = require('./models/eddyrepo');
var EddyClient = require('./models/eddyclient');
var WebClient = require('./models/webclient');

io.on('connection', function (socket) {
  socket.on('init', function(data){
    console.log("Init");
    console.log(data);
    if(data.clientType=='eddy')
    {
      var eddy = new EddyClient(socket,data);
      eddyClientRepo.addClient(eddy);
      webClientRepo.eddyConnected(eddy);
    }
    if (data.clientType=='web')
    {
      var webClient = new WebClient(socket);
      webClientRepo.addClient(webClient);
    }
  });
  socket.emit('welcome', { hello: 'world' });
  socket.on('test', function (data) {
    console.log(data);
  });
});

server.listen(port);

/**
 * Normalize a port into a number, string, or false.
 */

function normalizePort(val) {
  var port = parseInt(val, 10);

  if (isNaN(port)) {
    // named pipe
    return val;
  }

  if (port >= 0) {
    // port number
    return port;
  }

  return false;
}

/**
 * Event listener for HTTP server "error" event.
 */

function onError(error) {
  if (error.syscall !== 'listen') {
    throw error;
  }

  var bind = typeof port === 'string'
    ? 'Pipe ' + port
    : 'Port ' + port

  // handle specific listen errors with friendly messages
  switch (error.code) {
    case 'EACCES':
      console.error(bind + ' requires elevated privileges');
      process.exit(1);
      break;
    case 'EADDRINUSE':
      console.error(bind + ' is already in use');
      process.exit(1);
      break;
    default:
      throw error;
  }
}

/**
 * Event listener for HTTP server "listening" event.
 */

function onListening() {
  var addr = server.address();
  var bind = typeof addr === 'string'
    ? 'pipe ' + addr
    : 'port ' + addr.port;
  debug('Listening on ' + bind);
}
<commit_msg>socket.io+azure hell v2<commit_after>#!/usr/bin/env node

/**
 * Module dependencies.
 */

var app = require('./app');
var debug = require('debug')('node-edison-server:server');
var http = require('http');

/**
 * Get port from environment and store in Express.
 */

var port = normalizePort(process.env.PORT || '4222');
app.set('port', port);

/**
 * Create HTTP server.
 */

console.log("TestKey: " + process.env.TestKey);
console.log("RedisHostName: " + process.env.RedisHostName);
console.log("RedisKey: " + process.env.RedisKey);

var server = http.createServer(app);

/**
 * Listen on provided port, on all network interfaces.
 */

server.on('error', onError);
server.on('listening', onListening);

var io = require('socket.io').listen(server);
var redishostname = process.env.RedisHostName;
var rediskey = process.env.RedisKey;
var pub = require('redis').createClient(6379,redishostname, {auth_pass: rediskey, return_buffers: true});
var sub = require('redis').createClient(6379,redishostname, {auth_pass: rediskey, return_buffers: true});

var redis = require('socket.io-redis');
io.adapter(redis({pubClient: pub, subClient: sub}));

var webClientRepo = require('./models/webclientrepo');
var eddyClientRepo = require('./models/eddyrepo');
var EddyClient = require('./models/eddyclient');
var WebClient = require('./models/webclient');

io.on('connection', function (socket) {
  socket.on('init', function(data){
    console.log("Init");
    console.log(data);
    if(data.clientType=='eddy')
    {
      var eddy = new EddyClient(socket,data);
      eddyClientRepo.addClient(eddy);
      webClientRepo.eddyConnected(eddy);
    }
    if (data.clientType=='web')
    {
      var webClient = new WebClient(socket);
      webClientRepo.addClient(webClient);
    }
  });
  socket.emit('welcome', { hello: 'world' });
  socket.on('test', function (data) {
    console.log(data);
  });
});

server.listen(port);

/**
 * Normalize a port into a number, string, or false.
 */

function normalizePort(val) {
  var port = parseInt(val, 10);

  if (isNaN(port)) {
    // named pipe
    return val;
  }

  if (port >= 0) {
    // port number
    return port;
  }

  return false;
}

/**
 * Event listener for HTTP server "error" event.
 */

function onError(error) {
  if (error.syscall !== 'listen') {
    throw error;
  }

  var bind = typeof port === 'string'
    ? 'Pipe ' + port
    : 'Port ' + port

  // handle specific listen errors with friendly messages
  switch (error.code) {
    case 'EACCES':
      console.error(bind + ' requires elevated privileges');
      process.exit(1);
      break;
    case 'EADDRINUSE':
      console.error(bind + ' is already in use');
      process.exit(1);
      break;
    default:
      throw error;
  }
}

/**
 * Event listener for HTTP server "listening" event.
 */

function onListening() {
  var addr = server.address();
  var bind = typeof addr === 'string'
    ? 'pipe ' + addr
    : 'port ' + addr.port;
  debug('Listening on ' + bind);
}
<|endoftext|>


<commit_before>"use strict";

var Promise = require('bluebird');

var mmm = require('mmmagic'),
    Magic = mmm.Magic,
    magic = new Magic(mmm.MAGIC_MIME_TYPE);

var Chunk = function(file, n, riakfs) {
    if(!(this instanceof Chunk)) {
        return new Chunk(file, n, riakfs);
    }

    this.file = file;
    this.n = n;
    this.key = file.id + ':' + n;
    this.riak = riakfs.riak;
    this.bucket = riakfs.chunksBucket;

    this.length = 0;
    this.modified = false;
    this.vclock = undefined;
}

Chunk.CHUNK_SIZE = 256 * 1024;

module.exports = Chunk;

Chunk.prototype.load = function() {
    var self = this;

    return self.riak.get({
        bucket: self.bucket,
        key: self.key,
        deletedvclock: true
    }).then(function(reply) {
        if(!reply || !reply.content){
            throw new Error('Chunk not found: ' + self.bucket + '/' + self.key)
        }
        self.data = reply.content[0].value;
        self.length = self.data.length;
        self.modified = false;
        self.vclock = reply.vclock;
    })
}

var mimetype = function (buffer) {
    return new Promise(function(resolve, reject) {
        magic.detect(buffer, function(err, result) {
            if (err) {
                return reject(err)
            }
            resolve(result)
        })
    })
}

Chunk.prototype.save = function() {
    var self = this;

    if(!self.modified){
        return Promise.resolve()
    }

    var data = self.data.slice(0, self.length)

    return self.riak.put({
        bucket: self.bucket,
        key: self.key,
        vclock: self.vclock,
        content: {
            value: data,
            content_type: 'binary/octet-stream',
            usermeta: [{
                key: 'length',
                value: data.length
            }]
        }
    }).then(function() {
        self.mofified = false;
        if(self.n === 0){
            return mimetype(data)
                .then(function(_mt) {
                    self.file.contentType = _mt;
                })
                .catch(function() {})
        }
    })
}

Chunk.prototype.write = function(buffer, position) {
    var self = this;

    self.modified = true;

    // allocate new buffer
    if(!self.data){
        self.data = new Buffer(Chunk.CHUNK_SIZE);
    }

    // chunk data is appended, grow the buffer
    if(self.data.length < Chunk.CHUNK_SIZE){
        var newBuf = new Buffer(Chunk.CHUNK_SIZE)
        self.data.copy(newBuf)
        self.data = newBuf
    }

    if(position > self.length){
        return 0
    }

    var bytesToWrite = Chunk.CHUNK_SIZE - position
    if(bytesToWrite > buffer.length){
        bytesToWrite = buffer.length
    }

    if(bytesToWrite === 0){
        return 0
    }

    buffer.copy(self.data, position, 0, bytesToWrite)
    self.length += bytesToWrite

    if((position + bytesToWrite) > self.length){
        self.length = position + bytesToWrite
    }

    return bytesToWrite;
}

Chunk.prototype.read = function(buffer, position, length) {
    var self = this;

    if(position >= self.data.length){
        return 0
    }

    var bytesToRead = self.data.length - position
    if(bytesToRead > length){
        bytesToRead = length
    }

    self.data.copy(buffer, 0, position, position + bytesToRead)

    return bytesToRead
}
<commit_msg>Fix wrong chunk length when writing to file by position<commit_after>"use strict";

var Promise = require('bluebird');

var mmm = require('mmmagic'),
    Magic = mmm.Magic,
    magic = new Magic(mmm.MAGIC_MIME_TYPE);

var Chunk = function(file, n, riakfs) {
    if(!(this instanceof Chunk)) {
        return new Chunk(file, n, riakfs);
    }

    this.file = file;
    this.n = n;
    this.key = file.id + ':' + n;
    this.riak = riakfs.riak;
    this.bucket = riakfs.chunksBucket;

    this.length = 0;
    this.modified = false;
    this.vclock = undefined;
}

Chunk.CHUNK_SIZE = 256 * 1024;

module.exports = Chunk;

Chunk.prototype.load = function() {
    var self = this;

    return self.riak.get({
        bucket: self.bucket,
        key: self.key,
        deletedvclock: true
    }).then(function(reply) {
        if(!reply || !reply.content){
            throw new Error('Chunk not found: ' + self.bucket + '/' + self.key)
        }
        self.data = reply.content[0].value;
        self.length = self.data.length;
        self.modified = false;
        self.vclock = reply.vclock;
    })
}

var mimetype = function (buffer) {
    return new Promise(function(resolve, reject) {
        magic.detect(buffer, function(err, result) {
            if (err) {
                return reject(err)
            }
            resolve(result)
        })
    })
}

Chunk.prototype.save = function() {
    var self = this;

    if(!self.modified){
        return Promise.resolve()
    }

    var data = self.data.slice(0, self.length)

    return self.riak.put({
        bucket: self.bucket,
        key: self.key,
        vclock: self.vclock,
        content: {
            value: data,
            content_type: 'binary/octet-stream',
            usermeta: [{
                key: 'length',
                value: data.length
            }]
        }
    }).then(function() {
        self.mofified = false;
        if(self.n === 0){
            return mimetype(data)
                .then(function(_mt) {
                    self.file.contentType = _mt;
                })
                .catch(function() {})
        }
    })
}

Chunk.prototype.write = function(buffer, position) {
    var self = this;

    self.modified = true;

    // allocate new buffer
    if(!self.data){
        self.data = new Buffer(Chunk.CHUNK_SIZE);
    }

    // chunk data is appended, grow the buffer
    if(self.data.length < Chunk.CHUNK_SIZE){
        var newBuf = new Buffer(Chunk.CHUNK_SIZE)
        self.data.copy(newBuf)
        self.data = newBuf
    }

    if(position > self.length){
        return 0
    }

    var bytesToWrite = Chunk.CHUNK_SIZE - position
    if(bytesToWrite > buffer.length){
        bytesToWrite = buffer.length
    }

    if(bytesToWrite === 0){
        return 0
    }

    buffer.copy(self.data, position, 0, bytesToWrite)

    if((position + bytesToWrite) > self.length){
        self.length = position + bytesToWrite
    }

    return bytesToWrite;
}

Chunk.prototype.read = function(buffer, position, length) {
    var self = this;

    if(position >= self.data.length){
        return 0
    }

    var bytesToRead = self.data.length - position
    if(bytesToRead > length){
        bytesToRead = length
    }

    self.data.copy(buffer, 0, position, position + bytesToRead)

    return bytesToRead
}
<|endoftext|>


<commit_before>const cluster = require('cluster');

const EventEmitter = require('events').EventEmitter;

const util   = require('util');
const logger = require('./lib/logger');
const _      = require('lodash');
const net = require('net');

const RequestDecoder = require('./messages/decoders').RequestDecoder;
const randomstring = require('randomstring');

const ResponseWriter = require('./lib/pipeline/response_writer');
const through2 = require('through2');
const Response       = require('./messages').Response;

const defaults = {
  port:      9485,
  hostname:  '0.0.0.0',
  logLevel: 'info',
  metrics: {
    gauge:     _.noop,
    increment: _.noop,
    histogram: _.noop,
    flush:     _.noop
  }
};

function fork_worker() {
  const worker = cluster.fork();

  worker._pendingRequests = new Map();

  worker.on('message', function (response) {
    var callback = worker._pendingRequests.get(response.request_id);
    worker._pendingRequests.delete(response.id);
    return callback(null, response);
  });

  worker.sendRequest = function (message, callback) {
    worker._pendingRequests.set(message.id, callback);
    worker.send(message);
  };

  return worker;
}

/*
 * Creates an instance of BaaSServer.
 *
 * Options:
 *
 *  - `port` the port to listen to. Defaults to 9231.
 *  - `hostname` the hostname to bind to. Defaults to INADDR_ANY
 *  - `logLevel` the verbosity of the logs. Defaults to 'info'.
 *
 */
function BaaSServer (options) {
  EventEmitter.call(this);
  const self = this;

  this._config = _.extend({}, defaults, options);
  this._logger = logger(this._config.logLevel);
  this._server = net.createServer(this._handler.bind(this));
  this._metrics = this._config.metrics;
  this._server.on('error', function (err) {
    self.emit('error', err);
  });

  cluster.setupMaster({
    exec: __dirname + '/worker.js'
  });

  const workers_number = typeof process.env.WORKERS === 'undefined' ||
                          process.env.WORKERS === 'AUTO' ?
                          Math.max(require('os').cpus().length - 1, 1) :
                          parseInt(process.env.WORKERS);

  this._workers = _.range(workers_number).map(fork_worker);

}

util.inherits(BaaSServer, EventEmitter);

BaaSServer.prototype._handler = function (socket) {
  const self = this;

  self._metrics.increment('connection.incoming');

  const sockets_details = _.pick(socket, ['remoteAddress', 'remotePort']);

  sockets_details.connection = socket._connection_id = randomstring.generate(5);

  const log = self._logger;

  socket.on('error', function (err) {
    self._metrics.increment('connection.error');
    log.info(_.extend(sockets_details, {
      err: {
        code:    err.code,
        message: err.message
      }
    }), 'connection error');
  }).on('close', function () {
    self._metrics.increment('connection.closed');
    log.debug(sockets_details, 'connection closed');
  });

  log.debug(sockets_details, 'connection accepted');

  const decoder = RequestDecoder();

  decoder.on('error', function () {
    log.info(sockets_details, 'unknown message format');
    return socket.end();
  });

  socket.pipe(decoder)
        .pipe(through2.obj((request, encoding, callback) => {
          const worker = self._workers.shift();
          const operation = request.operation === 0 ? 'compare' : 'hash';
          const start = new Date();

          if (!worker) {
            log.info({
              request:    request.id,
              connection: socket._connection_id,
              took:       new Date() - start,
              operation:  operation
            }, `${operation} not done - server is busy`);

            return  callback(null, new Response({
              request_id: request.id,
              success:    false,
              busy:       true
            }));
          }

          self._metrics.histogram(`requests.incoming.${operation}.time`, (new Date() - start));

          worker.sendRequest(request, (err, response) => {
            log.info({
              request:    request.id,
              connection: socket._connection_id,
              took:       new Date() - start,
              worker:     worker.id,
              operation:  operation
            }, `${operation} completed`);

            self._metrics.histogram(`requests.processed.${operation}.time`, (new Date() - start));
            self._metrics.increment(`requests.processed.${operation}`);
            self._workers.push(worker);
            callback(null, new Response(response));
          });

        }))
        .pipe(ResponseWriter())
        .pipe(socket);
};

BaaSServer.prototype.start = function (done) {
  const self = this;
  const log = self._logger;

  self._server.listen(this._config.port, this._config.hostname, function(err) {
    if (err) {
      log.error(err, 'error starting server');
      self.emit('error', err);
      if (done) {
        done(err);
      }
      return;
    }

    const address = self._server.address();

    log.info(address, 'server started');

    self.emit('started', address);
    if (done) {
      done(null, address);
    }
  });

  return this;
};

BaaSServer.prototype.stop = function () {
  const self = this;
  const log = self._logger;
  const address = self._server.address();

  this._server.close(function() {
    log.debug(address, 'server closed');
    self.emit('close');
  });
};

module.exports = BaaSServer;
<commit_msg>fix memory leak<commit_after>const cluster = require('cluster');

const EventEmitter = require('events').EventEmitter;

const util   = require('util');
const logger = require('./lib/logger');
const _      = require('lodash');
const net = require('net');

const RequestDecoder = require('./messages/decoders').RequestDecoder;
const randomstring = require('randomstring');

const ResponseWriter = require('./lib/pipeline/response_writer');
const through2 = require('through2');
const Response       = require('./messages').Response;

const defaults = {
  port:      9485,
  hostname:  '0.0.0.0',
  logLevel: 'info',
  metrics: {
    gauge:     _.noop,
    increment: _.noop,
    histogram: _.noop,
    flush:     _.noop
  }
};

function fork_worker() {
  const worker = cluster.fork();

  worker._pendingRequests = new Map();

  worker.on('message', function (response) {
    var callback = worker._pendingRequests.get(response.request_id);
    worker._pendingRequests.delete(response.request_id);
    return callback(null, response);
  });

  worker.sendRequest = function (message, callback) {
    worker._pendingRequests.set(message.id, callback);
    worker.send(message);
  };

  return worker;
}

/*
 * Creates an instance of BaaSServer.
 *
 * Options:
 *
 *  - `port` the port to listen to. Defaults to 9231.
 *  - `hostname` the hostname to bind to. Defaults to INADDR_ANY
 *  - `logLevel` the verbosity of the logs. Defaults to 'info'.
 *
 */
function BaaSServer (options) {
  EventEmitter.call(this);
  const self = this;

  this._config = _.extend({}, defaults, options);
  this._logger = logger(this._config.logLevel);
  this._server = net.createServer(this._handler.bind(this));
  this._metrics = this._config.metrics;
  this._server.on('error', function (err) {
    self.emit('error', err);
  });

  cluster.setupMaster({
    exec: __dirname + '/worker.js'
  });

  const workers_number = typeof process.env.WORKERS === 'undefined' ||
                          process.env.WORKERS === 'AUTO' ?
                          Math.max(require('os').cpus().length - 1, 1) :
                          parseInt(process.env.WORKERS);

  this._workers = _.range(workers_number).map(fork_worker);

}

util.inherits(BaaSServer, EventEmitter);

BaaSServer.prototype._handler = function (socket) {
  const self = this;

  self._metrics.increment('connection.incoming');

  const sockets_details = _.pick(socket, ['remoteAddress', 'remotePort']);

  sockets_details.connection = socket._connection_id = randomstring.generate(5);

  const log = self._logger;

  socket.on('error', function (err) {
    self._metrics.increment('connection.error');
    log.info(_.extend(sockets_details, {
      err: {
        code:    err.code,
        message: err.message
      }
    }), 'connection error');
  }).on('close', function () {
    self._metrics.increment('connection.closed');
    log.debug(sockets_details, 'connection closed');
  });

  log.debug(sockets_details, 'connection accepted');

  const decoder = RequestDecoder();

  decoder.on('error', function () {
    log.info(sockets_details, 'unknown message format');
    return socket.end();
  });

  socket.pipe(decoder)
        .pipe(through2.obj((request, encoding, callback) => {
          const worker = self._workers.shift();
          const operation = request.operation === 0 ? 'compare' : 'hash';
          const start = new Date();

          if (!worker) {
            log.info({
              request:    request.id,
              connection: socket._connection_id,
              took:       new Date() - start,
              operation:  operation
            }, `${operation} not done - server is busy`);

            return  callback(null, new Response({
              request_id: request.id,
              success:    false,
              busy:       true
            }));
          }

          self._metrics.histogram(`requests.incoming.${operation}.time`, (new Date() - start));

          worker.sendRequest(request, (err, response) => {
            log.info({
              request:    request.id,
              connection: socket._connection_id,
              took:       new Date() - start,
              worker:     worker.id,
              operation:  operation
            }, `${operation} completed`);

            self._metrics.histogram(`requests.processed.${operation}.time`, (new Date() - start));
            self._metrics.increment(`requests.processed.${operation}`);
            self._workers.push(worker);
            callback(null, new Response(response));
          });

        }))
        .pipe(ResponseWriter())
        .pipe(socket);
};

BaaSServer.prototype.start = function (done) {
  const self = this;
  const log = self._logger;

  self._server.listen(this._config.port, this._config.hostname, function(err) {
    if (err) {
      log.error(err, 'error starting server');
      self.emit('error', err);
      if (done) {
        done(err);
      }
      return;
    }

    const address = self._server.address();

    log.info(address, 'server started');

    self.emit('started', address);
    if (done) {
      done(null, address);
    }
  });

  return this;
};

BaaSServer.prototype.stop = function () {
  const self = this;
  const log = self._logger;
  const address = self._server.address();

  this._server.close(function() {
    log.debug(address, 'server closed');
    self.emit('close');
  });
};

module.exports = BaaSServer;
<|endoftext|>


<commit_before>var express = require("express");
var app = express();
var http = require('http');
var server = http.createServer(app);
var io = require('socket.io').listen(server);

var players = {};
var green_plants = [];

var NUM_COLORS = 3;

app.use(express.static('public'));

app.get('/', function(req, res){
	res.sendFile('index.html', { root: __dirname });
});

io.on('connection', function(socket) {
	console.log('user connected (id '+socket.id+')');
	var color = (Math.round(Math.random()*(NUM_COLORS-1))+1);
	socket.emit('your-info', {id: socket.id, color: color});

	for (var id in players) {
		socket.emit('existing-player', {id: id, name: players[id].name, color: players[id].color, position: players[id].position});
	}

	for (var i = 0; i < green_plants.length; i++) {
		socket.emit('green-plant', {position: green_plants[i]});
	}

	players[socket.id] = {socket: socket, name: 'Guest', color: color, position: {x: 135, y: 135}};

	io.emit('new-player', {id: socket.id, name: 'Guest', color: color, position: {x: 135, y: 135}});
	socket.on('key', function(msg) {
		//console.log(socket.id + ' pressed ' + msg['dir']);
		players[socket.id].position = msg.position;
		io.emit('player-move', {id: socket.id, dir: msg['dir'], delta: msg['delta']});
	});

	socket.on('green-plant', function(msg) {
		io.emit('green-plant', {position: msg.position});
		green_plants.push(msg.position);
	});

	socket.on('username', function(msg) {
		players[socket.id].name = msg.name;
		io.emit('username', {id: socket.id, name: msg.name});
	});

	socket.on('disconnect', function() {
		console.log('user disconnected (id '+socket.id+')');
		io.emit('player-left', {id: socket.id});
		delete players[socket.id];
	});
});

function brownPlants() {
	//console.log("entered brown plants");
	var plant = green_plants.shift();

	if (plant) {
		io.emit('brown-plant', {position: plant});
	}
	setTimeout(brownPlants, (Math.random()*4000)+1000);
}

brownPlants();
server.listen((process.env.PORT || 8082));
console.log("Server listening!");<commit_msg>fixing<commit_after>var express = require("express");
var app = express();
var http = require('http');
var server = http.createServer(app);
var io = require('socket.io').listen(server);

var players = {};
var green_plants = [];

var NUM_COLORS = 3;

app.use(express.static('public'));

app.get('/', function(req, res){
	res.sendFile('index.html', { root: __dirname });
});

io.on('connection', function(socket) {
	console.log('user connected (id '+socket.id+')');
	var color = (Math.round(Math.random()*(NUM_COLORS-1))+1);
	socket.emit('your-info', {id: socket.id, color: color});

	for (var id in players) {
		socket.emit('existing-player', {id: id, name: players[id].name, color: players[id].color, position: players[id].position});
	}

	for (var i = 0; i < green_plants.length; i++) {
		socket.emit('green-plant', {position: green_plants[i]});
	}

	players[socket.id] = {socket: socket, name: 'Guest', color: color, position: {x: 135, y: 135}};

	io.emit('new-player', {id: socket.id, name: 'Guest', color: color, position: {x: 135, y: 135}});
	socket.on('key', function(msg) {
		//console.log(socket.id + ' pressed ' + msg['dir']);
		players[socket.id].position = msg.position;
		io.emit('player-move', {id: socket.id, dir: msg['dir'], delta: msg['delta']});
	});

	socket.on('green-plant', function(msg) {
		io.emit('green-plant', {position: msg.position});
		green_plants.push(msg.position);
	});

	socket.on('username', function(msg) {
		players[socket.id].name = msg.name;
		io.emit('username', {id: socket.id, name: msg.name});
	});

	socket.on('disconnect', function() {
		console.log('user disconnected (id '+socket.id+')');
		io.emit('player-left', {id: socket.id});
		delete players[socket.id];
	});
});

function brownPlants() {
	//console.log("entered brown plants");
	var plant = green_plants.shift();

	if (plant) {
		io.emit('brown-plant', {position: plant});
	}
	setTimeout(brownPlants, (Math.random()*4000)+1000);
}

brownPlants();
server.listen((process.env.PORT || 8082));
console.log("Server listening!");
<|endoftext|>


<commit_before>'use strict'

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

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

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

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

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

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

	var xhr = new XMLHttpRequest();
	xhr.onreadystatechange = function () {
	  var DONE = 4; // readyState 4 means the request is done.
	  var OK = 200; // status 200 is a successful return.
	  if (xhr.readyState === DONE) {
	    if (xhr.status === OK)
	      console.log(xhr.responseText); // 'This is the returned text.'
		  msg.say("RESPONSE: "+xhr.responseText);
	    } else {
	      console.log('Error: ' + xhr.status); // An error occurred during the request.
		  msg.say("Error: "+xhr.status);
	    }
	  }
	};
	xhr.open('GET', 'http://api.giphy.com/v1/gifs/random?api_key=dc6zaTOxFJmzC&tag=reaction');
	xhr.send(null);
	msg.say(HELP_TEXT)
})

// slapp.message('Robert', ['mention', 'direct_message'], (msg) => {
//   msg.say('What a dick!')
// })

// slapp.message('jens', ['mention', 'direct_message'], (msg) => {
//   msg.say('What a dick!')
// })

slapp.message(/^(Ralf|Jens|Robert|Frank|Isa|Jan|Daniel)/i, ['mention', 'direct_message'], (msg) => {
	// var text = (msg.body.event && msg.body.event.text) || '';

	msg.say([
      '🚀',
      '💩',
      ':+1: That\'s my man',
      'Best colleague :sun_with_face: :full_moon_with_face:'
    ])
})

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

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

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

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

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

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

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

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

// http://giphy.com/gifs/thread-appreciation-rappers-Mqz2DNuhWjFyU

// http://giphy.com/gifs/kpop-k-pop-wink-26mfytBsu0XC9bVss

// http://giphy.com/gifs/reactionseditor-reaction-l0IyjeA5mmMZjhyPm

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

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

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

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

  console.log(`Listening on port ${port}`)
})
<commit_msg>ajax fix 0<commit_after>'use strict'

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

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

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

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

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

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

	var xhr = new XMLHttpRequest();
	xhr.onreadystatechange = function () {
	  var DONE = 4; // readyState 4 means the request is done.
	  var OK = 200; // status 200 is a successful return.
	  if (xhr.readyState === DONE) {
	    if (xhr.status === OK)
	      console.log(xhr.responseText); // 'This is the returned text.'
		  msg.say("RESPONSE: "+xhr.responseText);
	    } else {
	      console.log('Error: ' + xhr.status); // An error occurred during the request.
		  msg.say("Error: "+xhr.status);
	    }
	  }
	}

	xhr.open('GET', 'http://api.giphy.com/v1/gifs/random?api_key=dc6zaTOxFJmzC&tag=reaction');
	xhr.send(null);
	msg.say(HELP_TEXT);
})

// slapp.message('Robert', ['mention', 'direct_message'], (msg) => {
//   msg.say('What a dick!')
// })

// slapp.message('jens', ['mention', 'direct_message'], (msg) => {
//   msg.say('What a dick!')
// })

slapp.message(/^(Ralf|Jens|Robert|Frank|Isa|Jan|Daniel)/i, ['mention', 'direct_message'], (msg) => {
	// var text = (msg.body.event && msg.body.event.text) || '';

	msg.say([
      '🚀',
      '💩',
      ':+1: That\'s my man',
      'Best colleague :sun_with_face: :full_moon_with_face:'
    ])
})

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

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

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

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

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

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

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

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

// http://giphy.com/gifs/thread-appreciation-rappers-Mqz2DNuhWjFyU

// http://giphy.com/gifs/kpop-k-pop-wink-26mfytBsu0XC9bVss

// http://giphy.com/gifs/reactionseditor-reaction-l0IyjeA5mmMZjhyPm

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

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

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

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

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


<commit_before>var assign = require('object-assign');
var clamp = require('math-clamp');
var domThrottle = require('dom-throttle');
var getStyleProperty = require('desandro-get-style-property');
var getBounding = require('./getBounding');
var getComputedStyleValue = require('./getComputedStyleValue');
var getScrollParents = require('./getScrollParents');
var expandPostitionOffsetOption = require('./expandPostitionOffsetOption');
var splitOption = require('./splitOption');

var TRANSFORM_PROP = getStyleProperty('transform');

var OPTIONS_DEFAULT = {
	from: ['center', 'center'],
	to: ['center', 'center'],
	collision: ['none', 'none'],
	within: null,
	window: window,
	gpu: true
};

module.exports = function cling (fromEl, toEl, options) {
	// Normalize options
	options = assign({}, OPTIONS_DEFAULT, options);
	var fromOption = splitOption(options.from).map(expandPostitionOffsetOption);
	var toOption = splitOption(options.to).map(expandPostitionOffsetOption);
	var collisionOption = splitOption(options.collision);
	var within = options.within;
	var useTransform = options.gpu && TRANSFORM_PROP;

	// Window to bind events to
	var window = options.window;

	// To prevent multiply destroys
	var destroyed = false;

	// Cached fromEl top and left position styles
	var fromElPositionCache = { left: 0, top: 0 };

	// Get any scrollable parents of the toEl for listening to scroll events
	var scrollParents = getScrollParents(toEl);

	// Add `position: absolute;` style, unless already `position: fixed;`
	if (getComputedStyleValue(fromEl, 'position') !== 'fixed') {
		fromEl.style.position = 'absolute';
	}

	// Apply initial positioning styles
	assign(fromEl.style, {
		left: 0,
		top: 0,
		right: 'auto',
		bottom: 'auto'
	});

	var destroy = function () {
		// Destroy can only happen once
		if (destroyed) return false;
		destroyed = true;

		// Cancel any queued positionings
		position.cancel();

		// Reset styles
		assign(fromEl.style, {
			position: '',
			left: '',
			top: '',
			right: '',
			bottom: ''
		});

		// Unbind events
		window.removeEventListener('load', position, false);
		window.removeEventListener('scroll', position, false);
		window.removeEventListener('resize', position, false);
		window.removeEventListener('touchmove', position, false);

		if (scrollParents.length) {
			scrollParents.forEach(function (el) {
				el.removeEventListener('scroll', position, false);
			})
		}

		return true;
	};

	var position = domThrottle(function () {
		var fromElBounding = getBounding(fromEl);
		var toElBounding = getBounding(toEl);
		var withinBounding;

		if (within) {
			withinBounding = getBounding(within);
		}

		var newPositions = [
			{ axis: 'left', size: 'width' },
			{ axis: 'top', size: 'height' }
		].reduce(function (newPositions, o, i) {
			var axis = o.axis;
			var size = o.size;

			// Dat Math
			// 1. The toEl point
			// 2. Subtract the fromEl point
			// 3. Add the difference between the toEl and fromEl's current position
			// 4. Add our offset
			// 5. Add the current left/top style
			var newPosition =
				(toElBounding[size] * fromOption[i].position) - // 1
				(fromElBounding[size] * toOption[i].position) + // 2
				(toElBounding[axis] - fromElBounding[axis]) + // 3
				fromOption[i].offset + toOption[i].offset // 4
				fromElPositionCache[axis]; // 5

			// Optionally fit inside within element
			if (within && collisionOption[i] === 'fit') {
				newPosition = clamp(
					newPosition,
					withinBounding[axis],
					withinBounding[axis] + withinBounding[size] - fromElBounding[size]
				);
			}

			// Set and cache the newly calculated position.
			// Round the values to prevent sub-pixel issues.
			newPosition = fromElPositionCache[axis] = Math.round(newPosition);

			// Append 'px' for styles
			newPositions[axis] = newPosition + 'px';
			return newPositions;
		}, {});

		// Apply the positions
		if (useTransform) {
			fromEl.style[TRANSFORM_PROP] = 'translateX(' + newPositions.left + ') translateY(' + newPositions.top + ') translateZ(0)';
		} else {
			assign(fromEl.style, newPositions);
		}
	});

	// Listen to load, scroll or resize on window
	window.addEventListener('load', position, false);
	window.addEventListener('scroll', position, false);
	window.addEventListener('resize', position, false);
	window.addEventListener('touchmove', position, false);

	// Listen to scroll on scrollable parents
	if (scrollParents.length) {
		scrollParents.forEach(function (el) {
			el.addEventListener('scroll', position, false);
		})
	}

	// Initial positioning
	position();

	return {
		destroy: destroy,
		forceUpdate: position,
		isDestroyed: function () { return destroyed; }
	};
};
<commit_msg>Add missing stray +<commit_after>var assign = require('object-assign');
var clamp = require('math-clamp');
var domThrottle = require('dom-throttle');
var getStyleProperty = require('desandro-get-style-property');
var getBounding = require('./getBounding');
var getComputedStyleValue = require('./getComputedStyleValue');
var getScrollParents = require('./getScrollParents');
var expandPostitionOffsetOption = require('./expandPostitionOffsetOption');
var splitOption = require('./splitOption');

var TRANSFORM_PROP = getStyleProperty('transform');

var OPTIONS_DEFAULT = {
	from: ['center', 'center'],
	to: ['center', 'center'],
	collision: ['none', 'none'],
	within: null,
	window: window,
	gpu: true
};

module.exports = function cling (fromEl, toEl, options) {
	// Normalize options
	options = assign({}, OPTIONS_DEFAULT, options);
	var fromOption = splitOption(options.from).map(expandPostitionOffsetOption);
	var toOption = splitOption(options.to).map(expandPostitionOffsetOption);
	var collisionOption = splitOption(options.collision);
	var within = options.within;
	var useTransform = options.gpu && TRANSFORM_PROP;

	// Window to bind events to
	var window = options.window;

	// To prevent multiply destroys
	var destroyed = false;

	// Cached fromEl top and left position styles
	var fromElPositionCache = { left: 0, top: 0 };

	// Get any scrollable parents of the toEl for listening to scroll events
	var scrollParents = getScrollParents(toEl);

	// Add `position: absolute;` style, unless already `position: fixed;`
	if (getComputedStyleValue(fromEl, 'position') !== 'fixed') {
		fromEl.style.position = 'absolute';
	}

	// Apply initial positioning styles
	assign(fromEl.style, {
		left: 0,
		top: 0,
		right: 'auto',
		bottom: 'auto'
	});

	var destroy = function () {
		// Destroy can only happen once
		if (destroyed) return false;
		destroyed = true;

		// Cancel any queued positionings
		position.cancel();

		// Reset styles
		assign(fromEl.style, {
			position: '',
			left: '',
			top: '',
			right: '',
			bottom: ''
		});

		// Unbind events
		window.removeEventListener('load', position, false);
		window.removeEventListener('scroll', position, false);
		window.removeEventListener('resize', position, false);
		window.removeEventListener('touchmove', position, false);

		if (scrollParents.length) {
			scrollParents.forEach(function (el) {
				el.removeEventListener('scroll', position, false);
			})
		}

		return true;
	};

	var position = domThrottle(function () {
		var fromElBounding = getBounding(fromEl);
		var toElBounding = getBounding(toEl);
		var withinBounding;

		if (within) {
			withinBounding = getBounding(within);
		}

		var newPositions = [
			{ axis: 'left', size: 'width' },
			{ axis: 'top', size: 'height' }
		].reduce(function (newPositions, o, i) {
			var axis = o.axis;
			var size = o.size;

			// Dat Math
			// 1. The toEl point
			// 2. Subtract the fromEl point
			// 3. Add the difference between the toEl and fromEl's current position
			// 4. Add our offset
			// 5. Add the current left/top style
			var newPosition =
				(toElBounding[size] * fromOption[i].position) - // 1
				(fromElBounding[size] * toOption[i].position) + // 2
				(toElBounding[axis] - fromElBounding[axis]) + // 3
				fromOption[i].offset + toOption[i].offset + // 4
				fromElPositionCache[axis]; // 5

			// Optionally fit inside within element
			if (within && collisionOption[i] === 'fit') {
				newPosition = clamp(
					newPosition,
					withinBounding[axis],
					withinBounding[axis] + withinBounding[size] - fromElBounding[size]
				);
			}

			// Set and cache the newly calculated position.
			// Round the values to prevent sub-pixel issues.
			newPosition = fromElPositionCache[axis] = Math.round(newPosition);

			// Append 'px' for styles
			newPositions[axis] = newPosition + 'px';
			return newPositions;
		}, {});

		// Apply the positions
		if (useTransform) {
			fromEl.style[TRANSFORM_PROP] = 'translateX(' + newPositions.left + ') translateY(' + newPositions.top + ') translateZ(0)';
		} else {
			assign(fromEl.style, newPositions);
		}
	});

	// Listen to load, scroll or resize on window
	window.addEventListener('load', position, false);
	window.addEventListener('scroll', position, false);
	window.addEventListener('resize', position, false);
	window.addEventListener('touchmove', position, false);

	// Listen to scroll on scrollable parents
	if (scrollParents.length) {
		scrollParents.forEach(function (el) {
			el.addEventListener('scroll', position, false);
		})
	}

	// Initial positioning
	position();

	return {
		destroy: destroy,
		forceUpdate: position,
		isDestroyed: function () { return destroyed; }
	};
};
<|endoftext|>