<commit_before>'use strict';

const phoneFormatter = require('phone-formatter');
const config = require('../config/config');

/**
 * Verifies new webhook when setting up Messenger app
 *
 * @param req
 * @param res
 */
function verify(req, res) {
    console.log("Receiving webhook verification from FB.");
    var verifyToken = config.facebookVerifyToken;
    if (req.query['hub.verify_token'] === verifyToken) {
        res.send(req.query['hub.challenge']);
    } else {
      res.send('Error, wrong token');
    };
}

/**
 * Makes array of generic request objects from incoming context
 *
 * @param context
 * @return {genericRequests}
 */
function translateRequestToGenericFormats(context) {
  var genericRequests = [];
  // iterate over messaging events - FBM uses batch processing
  var messaging_events = context.userRequest.entry[0].messaging;
  for (let i = 0; i < messaging_events.length; i++) {
    let singleGenericRequest = {
      reqType: '',
      userInput: '',
      context: context
    };
    var event = context.userRequest.entry[0].messaging[i];
    if (event.message && event.message.text) {
      console.log("User input Post detected from FB");
      var userInput = event.message.text;

      if ((userInput === 'help') || (userInput === 'bot help')) {
        singleGenericRequest.userInput = userInput;
        singleGenericRequest.reqType = 'help';
      }
      else if (userInput.slice(0, 4) === 'bot ') {
        singleGenericRequest.userInput = userInput.slice(4);
        singleGenericRequest.reqType = 'user-input';
      }
      else {
        singleGenericRequest.userInput = userInput;
        singleGenericRequest.reqType = 'ignore';
      };
    } else if (event.postback) {
      console.log("Postback Post detected from FB");
    // Later: determine if this is triggering a new search, or displaying more Companies - right now just triggers new search
      singleGenericRequest.userInput = event.postback.payload;
      singleGenericRequest.reqType = 'postback';
    } else {
      console.log("Non-text-input Post detected from FB");
      singleGenericRequest.reqType = 'ignore';
    };
    genericRequests.push(singleGenericRequest);
  }
  return genericRequests;
}

/**
 * Takes generic response data and structures payloads for Messenger sending
 *
 * @param genericResponse
 * @return {payloads}
 */
function generateResponsePayloads(genericResponse) {
  // if a False object passed in, pass through false
  if (!genericResponse) {
    return false;
  };

  console.log("About to begin generating payloads from genericResponse.");
  var payloads = [];
  var token = config.facebookAccessToken;
  var url = 'https://graph.facebook.com/v2.6/me/messages';
  var sender = genericResponse.context.userRequest.entry[0].messaging[0].sender.id;
  // var userInput = genericResponse.userInput;
  var type = genericResponse.type;

  // Case: nothing returned from Companies search / junk input
  if (type === 'nothing-found') {
    console.log('No Company Results flag detected in genericResponse.');
    let elements = loadNothingFoundElements();
    payloads.push(makePayload(token, url, sender, elements));
  } else if (type === 'help') {
    // this should be solved by a separate Action Handler
    console.log('Help flag detected in genericResponse.');
    let elements = loadHelpElements();
    payloads.push(makePayload(token, url, sender, elements));
  } else if (type === 'standard') {
    // Can we refactor this to compress into another function?
    console.log('Standard type flag detected in genericResponse.');
    var name = genericResponse.data.name || '';
    var posts = genericResponse.data.posts || [];
    var contactMethods = genericResponse.data.contactMethods || [];
    var otherCompanies = genericResponse.data.otherCompanies || [];
    var elements = [];

    // load Payload cards for Posts
    if (posts && posts.length) {
      var postElements = loadPostElements(posts, name);
      elements = elements.concat(postElements);
    }

    // load Contact Methods card to Payload
    if (contactMethods) {
      var contactMethodsElements = loadContactMethodsElements(contactMethods, name);
      // only push in if at least one button exists:
      if (contactMethodsElements[0].subtitle || contactMethodsElements[0].buttons.length) {
          elements = elements.concat(contactMethodsElements);
      };
    }

    // make Other Companies Card
    if (otherCompanies && otherCompanies.length) {
      var otherCompaniesElements = loadOtherCompaniesElements(otherCompanies, name);
      elements = elements.concat(otherCompaniesElements);
    }

    // if no other payload loaded up, send a Nothing-Found reponse
    if (!elements.length) {
      let nothingFoundElements = loadNothingFoundElements();
      elements = elements.concat(nothingFoundElements);
    }

    payloads.push(makePayload(token, url, sender, elements));
  }
  console.log('Payloads prepared by Messenger bot: ' + JSON.stringify(payloads));
  return payloads;
}

/**
 * Loads response elements for Case: nothing found
 *
 * @param userInput
 * @return {elements}
 */
function loadNothingFoundElements() {
  return [{
      "title": "I didn\’t understand.",
      "subtitle": 'Please start by telling me the company name. (ex: \'bot verizon\')',
      "buttons": [{
          "type": "web_url",
          "url": "https://gethuman.com",
          "title": "Go to GetHuman"
      }],
  }];
}

/**
 * Loads response elements for Case: Help input
 *
 * @return {elements}
 */
function loadHelpElements() {
  return [{
      "title": "It sounds like you need help.",
      "subtitle": 'Just tell me the name of the company you need to reach.',
      "buttons": [{
          "type": "web_url",
          "url": "https://gethuman.com",
          "title": "Go to GetHuman"
      }],
  }];
}

/**
 * Loads response elements for Posts cards
 *
 * @param posts
 * @param name
 * @return {postElements}
 */
function loadPostElements(posts, name) {
  var postElements = [];
  for (let i = 0; i < posts.length; i++) {
    let title = posts[i].title || '';
    let urlId = posts[i].urlId || '';
    let singleElement = {
        "title": title,
        "subtitle": '#' + (i+1) + ' most common ' + name + ' issue',
        "buttons": [{
            "type": "web_url",
            "url": "https://gethuman.com?company=" + encodeURIComponent(name),
            "title": "Fix this issue for me"
        },
        {
            "type": "web_url",
            "url": "https://answers.gethuman.co/_" + encodeURIComponent(urlId),
            "title": "More info ..."
        }],
    };
    postElements.push(singleElement);
  }
  return postElements;
};

/**
 * Loads response elements for Contact Methods cards
 *
 * @param contactMethods
 * @param name
 * @return {contactMethodsElements}
 */
function loadContactMethodsElements(contactMethods, name) {
  var contactMethodsElements = [{
      title: 'Best ways to contact ' + name + ':',
      buttons: formatContactButtons(contactMethods)
  }];
  if (contactMethods.email) {
      contactMethodsElements[0].subtitle = contactMethods.email;
  };
  return contactMethodsElements;
};

/**
 * Loads response elements for Other Companies cards
 *
 * @param otherCompanies
 * @param name
 * @return {otherCompaniesElements}
 */
function loadOtherCompaniesElements(otherCompanies, name) {
  var otherCompaniesElements = [{
      "title": "Were you trying to reach " + name + "?",
      "subtitle": "Perhaps you would like to ask me about this company:",
      "buttons": []
  }];
  var altCompany = otherCompanies[0];
  otherCompaniesElements[0].buttons.push({
      "type": "postback",
      "title": altCompany,
      "payload": altCompany
  });
  otherCompaniesElements[0].buttons.push({
      "type": "web_url",
      "url": "https://gethuman.com/",
      "title": "Something else"
  });
  return otherCompaniesElements;
};

/**
 * Takes contact methods, formats associated buttons for Messenger card
 *
 * @param contactMethods
 * @return {buttons}
 */
function formatContactButtons(contactMethods) {
    var buttons = [];
    var counter = 1;
    for(var key in contactMethods) {
        if ((counter <= 2) && (contactMethods[key])) {
            var button = {};
            switch(key) {
                case 'twitter':
                    button = {
                        "type": "web_url",
                        "url": 'https://twitter.com/' + contactMethods[key],
                        "title": "Twitter"
                    };
                    break;
                case 'web':
                    button = {
                        "type": "web_url",
                        "url": contactMethods[key],
                        "title": "Web"
                    };
                    break;
                case 'chat':
                    button = {
                        "type": "web_url",
                        "url": contactMethods[key],
                        "title": "Chat"
                    };
                    break;
                case 'facebook':
                    button = {
                        "type": "web_url",
                        "url": contactMethods[key],
                        "title": "Facebook"
                    };
                    break;
                case 'phone':
                    button = {
                        "type": "phone_number",
                        "payload": phoneFormatter.format(contactMethods[key], "+1NNNNNNNNNN"),
                        "title": contactMethods[key]
                    };
                    break;
                case 'email':
                    console.log("Email detected, not creating button for it because Messenger won't let us.");
                    break;
                default:
                    console.log("Something went wrong in Facebook contact button formatting");
            }
            if (button.type) {
                buttons.push(button);
                counter += 1;
            }
        }
    }
    console.log("Buttons formatted from contact methods: " + JSON.stringify(buttons));
    return buttons;
}

/**
 * Forms payload for sending to Messenger
 *
 * @param token
 * @param url
 * @param sender
 * @param elements
 * @return {payload}
 */
function makePayload(token, url, sender, elements) {
  return {
    url: url,
    qs: {access_token: token},
    method: 'POST',
    json: {
        recipient: {id: sender},
        message: {
            "attachment": {
                "type": "template",
                "payload": {
                    "template_type": "generic",
                    "elements": elements
                }
            }
        },
    }
  };
};

module.exports = {
  verify: verify,
  translateRequestToGenericFormats: translateRequestToGenericFormats,
  generateResponsePayloads: generateResponsePayloads,
  loadOtherCompaniesElements: loadOtherCompaniesElements,
  loadContactMethodsElements: loadContactMethodsElements,
  loadPostElements: loadPostElements,
  loadNothingFoundElements: loadNothingFoundElements,
  formatContactButtons: formatContactButtons,
  makePayload: makePayload
};<commit_msg>debug<commit_after>'use strict';

const phoneFormatter = require('phone-formatter');
const config = require('../config/config');

/**
 * Verifies new webhook when setting up Messenger app
 *
 * @param req
 * @param res
 */
function verify(req, res) {
    console.log("Receiving webhook verification from FB.");
    var verifyToken = config.facebookVerifyToken;
    if (req.query['hub.verify_token'] === verifyToken) {
        res.send(req.query['hub.challenge']);
    } else {
      res.send('Error, wrong token');
    };
}

/**
 * Makes array of generic request objects from incoming context
 *
 * @param context
 * @return {genericRequests}
 */
function translateRequestToGenericFormats(context) {
  var genericRequests = [];
  // iterate over messaging events - FBM uses batch processing
  var messaging_events = context.userRequest.entry[0].messaging;
  for (let i = 0; i < messaging_events.length; i++) {
    let singleGenericRequest = {
      reqType: '',
      userInput: '',
      context: context
    };
    var event = context.userRequest.entry[0].messaging[i];
    if (event.message && event.message.text) {
      console.log("User input Post detected from FB");
      var userInput = event.message.text;

      if ((userInput === 'help') || (userInput === 'bot help')) {
        singleGenericRequest.userInput = userInput;
        singleGenericRequest.reqType = 'help';
      }
      else if (userInput.slice(0, 4) === 'bot ') {
        singleGenericRequest.userInput = userInput.slice(4);
        singleGenericRequest.reqType = 'user-input';
      }
      else {
        singleGenericRequest.userInput = userInput;
        singleGenericRequest.reqType = 'ignore';
      };
    } else if (event.postback) {
      console.log("Postback Post detected from FB");
    // Later: determine if this is triggering a new search, or displaying more Companies - right now just triggers new search
      singleGenericRequest.userInput = event.postback.payload;
      singleGenericRequest.reqType = 'postback';
    } else {
      console.log("Non-text-input Post detected from FB");
      singleGenericRequest.reqType = 'ignore';
    };
    genericRequests.push(singleGenericRequest);
  }
  return genericRequests;
}

/**
 * Takes generic response data and structures payloads for Messenger sending
 *
 * @param genericResponse
 * @return {payloads}
 */
function generateResponsePayloads(genericResponse) {
  // if a False object passed in, pass through false
  if (!genericResponse) {
    return false;
  };

  console.log("About to begin generating payloads from genericResponse.");
  var payloads = [];
  var token = config.facebookAccessToken;
  var url = 'https://graph.facebook.com/v2.6/me/messages';
  var sender = genericResponse.context.userRequest.entry[0].messaging[0].sender.id;
  // var userInput = genericResponse.userInput;
  var type = genericResponse.type;

  // Case: nothing returned from Companies search / junk input
  if (type === 'nothing-found') {
    console.log('No Company Results flag detected in genericResponse.');
    let elements = loadNothingFoundElements();
    payloads.push(makePayload(token, url, sender, elements));
  } else if (type === 'help') {
    // this should be solved by a separate Action Handler
    console.log('Help flag detected in genericResponse.');
    let elements = loadHelpElements();
    payloads.push(makePayload(token, url, sender, elements));
  } else if (type === 'standard') {
    // Can we refactor this to compress into another function?
    console.log('Standard type flag detected in genericResponse.');
    var name = genericResponse.data.name || '';
    var posts = genericResponse.data.posts || [];
    var contactMethods = genericResponse.data.contactMethods || [];
    var otherCompanies = genericResponse.data.otherCompanies || [];
    var elements = [];

    // load Payload cards for Posts
    if (posts && posts.length) {
      var postElements = loadPostElements(posts, name);
      elements = elements.concat(postElements);
    }

    // load Contact Methods card to Payload
    if (contactMethods) {
      var contactMethodsElements = loadContactMethodsElements(contactMethods, name);
      // only push in if at least one button exists:
      if (contactMethodsElements[0].subtitle || contactMethodsElements[0].buttons.length) {
          elements = elements.concat(contactMethodsElements);
      };
    }

    // make Other Companies Card
    if (otherCompanies && otherCompanies.length) {
      var otherCompaniesElements = loadOtherCompaniesElements(otherCompanies, name);
      elements = elements.concat(otherCompaniesElements);
    }

    // if no other payload loaded up, send a Nothing-Found reponse
    if (!elements.length) {
      let nothingFoundElements = loadNothingFoundElements();
      elements = elements.concat(nothingFoundElements);
    }

    payloads.push(makePayload(token, url, sender, elements));
  }
  console.log('Payloads prepared by Messenger bot: ' + JSON.stringify(payloads));
  return payloads;
}

/**
 * Loads response elements for Case: nothing found
 *
 * @param userInput
 * @return {elements}
 */
function loadNothingFoundElements() {
  return [{
      "title": "I didn\’t understand.",
      "subtitle": 'Please start by telling me the company name. (ex: \'bot verizon\')',
      "buttons": [{
          "type": "web_url",
          "url": "https://gethuman.com",
          "title": "Go to GetHuman"
      }],
  }];
}

/**
 * Loads response elements for Case: Help input
 *
 * @return {elements}
 */
function loadHelpElements() {
  return [{
      "title": "It sounds like you need help.",
      "subtitle": 'Start by saying \'bot\', followed by the company name. (ex: \'bot verizon\')',
      "buttons": [{
          "type": "web_url",
          "url": "https://gethuman.com",
          "title": "Go to GetHuman"
      }],
  }];
}

/**
 * Loads response elements for Posts cards
 *
 * @param posts
 * @param name
 * @return {postElements}
 */
function loadPostElements(posts, name) {
  var postElements = [];
  for (let i = 0; i < posts.length; i++) {
    let title = posts[i].title || '';
    let urlId = posts[i].urlId || '';
    let singleElement = {
        "title": title,
        "subtitle": '#' + (i+1) + ' most common ' + name + ' issue',
        "buttons": [{
            "type": "web_url",
            "url": "https://gethuman.com?company=" + encodeURIComponent(name),
            "title": "Fix this issue for me"
        },
        {
            "type": "web_url",
            "url": "https://answers.gethuman.co/_" + encodeURIComponent(urlId),
            "title": "More info ..."
        }],
    };
    postElements.push(singleElement);
  }
  return postElements;
};

/**
 * Loads response elements for Contact Methods cards
 *
 * @param contactMethods
 * @param name
 * @return {contactMethodsElements}
 */
function loadContactMethodsElements(contactMethods, name) {
  var contactMethodsElements = [{
      title: 'Best ways to contact ' + name + ':',
      buttons: formatContactButtons(contactMethods)
  }];
  if (contactMethods.email) {
      contactMethodsElements[0].subtitle = contactMethods.email;
  };
  return contactMethodsElements;
};

/**
 * Loads response elements for Other Companies cards
 *
 * @param otherCompanies
 * @param name
 * @return {otherCompaniesElements}
 */
function loadOtherCompaniesElements(otherCompanies, name) {
  var otherCompaniesElements = [{
      "title": "Were you trying to reach " + name + "?",
      "subtitle": "Perhaps you would like to ask me about this company:",
      "buttons": []
  }];
  var altCompany = otherCompanies[0];
  otherCompaniesElements[0].buttons.push({
      "type": "postback",
      "title": altCompany,
      "payload": altCompany
  });
  otherCompaniesElements[0].buttons.push({
      "type": "web_url",
      "url": "https://gethuman.com/",
      "title": "Something else"
  });
  return otherCompaniesElements;
};

/**
 * Takes contact methods, formats associated buttons for Messenger card
 *
 * @param contactMethods
 * @return {buttons}
 */
function formatContactButtons(contactMethods) {
    var buttons = [];
    var counter = 1;
    for(var key in contactMethods) {
        if ((counter <= 2) && (contactMethods[key])) {
            var button = {};
            switch(key) {
                case 'twitter':
                    button = {
                        "type": "web_url",
                        "url": 'https://twitter.com/' + contactMethods[key],
                        "title": "Twitter"
                    };
                    break;
                case 'web':
                    button = {
                        "type": "web_url",
                        "url": contactMethods[key],
                        "title": "Web"
                    };
                    break;
                case 'chat':
                    button = {
                        "type": "web_url",
                        "url": contactMethods[key],
                        "title": "Chat"
                    };
                    break;
                case 'facebook':
                    button = {
                        "type": "web_url",
                        "url": contactMethods[key],
                        "title": "Facebook"
                    };
                    break;
                case 'phone':
                    button = {
                        "type": "phone_number",
                        "payload": phoneFormatter.format(contactMethods[key], "+1NNNNNNNNNN"),
                        "title": contactMethods[key]
                    };
                    break;
                case 'email':
                    console.log("Email detected, not creating button for it because Messenger won't let us.");
                    break;
                default:
                    console.log("Something went wrong in Facebook contact button formatting");
            }
            if (button.type) {
                buttons.push(button);
                counter += 1;
            }
        }
    }
    console.log("Buttons formatted from contact methods: " + JSON.stringify(buttons));
    return buttons;
}

/**
 * Forms payload for sending to Messenger
 *
 * @param token
 * @param url
 * @param sender
 * @param elements
 * @return {payload}
 */
function makePayload(token, url, sender, elements) {
  return {
    url: url,
    qs: {access_token: token},
    method: 'POST',
    json: {
        recipient: {id: sender},
        message: {
            "attachment": {
                "type": "template",
                "payload": {
                    "template_type": "generic",
                    "elements": elements
                }
            }
        },
    }
  };
};

module.exports = {
  verify: verify,
  translateRequestToGenericFormats: translateRequestToGenericFormats,
  generateResponsePayloads: generateResponsePayloads,
  loadOtherCompaniesElements: loadOtherCompaniesElements,
  loadContactMethodsElements: loadContactMethodsElements,
  loadPostElements: loadPostElements,
  loadNothingFoundElements: loadNothingFoundElements,
  formatContactButtons: formatContactButtons,
  makePayload: makePayload
};<|endoftext|>


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

import stream from 'stream'
import mime from 'mime-types'

import _ from 'lodash'

// All characters in string which are NOT unreserved should be percent encoded.
// Unreserved characers are : ALPHA / DIGIT / "-" / "." / "_" / "~"
// Reference https://tools.ietf.org/html/rfc3986#section-2.2
export function uriEscape(string) {
  return string.split('').reduce((acc, elem) => {
    let buf = new Buffer(elem)
    if (buf.length === 1) {
      // length 1 indicates that elem is not a unicode character.
      // Check if it is an unreserved characer.
      if ('A' <= elem && elem <= 'Z' ||
          'a' <= elem && elem <= 'z' ||
          '0' <= elem && elem <= '9' ||
          elem === '_' ||
          elem === '.' ||
          elem === '~' ||
          elem === '-')
      {
        // Unreserved characer should not be encoded.
        acc = acc + elem
        return acc
      }
    }
    // elem needs encoding - i.e elem should be encoded if it's not unreserved
    // character or if it's a unicode character.
    for (var i = 0; i < buf.length; i++) {
      acc = acc + "%" + buf[i].toString(16).toUpperCase()
    }
    return acc
  }, '')
}

export function uriResourceEscape(string) {
  return uriEscape(string).replace(/%2F/g, '/')
}

export function getScope(region, date) {
  return `${date.format('YYYYMMDD')}/${region}/s3/aws4_request`
}

// isAmazonEndpoint - true if endpoint is 's3.amazonaws.com' or 's3.cn-north-1.amazonaws.com.cn'
export function isAmazonEndpoint(endpoint) {
  return endpoint === 's3.amazonaws.com' || endpoint === 's3.cn-north-1.amazonaws.com.cn'
}

// isVirtualHostStyle - verify if bucket name is support with virtual
// hosts. bucketNames with periods should be always treated as path
// style if the protocol is 'https:', this is due to SSL wildcard
// limitation. For all other buckets and Amazon S3 endpoint we will
// default to virtual host style.
export function isVirtualHostStyle(endpoint, protocol, bucket) {
  if (protocol === 'https:' && bucket.indexOf('.') > -1) {
    return false
  }
  return isAmazonEndpoint(endpoint)
}

var ipv4Regex = /^(\d{1,3}\.){3,3}\d{1,3}$/;

export function isValidIP(ip) {
  return ipv4Regex.test(ip)
}

// isValidEndpoint - true if endpoint is valid domain.
export function isValidEndpoint(endpoint) {
  if (!isValidDomain(endpoint) && !isValidIP(endpoint)) {
    return false
  }
  // Endpoint matches amazon, make sure its 's3.amazonaws.com'
  if (endpoint.match('.amazonaws.com$') || endpoint.match('.amazonaws.com.cn$')) {
    if (!isAmazonEndpoint(endpoint)) {
      return false
    }
  }
  // Return true.
  return true
}

// isValidDomain - true if input host is a valid domain.
export function isValidDomain(host) {
  if (!isString(host)) return false
  // See RFC 1035, RFC 3696.
  if (host.length === 0 || host.length > 255) {
    return false
  }
  // Host cannot start or end with a '-'
  if (host[0] === '-' || host.substr(-1) === '-') {
    return false
  }
  // Host cannot start or end with a '_'
  if (host[0] === '_' || host.substr(-1) === '_') {
    return false
  }
  // Host cannot start or end with a '.'
  if (host[0] === '.' || host.substr(-1) === '.') {
    return false
  }
  var alphaNumerics = '`~!@#$%^&*()+={}[]|\\\"\';:><?/'.split('')
  // All non alphanumeric characters are invalid.
  for (var i in alphaNumerics) {
    if (host.indexOf(alphaNumerics[i]) > -1) {
      return false
    }
  }
  // No need to regexp match, since the list is non-exhaustive.
  // We let it be valid and fail later.
  return true
}

// Probes contentType using file extensions.
// For example: probeContentType('file.png') returns 'image/png'.
export function probeContentType(path) {
  if (!mime.lookup(path)) {
    contentType = 'application/octet-stream'
  } else {
    contentType = mime.lookup(filePath)
  }
  return contentType
}

// isValidPort - is input port valid.
export function isValidPort(port) {
  // verify if port is a number.
  if (!isNumber(port)) return false
  // port cannot be negative.
  if (port < 0) return false
  // port '0' is valid and special case return true.
  if (port === 0) return true
  var min_port = 1;
  var max_port = 65535;
  // Verify if port is in range.
  return port >= min_port && port <= max_port
}

export function isValidBucketName(bucket) {
  if (!isString(bucket)) return false

  // bucket length should be less than and no more than 63
  // characters long.
  if (bucket.length < 3 || bucket.length > 63) {
    return false
  }
  // bucket with successive periods is invalid.
  if (bucket.indexOf('..') > -1) {
    return false
  }
  // bucket cannot have ip address style.
  if (bucket.match(/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/)) {
    return false
  }
  // bucket should begin with alphabet/number and end with alphabet/number,
  // with alphabet/number/.- in the middle.
  if (bucket.match(/^[a-z0-9][a-z0-9.-]+[a-z0-9]$/)) {
    return true
  }
  return false
}

// check if objectName is a valid object name
export function isValidObjectName(objectName) {
  if (!isValidPrefix(objectName)) return false
  if (objectName.length === 0) return false
  return true
}

// check if prefix is valid
export function isValidPrefix(prefix) {
  if (!isString(prefix)) return false
  if (prefix.length > 1024) return false
  return true
}

// check if typeof arg number
export function isNumber(arg) {
  return typeof(arg) === 'number'
}

// check if typeof arg function
export function isFunction(arg) {
  return typeof(arg) === 'function';
}

// check if typeof arg string
export function isString(arg) {
  return typeof(arg) === 'string';
}

// check if typeof arg object
export function isObject(arg) {
  return typeof(arg) === 'object' && arg !== null;
}

// check if object is readable stream
export function isReadableStream(arg) {
  return isObject(arg) && isFunction(arg._read)
}

// check if arg is boolean
export function isBoolean(arg) {
  return typeof(arg) === 'boolean'
}

// check if arg is array
export function isArray(arg) {
  return Array.isArray(arg)
}

// check if arg is Date
export function isDate(arg) {
  return arg._isAMomentObject
}

// pipesetup sets up pipe() from left to right os streams array
// pipesetup will also make sure that error emitted at any of the upstream Stream
// will be emitted at the last stream. This makes error handling simple
export function pipesetup(...streams) {
  return streams.reduce((src, dst) => {
    src.on('error', err => dst.emit('error', err))
    return src.pipe(dst)
  })
}

// return a Readable stream that emits data
export function readableStream(data) {
  var s = new stream.Readable()
  s._read = () => {}
  s.push(data)
  s.push(null)
  return s
}
<commit_msg>contentType variable was not declared. (#543)<commit_after>/*
 * Minio Javascript Library for Amazon S3 Compatible Cloud Storage, (C) 2015 Minio, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import stream from 'stream'
import mime from 'mime-types'

import _ from 'lodash'

// All characters in string which are NOT unreserved should be percent encoded.
// Unreserved characers are : ALPHA / DIGIT / "-" / "." / "_" / "~"
// Reference https://tools.ietf.org/html/rfc3986#section-2.2
export function uriEscape(string) {
  return string.split('').reduce((acc, elem) => {
    let buf = new Buffer(elem)
    if (buf.length === 1) {
      // length 1 indicates that elem is not a unicode character.
      // Check if it is an unreserved characer.
      if ('A' <= elem && elem <= 'Z' ||
          'a' <= elem && elem <= 'z' ||
          '0' <= elem && elem <= '9' ||
          elem === '_' ||
          elem === '.' ||
          elem === '~' ||
          elem === '-')
      {
        // Unreserved characer should not be encoded.
        acc = acc + elem
        return acc
      }
    }
    // elem needs encoding - i.e elem should be encoded if it's not unreserved
    // character or if it's a unicode character.
    for (var i = 0; i < buf.length; i++) {
      acc = acc + "%" + buf[i].toString(16).toUpperCase()
    }
    return acc
  }, '')
}

export function uriResourceEscape(string) {
  return uriEscape(string).replace(/%2F/g, '/')
}

export function getScope(region, date) {
  return `${date.format('YYYYMMDD')}/${region}/s3/aws4_request`
}

// isAmazonEndpoint - true if endpoint is 's3.amazonaws.com' or 's3.cn-north-1.amazonaws.com.cn'
export function isAmazonEndpoint(endpoint) {
  return endpoint === 's3.amazonaws.com' || endpoint === 's3.cn-north-1.amazonaws.com.cn'
}

// isVirtualHostStyle - verify if bucket name is support with virtual
// hosts. bucketNames with periods should be always treated as path
// style if the protocol is 'https:', this is due to SSL wildcard
// limitation. For all other buckets and Amazon S3 endpoint we will
// default to virtual host style.
export function isVirtualHostStyle(endpoint, protocol, bucket) {
  if (protocol === 'https:' && bucket.indexOf('.') > -1) {
    return false
  }
  return isAmazonEndpoint(endpoint)
}

var ipv4Regex = /^(\d{1,3}\.){3,3}\d{1,3}$/;

export function isValidIP(ip) {
  return ipv4Regex.test(ip)
}

// isValidEndpoint - true if endpoint is valid domain.
export function isValidEndpoint(endpoint) {
  if (!isValidDomain(endpoint) && !isValidIP(endpoint)) {
    return false
  }
  // Endpoint matches amazon, make sure its 's3.amazonaws.com'
  if (endpoint.match('.amazonaws.com$') || endpoint.match('.amazonaws.com.cn$')) {
    if (!isAmazonEndpoint(endpoint)) {
      return false
    }
  }
  // Return true.
  return true
}

// isValidDomain - true if input host is a valid domain.
export function isValidDomain(host) {
  if (!isString(host)) return false
  // See RFC 1035, RFC 3696.
  if (host.length === 0 || host.length > 255) {
    return false
  }
  // Host cannot start or end with a '-'
  if (host[0] === '-' || host.substr(-1) === '-') {
    return false
  }
  // Host cannot start or end with a '_'
  if (host[0] === '_' || host.substr(-1) === '_') {
    return false
  }
  // Host cannot start or end with a '.'
  if (host[0] === '.' || host.substr(-1) === '.') {
    return false
  }
  var alphaNumerics = '`~!@#$%^&*()+={}[]|\\\"\';:><?/'.split('')
  // All non alphanumeric characters are invalid.
  for (var i in alphaNumerics) {
    if (host.indexOf(alphaNumerics[i]) > -1) {
      return false
    }
  }
  // No need to regexp match, since the list is non-exhaustive.
  // We let it be valid and fail later.
  return true
}

// Probes contentType using file extensions.
// For example: probeContentType('file.png') returns 'image/png'.
export function probeContentType(path) {
  let contentType = mime.lookup(path)
  if (!contentType) {
    contentType = 'application/octet-stream'
  }
  return contentType
}

// isValidPort - is input port valid.
export function isValidPort(port) {
  // verify if port is a number.
  if (!isNumber(port)) return false
  // port cannot be negative.
  if (port < 0) return false
  // port '0' is valid and special case return true.
  if (port === 0) return true
  var min_port = 1;
  var max_port = 65535;
  // Verify if port is in range.
  return port >= min_port && port <= max_port
}

export function isValidBucketName(bucket) {
  if (!isString(bucket)) return false

  // bucket length should be less than and no more than 63
  // characters long.
  if (bucket.length < 3 || bucket.length > 63) {
    return false
  }
  // bucket with successive periods is invalid.
  if (bucket.indexOf('..') > -1) {
    return false
  }
  // bucket cannot have ip address style.
  if (bucket.match(/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/)) {
    return false
  }
  // bucket should begin with alphabet/number and end with alphabet/number,
  // with alphabet/number/.- in the middle.
  if (bucket.match(/^[a-z0-9][a-z0-9.-]+[a-z0-9]$/)) {
    return true
  }
  return false
}

// check if objectName is a valid object name
export function isValidObjectName(objectName) {
  if (!isValidPrefix(objectName)) return false
  if (objectName.length === 0) return false
  return true
}

// check if prefix is valid
export function isValidPrefix(prefix) {
  if (!isString(prefix)) return false
  if (prefix.length > 1024) return false
  return true
}

// check if typeof arg number
export function isNumber(arg) {
  return typeof(arg) === 'number'
}

// check if typeof arg function
export function isFunction(arg) {
  return typeof(arg) === 'function';
}

// check if typeof arg string
export function isString(arg) {
  return typeof(arg) === 'string';
}

// check if typeof arg object
export function isObject(arg) {
  return typeof(arg) === 'object' && arg !== null;
}

// check if object is readable stream
export function isReadableStream(arg) {
  return isObject(arg) && isFunction(arg._read)
}

// check if arg is boolean
export function isBoolean(arg) {
  return typeof(arg) === 'boolean'
}

// check if arg is array
export function isArray(arg) {
  return Array.isArray(arg)
}

// check if arg is Date
export function isDate(arg) {
  return arg._isAMomentObject
}

// pipesetup sets up pipe() from left to right os streams array
// pipesetup will also make sure that error emitted at any of the upstream Stream
// will be emitted at the last stream. This makes error handling simple
export function pipesetup(...streams) {
  return streams.reduce((src, dst) => {
    src.on('error', err => dst.emit('error', err))
    return src.pipe(dst)
  })
}

// return a Readable stream that emits data
export function readableStream(data) {
  var s = new stream.Readable()
  s._read = () => {}
  s.push(data)
  s.push(null)
  return s
}
<|endoftext|>


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

var currentValue = BigDecimal.ZERO;
var savedValue = BigDecimal.ZERO;
var initValue = true;
var doInitValue = true;
var commandCode = '=';
var memoryValue = BigDecimal.valueOf(0);
function $id() {
    return document.getElementById('calc_result');
}
function fCalc(command) {
    if("ce" == command) {
        initCalc();
    } else if ("=" == command) {
        if (commandCode != '=' && !initValue) {
            var value = new BigDecimal($id().value.replace(',', '.'));
            var result = BigDecimal.ZERO;
            switch (commandCode) {
                case '+':
                    result = savedValue.add(value);
                    break;
                case '-':
                    result = savedValue.subtract(value);
                    break;
                case '*':
                    result = savedValue.multiply(value);
                    break;
                case '/':
                    try {
                        result = savedValue.divide(value, 32, BigDecimal.ROUND_HALF_UP);
                    } catch (ex) {
                        initCalc();
                        $id().value = "Error.";
                        return;
                    }
                    break;
            }
            commandCode = '=';
            $id().value = result.setScale(16, BigDecimal.ROUND_HALF_UP).toPlainString().replace('.', ',')
                .replace(/0+$/, "").replace(/,$/, "");
            savedValue = result;
            currentValue = BigDecimal.ZERO;
        }
    } else if ("+-" == command) {
            currentValue = new BigDecimal($id().value.replace(',', '.'));
            currentValue = currentValue.multiply(new BigDecimal("-1"));
            $id().value = currentValue.toPlainString().replace('.', ',');
            if (commandCode == '=') {
                savedValue = currentValue;
                currentValue = BigDecimal.ZERO;
            }
            doInitValue = false;
    } else if("sqrt" == command) {
            currentValue = new BigDecimal($id().value.replace(',', '.'));
            try {
                currentValue = sqrt(currentValue);
            } catch (ex) {
                console.log(ex);
            }
            $id().value = currentValue.setScale(16, BigDecimal.ROUND_HALF_UP).toPlainString().replace('.', ',')
                .replace(/(.+?)0+$/, "$1").replace(/,$/, "");
            if (commandCode == '=') {
                savedValue = currentValue;
                currentValue = BigDecimal.ZERO;
            }
            doInitValue = true;
    } else if ("nbs" == command) {
        if (!initValue && $id().value.match("[\\d,]+")) {
            if ($id().value.length == 1) {
                $id().value = "0";
                initValue = true;
            } else {
                $id().value = $id().value.substring(0, $id().value.length - 1);
            }
            savedValue = new BigDecimal($id().value.replace(',', '.'));
            return;
        }
    } else if ("+" == command) {
        if (commandCode != '=' && !initValue) {
            var value = new BigDecimal($id().value.replace(',', '.'));
            var result = savedValue.add(value);
            $id().value = result.toPlainString().replace('.', ',');
            savedValue = result;
            currentValue = BigDecimal.ZERO;
        }
        commandCode = '+';
    } else if ("-" == command) {
        if (commandCode != '=' && !initValue) {
            var value = new BigDecimal($id().value.replace(',', '.'));
            var result = savedValue.subtract(value);
            $id().value = result.toPlainString().replace('.', ',');
            savedValue = result;
            currentValue = BigDecimal.ZERO;
        }
        commandCode = '-';
    } else if ("*" == command) {
        if (commandCode != '=' && !initValue) {
            var value = new BigDecimal($id().value.replace(',', '.'));
            var result = savedValue.multiply(value);
            $id().value = result.toPlainString().replace('.', ',');
            savedValue = result;
            currentValue = BigDecimal.ZERO;
        }
        commandCode = '*';
    } else if ("/" == command) {
        if (commandCode != '=' && !initValue) {
            var value = new BigDecimal($id().value.replace(',', '.'));
            var result = savedValue.divide(value, 32, BigDecimal.ROUND_HALF_UP);
            $id().value = result.setScale(16, BigDecimal.ROUND_HALF_UP).toPlainString().replace('.', ',')
                .replace(/(.+?)0+$/, "$1").replace(/,$/, "");
            savedValue = result;
            currentValue = BigDecimal.ZERO;
        }
        commandCode = '/';
    } else if ("1/x" == command) {
        currentValue = savedValue == BigDecimal.ZERO
            ? new BigDecimal($id().value.replace(',', '.')) : savedValue;
        try {
            currentValue = BigDecimal.valueOf(1).divide(currentValue, 32, BigDecimal.ROUND_HALF_UP);
        } catch (ex) {
            console.log(ex);
        }
        $id().value = currentValue.setScale(16, BigDecimal.ROUND_HALF_UP).toPlainString().replace('.', ',')
            .replace(/(.+?)0+$/, "$1").replace(/,$/, "");
        if (commandCode == '=') {
            savedValue = currentValue;
            currentValue = BigDecimal.ZERO;
        }
        doInitValue = true;
    } else if ("%" == command) {
        if (commandCode != '=' && !initValue) {
            var value = new BigDecimal($id().value.replace(',', '.'));
            var result = savedValue.multiply(value).divide(BigDecimal.valueOf(100), 32, BigDecimal.ROUND_HALF_UP);
            $id().value = result.setScale(16, BigDecimal.ROUND_HALF_UP).toPlainString().replace('.', ',')
                .replace(/(.+?)0+/, "$1").replace(/,$/, "");
            currentValue = result;
            return;
        }
    } else if ("MC" == command) {
        memoryValue = BigDecimal.valueOf(0);
        if (commandCode == '=') {
            savedValue = currentValue;
            currentValue = BigDecimal.ZERO;
        }
        doInitValue = true;
    } else if ("MR" == command) {
        $id().value = memoryValue.toPlainString().replace('.', ',');
        if (commandCode == '=') {
            savedValue = currentValue;
            currentValue = BigDecimal.ZERO;
        }
        doInitValue = true;
    } else if ("MS" == command) {
        currentValue = new BigDecimal($id().value.replace(',', '.'));
        memoryValue = currentValue;
        doInitValue = true;
    } else if ("M+" == command) {
        currentValue = new BigDecimal($id().value.replace(',', '.'));
        memoryValue = memoryValue.add(currentValue);
        if (commandCode == '=') {
            savedValue = currentValue;
            currentValue = BigDecimal.ZERO;
        }
        doInitValue = true;
    } else if ("M-" == command) {
        currentValue = new BigDecimal($id().value.replace(',', '.'));
        memoryValue = memoryValue.subtract(currentValue);
        if (commandCode == '=') {
            savedValue = currentValue;
            currentValue = BigDecimal.ZERO;
        }
        doInitValue = true;
    }
    if (doInitValue) {
        initValue = true;
    } else {
        doInitValue = true;
    }
}
function addCalc(command) {
    if (initValue) {
        if (command == ",") {
            $id().value = "0" + command;
        } else {
            $id().value = command;
        }
    } else {
        $id().value = $id().value + command;
    }
    if (commandCode == '=') {
        savedValue = new BigDecimal($id().value.replace(',', '.'));
        currentValue = BigDecimal.ZERO;
    } else {
        currentValue = new BigDecimal($id().value.replace(',', '.'));
    }
    initValue = false;
}
function initCalc() {
    currentValue = BigDecimal.ZERO;
    savedValue = BigDecimal.ZERO;
    initValue = true;
    doInitValue = true;
    commandCode = '=';
    $id().value = "0";
}
function keyDetect(keyChar) {
    if (keyChar >= '0' && keyChar <= '9') {
        addCalc(keyChar);
    } else if (keyChar == ',') {
        if (initValue || $id().value.indexOf(",") == -1) {
            addCalc(keyChar);
        }
    } else if (keyChar == '\u2190') {
        fCalc("nbs");
    }
    return true;
}
function keyDetectCalc(evt) {
    var keyChar = String.fromCharCode(evt.charCode);
    if (keyChar == '+' || keyChar == '-' || keyChar == '*'
            || keyChar == '/' || keyChar == '=' || keyChar == '%') {
        fCalc(keyChar);
    } else if (evt.keyCode == 8) {
        fCalc("nbs");
    } else if (evt.keyCode == 13) {
        fCalc("=");
    } else {
        keyDetect(keyChar == '.' ? ',' : keyChar);
    }
}
function sqrt(x) {
    // Check that x >= 0.
    if (x.signum() < 0) {
        throw new Exception("x < 0");
    }

    // n = x*(10^(2*32))
    var n = x.movePointRight(32 << 1).toBigInteger();

    // The first approximation is the upper half of n.
    var bits = (n.bitLength() + 1) >> 1;
    var ix = n.shiftRight(bits);
    var ixPrev;

    // Loop until the approximations converge
    // (two successive approximations are equal after rounding).
    do {
        ixPrev = ix;

        // x = (x + n/x)/2
        ix = ix.add(n.divide(ix)).shiftRight(1);
    } while (ix.compareTo(ixPrev) != 0);

    return new BigDecimal(ix, 32);
}
<commit_msg>Improved MR support<commit_after>/*
 * $Id$
 *
 * Copyright (c) 2013 Valentyn Kolesnikov
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var currentValue = BigDecimal.valueOf(0);
var savedValue = BigDecimal.valueOf(0);
var initValue = true;
var doInitValue = true;
var commandCode = '=';
var memoryValue = BigDecimal.valueOf(0);
function $id() {
    return document.getElementById('calc_result');
}
function fCalc(command) {
    if("ce" == command) {
        initCalc();
    } else if ("=" == command) {
        if (commandCode != '=' && !initValue) {
            var value = new BigDecimal($id().value.replace(',', '.'));
            var result = BigDecimal.valueOf(0);
            switch (commandCode) {
                case '+':
                    result = savedValue.add(value);
                    break;
                case '-':
                    result = savedValue.subtract(value);
                    break;
                case '*':
                    result = savedValue.multiply(value);
                    break;
                case '/':
                    try {
                        result = savedValue.divide(value, 32, BigDecimal.ROUND_HALF_UP);
                    } catch (ex) {
                        initCalc();
                        $id().value = "Error.";
                        return;
                    }
                    break;
            }
            commandCode = '=';
            $id().value = result.setScale(16, BigDecimal.ROUND_HALF_UP).toPlainString().replace('.', ',')
                .replace(/0+$/, "").replace(/,$/, "");
            savedValue = result;
            currentValue = BigDecimal.valueOf(0);
        }
    } else if ("+-" == command) {
            currentValue = new BigDecimal($id().value.replace(',', '.'));
            currentValue = currentValue.multiply(new BigDecimal("-1"));
            $id().value = currentValue.toPlainString().replace('.', ',');
            if (commandCode == '=') {
                savedValue = currentValue;
                currentValue = BigDecimal.valueOf(0);
            }
            doInitValue = false;
    } else if("sqrt" == command) {
            currentValue = new BigDecimal($id().value.replace(',', '.'));
            try {
                currentValue = sqrt(currentValue);
            } catch (ex) {
                console.log(ex);
            }
            $id().value = currentValue.setScale(16, BigDecimal.ROUND_HALF_UP).toPlainString().replace('.', ',')
                .replace(/(.+?)0+$/, "$1").replace(/,$/, "");
            if (commandCode == '=') {
                savedValue = currentValue;
                currentValue = BigDecimal.valueOf(0);
            }
            doInitValue = true;
    } else if ("nbs" == command) {
        if (!initValue && $id().value.match("[\\d,]+")) {
            if ($id().value.length == 1) {
                $id().value = "0";
                initValue = true;
            } else {
                $id().value = $id().value.substring(0, $id().value.length - 1);
            }
            savedValue = new BigDecimal($id().value.replace(',', '.'));
            return;
        }
    } else if ("+" == command) {
        if (commandCode != '=' && !initValue) {
            var value = new BigDecimal($id().value.replace(',', '.'));
            var result = savedValue.add(value);
            $id().value = result.toPlainString().replace('.', ',');
            savedValue = result;
            currentValue = BigDecimal.valueOf(0);
        }
        commandCode = '+';
    } else if ("-" == command) {
        if (commandCode != '=' && !initValue) {
            var value = new BigDecimal($id().value.replace(',', '.'));
            var result = savedValue.subtract(value);
            $id().value = result.toPlainString().replace('.', ',');
            savedValue = result;
            currentValue = BigDecimal.valueOf(0);
        }
        commandCode = '-';
    } else if ("*" == command) {
        if (commandCode != '=' && !initValue) {
            var value = new BigDecimal($id().value.replace(',', '.'));
            var result = savedValue.multiply(value);
            $id().value = result.toPlainString().replace('.', ',');
            savedValue = result;
            currentValue = BigDecimal.valueOf(0);
        }
        commandCode = '*';
    } else if ("/" == command) {
        if (commandCode != '=' && !initValue) {
            var value = new BigDecimal($id().value.replace(',', '.'));
            var result = savedValue.divide(value, 32, BigDecimal.ROUND_HALF_UP);
            $id().value = result.setScale(16, BigDecimal.ROUND_HALF_UP).toPlainString().replace('.', ',')
                .replace(/(.+?)0+$/, "$1").replace(/,$/, "");
            savedValue = result;
            currentValue = BigDecimal.valueOf(0);
        }
        commandCode = '/';
    } else if ("1/x" == command) {
        currentValue = savedValue == BigDecimal.valueOf(0)
            ? new BigDecimal($id().value.replace(',', '.')) : savedValue;
        try {
            currentValue = BigDecimal.valueOf(1).divide(currentValue, 32, BigDecimal.ROUND_HALF_UP);
        } catch (ex) {
            console.log(ex);
        }
        $id().value = currentValue.setScale(16, BigDecimal.ROUND_HALF_UP).toPlainString().replace('.', ',')
            .replace(/(.+?)0+$/, "$1").replace(/,$/, "");
        if (commandCode == '=') {
            savedValue = currentValue;
            currentValue = BigDecimal.valueOf(0);
        }
        doInitValue = true;
    } else if ("%" == command) {
        if (commandCode != '=' && !initValue) {
            var value = new BigDecimal($id().value.replace(',', '.'));
            var result = savedValue.multiply(value).divide(BigDecimal.valueOf(100), 32, BigDecimal.ROUND_HALF_UP);
            $id().value = result.setScale(16, BigDecimal.ROUND_HALF_UP).toPlainString().replace('.', ',')
                .replace(/(.+?)0+/, "$1").replace(/,$/, "");
            currentValue = result;
            return;
        }
    } else if ("MC" == command) {
        memoryValue = BigDecimal.valueOf(0);
        doInitValue = true;
    } else if ("MR" == command) {
        $id().value = memoryValue.toPlainString().replace('.', ',');
        if (commandCode != '=') {
            currentValue = BigDecimal.valueOf(0);
            initValue = false;
        }
        doInitValue = false;
    } else if ("MS" == command) {
        currentValue = new BigDecimal($id().value.replace(',', '.'));
        memoryValue = currentValue;
        doInitValue = true;
    } else if ("M+" == command) {
        currentValue = new BigDecimal($id().value.replace(',', '.'));
        memoryValue = memoryValue.add(currentValue);
        doInitValue = true;
    } else if ("M-" == command) {
        currentValue = new BigDecimal($id().value.replace(',', '.'));
        memoryValue = memoryValue.subtract(currentValue);
        doInitValue = true;
    }
    if (doInitValue) {
        initValue = true;
    } else {
        doInitValue = true;
    }
}
function addCalc(command) {
    if (initValue) {
        if (command == ",") {
            $id().value = "0" + command;
        } else {
            $id().value = command;
        }
    } else {
        $id().value = $id().value + command;
    }
    if (commandCode == '=') {
        savedValue = new BigDecimal($id().value.replace(',', '.'));
        currentValue = BigDecimal.valueOf(0);
    } else {
        currentValue = new BigDecimal($id().value.replace(',', '.'));
    }
    initValue = false;
}
function initCalc() {
    currentValue = BigDecimal.valueOf(0);
    savedValue = BigDecimal.valueOf(0);
    initValue = true;
    doInitValue = true;
    commandCode = '=';
    $id().value = "0";
}
function keyDetect(keyChar) {
    if (keyChar >= '0' && keyChar <= '9') {
        addCalc(keyChar);
    } else if (keyChar == ',') {
        if (initValue || $id().value.indexOf(",") == -1) {
            addCalc(keyChar);
        }
    } else if (keyChar == '\u2190') {
        fCalc("nbs");
    }
    return true;
}
function keyDetectCalc(evt) {
    var keyChar = String.fromCharCode(evt.charCode);
    if (keyChar == '+' || keyChar == '-' || keyChar == '*'
            || keyChar == '/' || keyChar == '=' || keyChar == '%') {
        fCalc(keyChar);
    } else if (evt.keyCode == 8) {
        fCalc("nbs");
    } else if (evt.keyCode == 13) {
        fCalc("=");
    } else {
        keyDetect(keyChar == '.' ? ',' : keyChar);
    }
}
function sqrt(x) {
    // Check that x >= 0.
    if (x.signum() < 0) {
        throw new Exception("x < 0");
    }

    // n = x*(10^(2*32))
    var n = x.movePointRight(32 << 1).toBigInteger();

    // The first approximation is the upper half of n.
    var bits = (n.bitLength() + 1) >> 1;
    var ix = n.shiftRight(bits);
    var ixPrev;

    // Loop until the approximations converge
    // (two successive approximations are equal after rounding).
    do {
        ixPrev = ix;

        // x = (x + n/x)/2
        ix = ix.add(n.divide(ix)).shiftRight(1);
    } while (ix.compareTo(ixPrev) != 0);

    return new BigDecimal(ix, 32);
}
<|endoftext|>


<commit_before>
/*accountInformation
[credentials]
credentials:{key: validation}
*/

/*
queue
[{endpoint1: string, endpoint2: string, speed: number}]
*/

import { LOGIN, LOGOUT, PROMOTE, ENDPOINT_PROGRESS, ENDPOINT_UPDATE, UPDATE_HASH } from './actions';
import { transferOptimizations } from "./actions";

export const cookies = require("js-cookie");

export const beforeLogin = 0;
export const duringLogin = 1;
export const afterLogin = 2;
const initialState = {
	login: cookies.get('email') ? true : false,
	admin: false,
	email: cookies.get('email') || "noemail" ,
  publicKey: cookies.get('publicKey') || null ,
	hash: cookies.get('hash') || null,

	endpoint1: cookies.get('endpoint1') ? JSON.parse(cookies.get('endpoint1')) : {
		login: false,
		credential: {},
		uri: "",
        side: "left"
	},

	endpoint2: cookies.get('endpoint2') ? JSON.parse(cookies.get('endpoint2')) : {
    login: false,
		credential: {},
		uri: "",
        side: "right"
	},

	queue: [],
	transferOptions : {
		useTransferOptimization : transferOptimizations.None,
		overwriteExistingFiles : true,
		verifyFileInterity : false,
		encryptDataChannel : false,
		compressDataChannel : false
	}
}

export function onedatashareModel(state = initialState, action) {
  // For now, don't handle any actions
  // and just return the state given to us.
  switch (action.type) {
    case LOGIN:
    	console.log('logging in')
   		const {email, hash, publicKey} = action.credential;
      console.log(email);
    	cookies.set('email', email, );
		  cookies.set('hash', hash, );
      cookies.set('publicKey', publicKey, );
    	return Object.assign({}, state, {
    		login: true,
    		email: email,
    		hash: hash,
            publicKey: publicKey
    	});
    case LOGOUT:
      console.log("logging out");
      cookies.remove('email');
      cookies.remove('hash');
      cookies.remove('admin');
      cookies.remove('endpoint1');
      cookies.remove('endpoint2');
      cookies.remove("publicKey");
      window.location.replace('/');

      return Object.assign({}, state, {
        login: false,
        admin: false,
        hash: "",
        email: "noemail"
      });
    case PROMOTE:
      return Object.assign({}, state, {
        admin: true,
      });
    case ENDPOINT_PROGRESS:
      if(action.side === "left")
        return Object.assign({}, state, {
          endpoint1: {...state.endpoint1, loginProgress: action.progress},
        });
      else
        return Object.assign({}, state, {
          endpoint2: {...state.endpoint2, loginProgress: action.progress},
        });
    case ENDPOINT_UPDATE:
      if(action.side === "left"){
        console.log(JSON.stringify({...state.endpoint1, ...action.endpoint}));
        cookies.set('endpoint1', JSON.stringify({...state.endpoint1, ...action.endpoint}), );
          return Object.assign({}, state, {
            endpoint1: {...state.endpoint1, ...action.endpoint},
          });
        }
      else{
        cookies.set('endpoint2', JSON.stringify({...state.endpoint2, ...action.endpoint}), );
        return Object.assign({}, state, {
          endpoint2: {...state.endpoint2, ...action.endpoint},
        });
      }
    case UPDATE_HASH:
        cookies.remove('hash');
     cookies.set('hash',  action.hash, );
         return Object.assign({}, state, {
                  hash: action.hash
                });

    default:
      return state
  }
}<commit_msg>Update reducers.js<commit_after>
/*accountInformation
[credentials]
credentials:{key: validation}
*/

/*
queue
[{endpoint1: string, endpoint2: string, speed: number}]
*/

import { LOGIN, LOGOUT, PROMOTE, ENDPOINT_PROGRESS, ENDPOINT_UPDATE, UPDATE_HASH } from './actions';
import { transferOptimizations } from "./actions";

export const cookies = require("js-cookie");

export const beforeLogin = 0;
export const duringLogin = 1;
export const afterLogin = 2;
const initialState = {
	login: cookies.get('email') ? true : false,
	admin: false,
	email: cookies.get('email') || "noemail" ,
  publicKey: cookies.get('publicKey') || null ,
	hash: cookies.get('hash') || null,

	endpoint1: cookies.get('endpoint1') ? JSON.parse(cookies.get('endpoint1')) : {
		login: false,
		credential: {},
		uri: "",
        side: "left"
	},

	endpoint2: cookies.get('endpoint2') ? JSON.parse(cookies.get('endpoint2')) : {
    login: false,
		credential: {},
		uri: "",
        side: "right"
	},

	queue: [],
	transferOptions : {
		useTransferOptimization : transferOptimizations.None,
		overwriteExistingFiles : true,
		verifyFileInterity : false,
		encryptDataChannel : false,
		compressDataChannel : false
	}
}

export function onedatashareModel(state = initialState, action) {
  // For now, don't handle any actions
  // and just return the state given to us.
  switch (action.type) {
    case LOGIN:
    	console.log('logging in')
   		const {email, hash, publicKey} = action.credential;
      console.log(email);
    	cookies.set('email', email);
		  cookies.set('hash', hash);
      cookies.set('publicKey', publicKey);
    	return Object.assign({}, state, {
    		login: true,
    		email: email,
    		hash: hash,
            publicKey: publicKey
    	});
    case LOGOUT:
      console.log("logging out");
      cookies.remove('email');
      cookies.remove('hash');
      cookies.remove('admin');
      cookies.remove('endpoint1');
      cookies.remove('endpoint2');
      cookies.remove("publicKey");
      window.location.replace('/');

      return Object.assign({}, state, {
        login: false,
        admin: false,
        hash: "",
        email: "noemail"
      });
    case PROMOTE:
      return Object.assign({}, state, {
        admin: true,
      });
    case ENDPOINT_PROGRESS:
      if(action.side === "left")
        return Object.assign({}, state, {
          endpoint1: {...state.endpoint1, loginProgress: action.progress},
        });
      else
        return Object.assign({}, state, {
          endpoint2: {...state.endpoint2, loginProgress: action.progress},
        });
    case ENDPOINT_UPDATE:
      if(action.side === "left"){
        console.log(JSON.stringify({...state.endpoint1, ...action.endpoint}));
        cookies.set('endpoint1', JSON.stringify({...state.endpoint1, ...action.endpoint}));
          return Object.assign({}, state, {
            endpoint1: {...state.endpoint1, ...action.endpoint},
          });
        }
      else{
        cookies.set('endpoint2', JSON.stringify({...state.endpoint2, ...action.endpoint}));
        return Object.assign({}, state, {
          endpoint2: {...state.endpoint2, ...action.endpoint},
        });
      }
    case UPDATE_HASH:
        cookies.remove('hash');
     cookies.set('hash',  action.hash);
         return Object.assign({}, state, {
                  hash: action.hash
                });

    default:
      return state
  }
}
<|endoftext|>


<commit_before>var irc = require('irc');
var fs = require('fs');
var EventEmitter = require('events');
var reload = require('require-reload')(require);
var utils;

if(!global.is_reloading) {
    var console_log = console.log;
    var console_err = console.error;
    console.log = function(text) {
        console_log(new Date().toUTCString() + ' - ' + text);
    }
    console.error = function(text) {
        console_err(new Date().toUTCString() + ' - ERROR: ' + text);
    }
    global.is_reloading = true;
}

var actions;
var modules = {};
var configs = {};
var globals = {};

function reset_actions() {
    for(var module in modules) {
        if(modules[module].destroy) {
            try {
                modules[module].destroy();
            } catch(e) {
                console.error('while destroying ' + module + ': ' + e);
            }
        }
    }

    actions = new EventEmitter();
    modules = {};
    globals = {};
}

function load_actions() {
    reset_actions();

    utils = reload('./utils.js');

    function help_on_empty(func) {
        return function(bot, from, to, text) {
            if(!text.trim()) {
                return true;
            } else {
                return func.apply(this, arguments);
            }
        }
    }

    function op_only(func) {
        return function(bot, from, to) {
            if(!bot.chans || !bot.chans[bot.channel.toLowerCase()] || bot.chans[bot.channel.toLowerCase()].users[from] !== '@') {
                bot.sayDirect(from, to, 'Only ops may use this command.');
                return;
            }

            return func.apply(this, arguments);
        }
    }

    function no_pm(func) {
        return function(bot, from, to) {
            if(to === bot.nick && bot.chans[bot.channel] && bot.chans[bot.channel].users[from] !== '@') {
                bot.sayDirect(from, to, 'This command is not allowed in pm.');
            } else {
                return func.apply(this, arguments);
            }
        }
    }

    var help_msgs = {};

    actions.on('reload', op_only(function(bot, from, to, text, message) {
        console.log('Reloading actions.');

        var old_actions = actions;
        var old_globals = globals;

        try {
            load_actions();
            bot.sayDirect(from, to, 'Successfully reloaded actions.');
            console.log('Successfully reloaded actions.');
        } catch(e) {
            bot.sayDirect(from, to, 'Reloading attempt failed, could not reload actions: ' + e);
            console.error('Failed to reload actions: ' + e);
            console.error(e.stack);

            actions = old_actions;
            globals = old_globals;
        }
    }));
    help_msgs['reload'] = 'Usage: !reload. Reloads all actions, op only use.';

    actions.on('reloadbot', op_only(function(bot, from, to, text, message) {
        try {
            console.log('Reloading FancyBot');

            for(var config in configs) {
                save_config(config, configs[config], true);
            }

            try {
                load_actions();

                bot.disconnect('Reloading...', function() {
                    global.is_reloading = true;
                    reload(process.argv[1]);
                });
            } catch(e) {
                bot.sayDirect(from, to, 'Reloading attempt failed, could not reload actions: ' + e);
                console.error('Failed to reload actions: ' + e);
                console.error(e.stack);
            }
        } catch(e) {
            console.log('Failed to reload the actions ' + e + '\n' + e.stack);
            bot.sayDirect(from, to, 'Failed to reload the actions ' + e.message);
        }
    }));
    help_msgs['reloadbot'] = 'Usage: !reloadbot. Reloads the bot entirely, including reconnecting to IRC, op only use.';

    actions.on('help', function(bot, from, to, text, message) {
        if(text) {
            if(help_msgs[text]) {
                bot.sayDirect(from, to, help_msgs[text]);
            } else {
                bot.sayDirect(from, to, 'No help message found for command \'' + text + '\'.');
            }
        } else {
            var commands = '';
            for(var command in actions._events) {
                if(command[0] !== '_') {
                    commands += ' ' + command;
                }
            }
            bot.sayDirect(from, to, 'Available commands:' + commands);
        }
    });
    help_msgs['help'] = 'Usage: !help [command]. Displays a help message for the command, or if ommitted lists all available commands.'

    fs.readdirSync('actions/').forEach(function(file) {
        if(!file.endsWith('.js')) return;

        var name = file.substring(0, file.length - 3);

        if(name === 'bot') {
            throw new Error('Cannot use reserved name \'bot\'.');
        }

        modules[name] = reload('./actions/' + file);

        var action_utils = {
            save_config: function() {
                save_config(name, configs[name]);
            },
            globals: globals,
        };
        Object.assign(action_utils, utils);

        if(!configs[name]) {
            configs[name] = load_config(name);
        }
        var action_config = configs[name];

        function action(options, func) {
            if(options.name[0] !== '_') {
                if(actions.listenerCount(options.name) > 0) {
                    throw new Error('Cannot have two user actions registered to the same name.');
                }

                if(options.help_on_empty) {
                    func = help_on_empty(func);
                }
                if(options.op_only) {
                    func = op_only(func);
                }
                if(options.no_pm) {
                    func = no_pm(func);
                }

                help_msgs[options.name.toLowerCase()] = options.help;
            }

            var f = function(bot, from, to) {
                var args = Array.from(arguments).concat([action_utils, action_config]);
                if(func.apply(this, args) && options.name[0] !== '_' && options.help) {
                    bot.sayDirect(from, to, options.help);
                }
            };

            actions.on(options.name.toLowerCase(), f);
        }

        if(modules[name].init) {
            modules[name].init(action, action_utils, action_config);
            console.log('Loaded ' + name);
        }
    });
}

function load_config(name) {
    try {
        var config = JSON.parse(fs.readFileSync('configs/' + name + '.json'));
        console.log('Loaded config');
        return config;
    } catch(e) {
        console.error('COULD NOT LOAD CONFIG: ' + e + '\n' + e.stack);
        return {};
    }
}

var configs_timeout = {};
function save_config(name, config, immediately) {
    if(!configs_timeout[name]) {
        configs_timeout[name] = {
            save_config_count: 0,
            last_config_timeout: null,
        };
    }

    if(configs_timeout[name].save_config_count < 10 || immediately) {
        if(configs_timeout[name].last_config_timeout) {
            clearTimeout(configs_timeout[name].last_config_timeout);
            configs_timeout[name].save_config_count++;
        }

        if(immediately) {
            fs.writeFileSync('configs/' + name + '.json', JSON.stringify(config, null, 4));
            configs_timeout[name].save_config_count = 0;
            configs_timeout[name].last_config_timeout = null;
        } else {
            configs_timeout[name].last_config_timeout = setTimeout(function() {
                configs_timeout[name].save_config_count = 0;
                configs_timeout[name].last_config_timeout = null;
                fs.writeFile('configs/' + name + '.json', JSON.stringify(config, null, 4), function(err) {
                    if(err)
                        console.error('COULD NOT WRITE CONFIG!');
                });
            }, 1000);
        }
    }
}

var bot_config = JSON.parse(fs.readFileSync('config.json'));

load_actions();

var name = bot_config.name;
var server = bot_config.server;
var chan = bot_config.channel;

var bot = new irc.Client(server, name, {
    userName: name,
    realName: name,
    channels: [chan],
    autoRejoin: true
});
bot.channel = chan;

bot.sayDirect = function(from, to, message) {
    if(to === bot.nick) {
        bot.say(from, message);
    } else {
        bot.say(to, from + ': ' + message);
    }
}

bot.on('registered', function(message) {
    console.log('Successfully joined ' + server + '!');

    if(bot_config.password) {
        console.log('Identifying...');
        bot.say('NickServ', 'identify ' + bot_config.password);
    }

    actions.emit('_init', bot, message);
});

bot.on('join', function(channel, nick, message) {
    if(nick === bot.nick) {
        if(global.is_reloading) {
            console.log('Successfully reloaded ' + name + '.');
            bot.say(channel, 'Successfully reloaded ' + name + '.');
        }

        console.log('Joined ' + channel);
        actions.emit('_joined', bot, channel, message);
    } else {
        actions.emit('_join', bot, channel, nick, message);
    }
});

bot.on('part', function(channel, nick, reason, message) {
    actions.emit('_part', bot, channel, nick, reason, message);
});

bot.on('quit', function(nick, reason, channels, message) {
    actions.emit('_quit', bot, bot.channel, nick, reason, message);
});

bot.on('kick', function(channel, nick, by, reason ,message) {
    actions.emit('_kick', bot, channel, nick, by, reason, message);
});

bot.on('nick', function(oldnick, newnick, channels, message) {
    if(bot.nick != name) {
        bot.send('NICK', name);
    }

    if(newnick === name) {
        actions.emit('_init', bot, message);
    }

    actions.emit('_nick', bot, oldnick, newnick, channels, message);
});

bot.on('message', function(nick, to, text, message) {
    actions.emit('_msg', bot, nick, to, text, message);

    if(text[0] === '!') {
        var index = text.indexOf(' ');
        var command = text.substring(1, index == -1 ? undefined : index).trim().toLowerCase();

        console.log('Detected command from ' + nick + ': ' + command);

        if(command[0] != '_' && actions.emit(command, bot, nick, to, index == -1 ? '' : text.substring(index).trim(), message)) {
            return;
        }

        console.log('Command \'' + command + '\' not found.');
    }

    actions.emit('_', bot, nick, to, text, message);
});

bot.on('notice', function(nick, to, text, message) {
    if(to === bot.nick) {
        console.log('NOTICE: -' + (nick === null ? 'Server' : nick) + '- ' + text);
    }

    actions.emit('_notice', bot, nick, to, text, message);
});

bot.on('selfMessage', function(to, text) {
    actions.emit('_self', bot, to, text);
});

bot.on('action', function(nick, to, text, message) {
    actions.emit('_action', bot, nick, to, text, message);
});

bot.on('+mode', function(channel, by, mode, argument, message) {
    actions.emit('_mode', bot, channel, by, '+' + mode, argument, message);
});

bot.on('-mode', function(channel, by, mode, argument, message) {
    actions.emit('_mode', bot, channel, by, '-' + mode, argument, message);
});

bot.on('error', function(message) {
    console.error(require('util').inspect(message));
});

process.on('exit', function() {
    console.log("Goodbye!");
    reset_actions();
});

console.log('Joining ' + server + '...');
<commit_msg>Forgot to normalize action name everywhere.<commit_after>var irc = require('irc');
var fs = require('fs');
var EventEmitter = require('events');
var reload = require('require-reload')(require);
var utils;

if(!global.is_reloading) {
    var console_log = console.log;
    var console_err = console.error;
    console.log = function(text) {
        console_log(new Date().toUTCString() + ' - ' + text);
    }
    console.error = function(text) {
        console_err(new Date().toUTCString() + ' - ERROR: ' + text);
    }
    global.is_reloading = true;
}

var actions;
var modules = {};
var configs = {};
var globals = {};

function reset_actions() {
    for(var module in modules) {
        if(modules[module].destroy) {
            try {
                modules[module].destroy();
            } catch(e) {
                console.error('while destroying ' + module + ': ' + e);
            }
        }
    }

    actions = new EventEmitter();
    modules = {};
    globals = {};
}

function load_actions() {
    reset_actions();

    utils = reload('./utils.js');

    function help_on_empty(func) {
        return function(bot, from, to, text) {
            if(!text.trim()) {
                return true;
            } else {
                return func.apply(this, arguments);
            }
        }
    }

    function op_only(func) {
        return function(bot, from, to) {
            if(!bot.chans || !bot.chans[bot.channel.toLowerCase()] || bot.chans[bot.channel.toLowerCase()].users[from] !== '@') {
                bot.sayDirect(from, to, 'Only ops may use this command.');
                return;
            }

            return func.apply(this, arguments);
        }
    }

    function no_pm(func) {
        return function(bot, from, to) {
            if(to === bot.nick && bot.chans[bot.channel] && bot.chans[bot.channel].users[from] !== '@') {
                bot.sayDirect(from, to, 'This command is not allowed in pm.');
            } else {
                return func.apply(this, arguments);
            }
        }
    }

    var help_msgs = {};

    actions.on('reload', op_only(function(bot, from, to, text, message) {
        console.log('Reloading actions.');

        var old_actions = actions;
        var old_globals = globals;

        try {
            load_actions();
            bot.sayDirect(from, to, 'Successfully reloaded actions.');
            console.log('Successfully reloaded actions.');
        } catch(e) {
            bot.sayDirect(from, to, 'Reloading attempt failed, could not reload actions: ' + e);
            console.error('Failed to reload actions: ' + e);
            console.error(e.stack);

            actions = old_actions;
            globals = old_globals;
        }
    }));
    help_msgs['reload'] = 'Usage: !reload. Reloads all actions, op only use.';

    actions.on('reloadbot', op_only(function(bot, from, to, text, message) {
        try {
            console.log('Reloading FancyBot');

            for(var config in configs) {
                save_config(config, configs[config], true);
            }

            try {
                load_actions();

                bot.disconnect('Reloading...', function() {
                    global.is_reloading = true;
                    reload(process.argv[1]);
                });
            } catch(e) {
                bot.sayDirect(from, to, 'Reloading attempt failed, could not reload actions: ' + e);
                console.error('Failed to reload actions: ' + e);
                console.error(e.stack);
            }
        } catch(e) {
            console.log('Failed to reload the actions ' + e + '\n' + e.stack);
            bot.sayDirect(from, to, 'Failed to reload the actions ' + e.message);
        }
    }));
    help_msgs['reloadbot'] = 'Usage: !reloadbot. Reloads the bot entirely, including reconnecting to IRC, op only use.';

    actions.on('help', function(bot, from, to, text, message) {
        if(text) {
            if(help_msgs[text]) {
                bot.sayDirect(from, to, help_msgs[text]);
            } else {
                bot.sayDirect(from, to, 'No help message found for command \'' + text + '\'.');
            }
        } else {
            var commands = '';
            for(var command in actions._events) {
                if(command[0] !== '_') {
                    commands += ' ' + command;
                }
            }
            bot.sayDirect(from, to, 'Available commands:' + commands);
        }
    });
    help_msgs['help'] = 'Usage: !help [command]. Displays a help message for the command, or if ommitted lists all available commands.'

    fs.readdirSync('actions/').forEach(function(file) {
        if(!file.endsWith('.js')) return;

        var name = file.substring(0, file.length - 3);

        if(name === 'bot') {
            throw new Error('Cannot use reserved name \'bot\'.');
        }

        modules[name] = reload('./actions/' + file);

        var action_utils = {
            save_config: function() {
                save_config(name, configs[name]);
            },
            globals: globals,
        };
        Object.assign(action_utils, utils);

        if(!configs[name]) {
            configs[name] = load_config(name);
        }
        var action_config = configs[name];

        function action(options, func) {
            if(options.name[0] !== '_') {
                if(actions.listenerCount(options.name.toLowerCase()) > 0) {
                    throw new Error('Cannot have two user actions registered to the same name.');
                }

                if(options.help_on_empty) {
                    func = help_on_empty(func);
                }
                if(options.op_only) {
                    func = op_only(func);
                }
                if(options.no_pm) {
                    func = no_pm(func);
                }

                help_msgs[options.name.toLowerCase()] = options.help;
            }

            var f = function(bot, from, to) {
                var args = Array.from(arguments).concat([action_utils, action_config]);
                if(func.apply(this, args) && options.name[0] !== '_' && options.help) {
                    bot.sayDirect(from, to, options.help);
                }
            };

            actions.on(options.name.toLowerCase(), f);
        }

        if(modules[name].init) {
            modules[name].init(action, action_utils, action_config);
            console.log('Loaded ' + name);
        }
    });
}

function load_config(name) {
    try {
        var config = JSON.parse(fs.readFileSync('configs/' + name + '.json'));
        console.log('Loaded config');
        return config;
    } catch(e) {
        console.error('COULD NOT LOAD CONFIG: ' + e + '\n' + e.stack);
        return {};
    }
}

var configs_timeout = {};
function save_config(name, config, immediately) {
    if(!configs_timeout[name]) {
        configs_timeout[name] = {
            save_config_count: 0,
            last_config_timeout: null,
        };
    }

    if(configs_timeout[name].save_config_count < 10 || immediately) {
        if(configs_timeout[name].last_config_timeout) {
            clearTimeout(configs_timeout[name].last_config_timeout);
            configs_timeout[name].save_config_count++;
        }

        if(immediately) {
            fs.writeFileSync('configs/' + name + '.json', JSON.stringify(config, null, 4));
            configs_timeout[name].save_config_count = 0;
            configs_timeout[name].last_config_timeout = null;
        } else {
            configs_timeout[name].last_config_timeout = setTimeout(function() {
                configs_timeout[name].save_config_count = 0;
                configs_timeout[name].last_config_timeout = null;
                fs.writeFile('configs/' + name + '.json', JSON.stringify(config, null, 4), function(err) {
                    if(err)
                        console.error('COULD NOT WRITE CONFIG!');
                });
            }, 1000);
        }
    }
}

var bot_config = JSON.parse(fs.readFileSync('config.json'));

load_actions();

var name = bot_config.name;
var server = bot_config.server;
var chan = bot_config.channel;

var bot = new irc.Client(server, name, {
    userName: name,
    realName: name,
    channels: [chan],
    autoRejoin: true
});
bot.channel = chan;

bot.sayDirect = function(from, to, message) {
    if(to === bot.nick) {
        bot.say(from, message);
    } else {
        bot.say(to, from + ': ' + message);
    }
}

bot.on('registered', function(message) {
    console.log('Successfully joined ' + server + '!');

    if(bot_config.password) {
        console.log('Identifying...');
        bot.say('NickServ', 'identify ' + bot_config.password);
    }

    actions.emit('_init', bot, message);
});

bot.on('join', function(channel, nick, message) {
    if(nick === bot.nick) {
        if(global.is_reloading) {
            console.log('Successfully reloaded ' + name + '.');
            bot.say(channel, 'Successfully reloaded ' + name + '.');
        }

        console.log('Joined ' + channel);
        actions.emit('_joined', bot, channel, message);
    } else {
        actions.emit('_join', bot, channel, nick, message);
    }
});

bot.on('part', function(channel, nick, reason, message) {
    actions.emit('_part', bot, channel, nick, reason, message);
});

bot.on('quit', function(nick, reason, channels, message) {
    actions.emit('_quit', bot, bot.channel, nick, reason, message);
});

bot.on('kick', function(channel, nick, by, reason ,message) {
    actions.emit('_kick', bot, channel, nick, by, reason, message);
});

bot.on('nick', function(oldnick, newnick, channels, message) {
    if(bot.nick != name) {
        bot.send('NICK', name);
    }

    if(newnick === name) {
        actions.emit('_init', bot, message);
    }

    actions.emit('_nick', bot, oldnick, newnick, channels, message);
});

bot.on('message', function(nick, to, text, message) {
    actions.emit('_msg', bot, nick, to, text, message);

    if(text[0] === '!') {
        var index = text.indexOf(' ');
        var command = text.substring(1, index == -1 ? undefined : index).trim().toLowerCase();

        console.log('Detected command from ' + nick + ': ' + command);

        if(command[0] != '_' && actions.emit(command, bot, nick, to, index == -1 ? '' : text.substring(index).trim(), message)) {
            return;
        }

        console.log('Command \'' + command + '\' not found.');
    }

    actions.emit('_', bot, nick, to, text, message);
});

bot.on('notice', function(nick, to, text, message) {
    if(to === bot.nick) {
        console.log('NOTICE: -' + (nick === null ? 'Server' : nick) + '- ' + text);
    }

    actions.emit('_notice', bot, nick, to, text, message);
});

bot.on('selfMessage', function(to, text) {
    actions.emit('_self', bot, to, text);
});

bot.on('action', function(nick, to, text, message) {
    actions.emit('_action', bot, nick, to, text, message);
});

bot.on('+mode', function(channel, by, mode, argument, message) {
    actions.emit('_mode', bot, channel, by, '+' + mode, argument, message);
});

bot.on('-mode', function(channel, by, mode, argument, message) {
    actions.emit('_mode', bot, channel, by, '-' + mode, argument, message);
});

bot.on('error', function(message) {
    console.error(require('util').inspect(message));
});

process.on('exit', function() {
    console.log("Goodbye!");
    reset_actions();
});

console.log('Joining ' + server + '...');
<|endoftext|>


<commit_before>var Sequelize = require('sequelize');

var Story = sequelize.define('Story', {
  id: Sequelize.INTEGER
  deleted: Sequelize.BOOLEAN,
  by: Sequelize.STRING,
  createdAt: Sequelize.INTEGER,
  text: Sequelize.STRING,
  dead: Sequelize.BOOLEAN,
  //figure out how to use array
  kids: Sequelize.ARRAY(Sequelize.STRING),
  url: Sequelize.STRING,
  score: Sequelize.INTEGER,
  title: Sequelize.STRING
});

var Comment = sequelize.define('Comment', {
  id: Sequelize.INTEGER
  deleted: Sequelize.BOOLEAN,
  by: Sequelize.STRING,
  createdAt: Sequelize.INTEGER,
  text: Sequelize.STRING,
  dead: Sequelize.BOOLEAN,
  //figure out how to use array
  kids: Sequelize.ARRAY(Sequelize.INTEGER),
  url: Sequelize.STRING,
  score: Sequelize.INTEGER,
  title: Sequelize.STRING
});

var Job = sequelize.define('Job', {
  id: Sequelize.INTEGER
  deleted: Sequelize.BOOLEAN,
  by: Sequelize.STRING,
  createdAt: Sequelize.INTEGER,
  text: Sequelize.STRING,
  dead: Sequelize.BOOLEAN,
  //figure out how to use array
  kids: Sequelize.ARRAY(Sequelize.INTEGER),
  url: Sequelize.STRING,
  score: Sequelize.INTEGER,
  title: Sequelize.STRING
});

var Poll = sequelize.define('Poll', {
  id: Sequelize.INTEGER
  deleted: Sequelize.BOOLEAN,
  by: Sequelize.STRING,
  createdAt: Sequelize.INTEGER,
  text: Sequelize.STRING,
  dead: Sequelize.BOOLEAN,
  //figure out how to use array
  kids: Sequelize.ARRAY(Sequelize.INTEGER),
  url: Sequelize.STRING,
  score: Sequelize.INTEGER,
  title: Sequelize.STRING
});

var Pollopt = sequelize.define('Pollopt', {
  id: Sequelize.INTEGER
  deleted: Sequelize.BOOLEAN,
  by: Sequelize.STRING,
  createdAt: Sequelize.INTEGER,
  text: Sequelize.STRING,
  dead: Sequelize.BOOLEAN,
  //figure out how to use array
  kids: Sequelize.ARRAY(Sequelize.INTEGER),
  url: Sequelize.STRING,
  score: Sequelize.INTEGER,
  title: Sequelize.STRING,
  parts: Sequelize.ARRAY(Sequelize.INTEGER)
});

var User = sequelize.define('User', {
  id: {type: Sequelize.STRING, unique: true, primarykey: true},
  delay: Sequelize.INTEGER,
  createdAt: Sequelize.INTEGER,
  karma: Sequelize.INTEGER,
  about: Sequelize.STRING,
  submitted: Sequelize.ARRAY(Sequelize.INTEGER)
});<commit_msg>Tables created and ordered.<commit_after>var Sequelize = require('sequelize');

var Story = sequelize.define('Story', {
  id: {type: Sequelize.INTEGER, primarykey: true},
  title: Sequelize.STRING,
  by: Sequelize.STRING,
  createdAt: Sequelize.INTEGER,
  text: Sequelize.STRING,
  url: Sequelize.STRING,
  score: Sequelize.INTEGER,
  //figure out how to use array
  kids: Sequelize.ARRAY(Sequelize.STRING),
  //optional below here?
  deleted: Sequelize.BOOLEAN,
  dead: Sequelize.BOOLEAN
});

var Comment = sequelize.define('Comment', {
  id: {type: Sequelize.INTEGER, primarykey: true},
  by: Sequelize.STRING,
  parent: Sequelize.INTEGER,
  createdAt: Sequelize.INTEGER,
  text: Sequelize.STRING,
  //optional below here
  //figure out how to use array
  kids: Sequelize.ARRAY(Sequelize.INTEGER),
  url: Sequelize.STRING,
  score: Sequelize.INTEGER,
  title: Sequelize.STRING
  deleted: Sequelize.BOOLEAN,
  dead: Sequelize.BOOLEAN,
});

var Job = sequelize.define('Job', {
  id: {type: Sequelize.INTEGER, primarykey: true},
  title: Sequelize.STRING
  by: Sequelize.STRING,
  createdAt: Sequelize.INTEGER,
  text: Sequelize.STRING,
  url: Sequelize.STRING,
  score: Sequelize.INTEGER,
  //figure out how to use array
  dead: Sequelize.BOOLEAN,
  kids: Sequelize.ARRAY(Sequelize.INTEGER),
  deleted: Sequelize.BOOLEAN
});

var Poll = sequelize.define('Poll', {
  id: {type: Sequelize.INTEGER, primarykey: true},
  title: Sequelize.STRING,
  by: Sequelize.STRING,
  createdAt: Sequelize.INTEGER,
  parts: Sequelize.ARRAY(Sequelize.INTEGER),
  text: Sequelize.STRING,
  url: Sequelize.STRING,
  score: Sequelize.INTEGER,
  //figure out how to use array
  kids: Sequelize.ARRAY(Sequelize.INTEGER),
  //optional
  deleted: Sequelize.BOOLEAN,
  dead: Sequelize.BOOLEAN,
});

var PollOption = sequelize.define('PollOption', {
  id: {type: Sequelize.INTEGER, primarykey: true},
  by: Sequelize.STRING,
  parent: Sequelize.INTEGER,
  score: Sequelize.INTEGER,
  text: Sequelize.STRING,
  createdAt: Sequelize.INTEGER,
  //figure out how to use array
  kids: Sequelize.ARRAY(Sequelize.INTEGER),
  url: Sequelize.STRING,
  dead: Sequelize.BOOLEAN,
  deleted: Sequelize.BOOLEAN,
  title: Sequelize.STRING
});

var User = sequelize.define('User', {
  id: {type: Sequelize.STRING, unique: true, primarykey: true},
  about: Sequelize.STRING,
  createdAt: Sequelize.INTEGER,
  delay: Sequelize.INTEGER,
  karma: Sequelize.INTEGER,
  submitted: Sequelize.ARRAY(Sequelize.INTEGER)
});<|endoftext|>


<commit_before>// This script connects the app to the database

var mongoose = require('mongoose')

// Connect to the database
// The connection is made asynchronously.  Mongoose will queue up database
// operations and release them when the connection is complete.
console.log('Attempting to connect to the database.')
var mongoDBURI = process.env.MONGODB_URI
if (typeof (mongoDBURI) === 'undefined') {
  console.log("No database URI has been set in this app's config file. You must set the config variable 'MONGODB_URI' to point to a MongoDB database.")
  process.exit(1)
}
mongoose.connect(mongoDBURI, function (error, res) {
  if (error) {
    console.log('Connecting to the database failed. Databse URI: %s, Error: %s.', mongoDBURI, error)
  } else {
    console.log('Connecting to the database succeeded.')
  }
})
<commit_msg>Killing the process if database connection fails<commit_after>// This script connects the app to the database

var mongoose = require('mongoose')

// Connect to the database
// The connection is made asynchronously.  Mongoose will queue up database
// operations and release them when the connection is complete.
console.log('Attempting to connect to the database.')
var mongoDBURI = process.env.MONGODB_URI
if (typeof (mongoDBURI) === 'undefined') {
  console.log("No database URI has been set in this app's config file. You must set the config variable 'MONGODB_URI' to point to a MongoDB database.")
  process.exit(1)
}
mongoose.connect(mongoDBURI, function (error, res) {
  if (error) {
    console.log('Connecting to the database failed. Databse URI: %s, Error: %s.', mongoDBURI, error)
    process.exit(1)
  } else {
    console.log('Connecting to the database succeeded.')
  }
})
<|endoftext|>