<commit_before>import baseLogger from './logger.js';

// definition http://translate.sourceforge.net/wiki/l10n/pluralforms
/* eslint-disable */
let sets = [
  { lngs: ['ach','ak','am','arn','br','fil','gun','ln','mfe','mg','mi','oc', 'pt', 'pt-BR',
    'tg','ti','tr','uz','wa'], nr: [1,2], fc: 1 },

  { lngs: ['af','an','ast','az','bg','bn','ca','da','de','dev','el','en',
    'eo','es','et','eu','fi','fo','fur','fy','gl','gu','ha','hi',
    'hu','hy','ia','it','kn','ku','lb','mai','ml','mn','mr','nah','nap','nb',
    'ne','nl','nn','no','nso','pa','pap','pms','ps','pt-PT','rm','sco',
    'se','si','so','son','sq','sv','sw','ta','te','tk','ur','yo'], nr: [1,2], fc: 2 },

  { lngs: ['ay','bo','cgg','fa','id','ja','jbo','ka','kk','km','ko','ky','lo',
    'ms','sah','su','th','tt','ug','vi','wo','zh'], nr: [1], fc: 3 },

  { lngs: ['be','bs', 'cnr', 'dz','hr','ru','sr','uk'], nr: [1,2,5], fc: 4 },

  { lngs: ['ar'], nr: [0,1,2,3,11,100], fc: 5 },
  { lngs: ['cs','sk'], nr: [1,2,5], fc: 6 },
  { lngs: ['csb','pl'], nr: [1,2,5], fc: 7 },
  { lngs: ['cy'], nr: [1,2,3,8], fc: 8 },
  { lngs: ['fr'], nr: [1,2], fc: 9 },
  { lngs: ['ga'], nr: [1,2,3,7,11], fc: 10 },
  { lngs: ['gd'], nr: [1,2,3,20], fc: 11 },
  { lngs: ['is'], nr: [1,2], fc: 12 },
  { lngs: ['jv'], nr: [0,1], fc: 13 },
  { lngs: ['kw'], nr: [1,2,3,4], fc: 14 },
  { lngs: ['lt'], nr: [1,2,10], fc: 15 },
  { lngs: ['lv'], nr: [1,2,0], fc: 16 },
  { lngs: ['mk'], nr: [1,2], fc: 17 },
  { lngs: ['mnk'], nr: [0,1,2], fc: 18 },
  { lngs: ['mt'], nr: [1,2,11,20], fc: 19 },
  { lngs: ['or'], nr: [2,1], fc: 2 },
  { lngs: ['ro'], nr: [1,2,20], fc: 20 },
  { lngs: ['sl'], nr: [5,1,2,3], fc: 21 },
  { lngs: ['he'], nr: [1,2,20,21], fc: 22 }
]

let _rulesPluralsTypes = {
  1: function(n) {return Number(n > 1);},
  2: function(n) {return Number(n != 1);},
  3: function(n) {return 0;},
  4: function(n) {return Number(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);},
  5: function(n) {return Number(n===0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 ? 4 : 5);},
  6: function(n) {return Number((n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2);},
  7: function(n) {return Number(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);},
  8: function(n) {return Number((n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != 11) ? 2 : 3);},
  9: function(n) {return Number(n >= 2);},
  10: function(n) {return Number(n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : 4) ;},
  11: function(n) {return Number((n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : (n > 2 && n < 20) ? 2 : 3);},
  12: function(n) {return Number(n%10!=1 || n%100==11);},
  13: function(n) {return Number(n !== 0);},
  14: function(n) {return Number((n==1) ? 0 : (n==2) ? 1 : (n == 3) ? 2 : 3);},
  15: function(n) {return Number(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);},
  16: function(n) {return Number(n%10==1 && n%100!=11 ? 0 : n !== 0 ? 1 : 2);},
  17: function(n) {return Number(n==1 || n%10==1 ? 0 : 1);},
  18: function(n) {return Number(n==0 ? 0 : n==1 ? 1 : 2);},
  19: function(n) {return Number(n==1 ? 0 : n===0 || ( n%100>1 && n%100<11) ? 1 : (n%100>10 && n%100<20 ) ? 2 : 3);},
  20: function(n) {return Number(n==1 ? 0 : (n===0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2);},
  21: function(n) {return Number(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n%100==4 ? 3 : 0); },
  22: function(n) {return Number(n===1 ? 0 : n===2 ? 1 : (n<0 || n>10) && n%10==0 ? 2 : 3); }
};
/* eslint-enable */

function createRules() {
  const rules = {};
  sets.forEach((set) => {
    set.lngs.forEach((l) => {
      rules[l] = {
        numbers: set.nr,
        plurals: _rulesPluralsTypes[set.fc]
      };
    });
  });
  return rules;
}

class PluralResolver {
  constructor(languageUtils, options = {}) {
    this.languageUtils = languageUtils;
    this.options = options;

    this.logger = baseLogger.create('pluralResolver');

    this.rules = createRules();
  }

  addRule(lng, obj) {
    this.rules[lng] = obj;
  }

  getRule(code) {
    return this.rules[code] || this.rules[this.languageUtils.getLanguagePartFromCode(code)];
  }

  needsPlural(code) {
    const rule = this.getRule(code);

    return rule && rule.numbers.length > 1;
  }

  getPluralFormsOfKey(code, key) {
    const ret = [];

    const rule = this.getRule(code);

    if (!rule) return ret;

    rule.numbers.forEach((n) => {
      const suffix = this.getSuffix(code, n);
      ret.push(`${key}${suffix}`);
    });

    return ret;
  }

  getSuffix(code, count) {
    const rule = this.getRule(code);

    if (rule) {
      // if (rule.numbers.length === 1) return ''; // only singular

      const idx = rule.noAbs ? rule.plurals(count) : rule.plurals(Math.abs(count));
      let suffix = rule.numbers[idx];

      // special treatment for lngs only having singular and plural
      if (this.options.simplifyPluralSuffix && rule.numbers.length === 2 && rule.numbers[0] === 1) {
        if (suffix === 2) {
          suffix = 'plural';
        } else if (suffix === 1) {
          suffix = '';
        }
      }

      const returnSuffix = () => (
        this.options.prepend && suffix.toString() ? this.options.prepend + suffix.toString() : suffix.toString()
      );

      // COMPATIBILITY JSON
      // v1
      if (this.options.compatibilityJSON === 'v1') {
        if (suffix === 1) return '';
        if (typeof suffix === 'number') return `_plural_${suffix.toString()}`;
        return returnSuffix();
      } else if (/* v2 */ this.options.compatibilityJSON === 'v2') {
        return returnSuffix();
      } else if (/* v3 - gettext index */ this.options.simplifyPluralSuffix && rule.numbers.length === 2 && rule.numbers[0] === 1) {
        return returnSuffix();
      }
      return this.options.prepend && idx.toString() ? this.options.prepend + idx.toString() : idx.toString();
    }

    this.logger.warn(`no plural rule found for: ${code}`);
    return '';
  }
}

export default PluralResolver;
<commit_msg>use == everywhere in the rules (#1461)<commit_after>import baseLogger from './logger.js';

// definition http://translate.sourceforge.net/wiki/l10n/pluralforms
/* eslint-disable */
let sets = [
  { lngs: ['ach','ak','am','arn','br','fil','gun','ln','mfe','mg','mi','oc', 'pt', 'pt-BR',
    'tg','ti','tr','uz','wa'], nr: [1,2], fc: 1 },

  { lngs: ['af','an','ast','az','bg','bn','ca','da','de','dev','el','en',
    'eo','es','et','eu','fi','fo','fur','fy','gl','gu','ha','hi',
    'hu','hy','ia','it','kn','ku','lb','mai','ml','mn','mr','nah','nap','nb',
    'ne','nl','nn','no','nso','pa','pap','pms','ps','pt-PT','rm','sco',
    'se','si','so','son','sq','sv','sw','ta','te','tk','ur','yo'], nr: [1,2], fc: 2 },

  { lngs: ['ay','bo','cgg','fa','id','ja','jbo','ka','kk','km','ko','ky','lo',
    'ms','sah','su','th','tt','ug','vi','wo','zh'], nr: [1], fc: 3 },

  { lngs: ['be','bs', 'cnr', 'dz','hr','ru','sr','uk'], nr: [1,2,5], fc: 4 },

  { lngs: ['ar'], nr: [0,1,2,3,11,100], fc: 5 },
  { lngs: ['cs','sk'], nr: [1,2,5], fc: 6 },
  { lngs: ['csb','pl'], nr: [1,2,5], fc: 7 },
  { lngs: ['cy'], nr: [1,2,3,8], fc: 8 },
  { lngs: ['fr'], nr: [1,2], fc: 9 },
  { lngs: ['ga'], nr: [1,2,3,7,11], fc: 10 },
  { lngs: ['gd'], nr: [1,2,3,20], fc: 11 },
  { lngs: ['is'], nr: [1,2], fc: 12 },
  { lngs: ['jv'], nr: [0,1], fc: 13 },
  { lngs: ['kw'], nr: [1,2,3,4], fc: 14 },
  { lngs: ['lt'], nr: [1,2,10], fc: 15 },
  { lngs: ['lv'], nr: [1,2,0], fc: 16 },
  { lngs: ['mk'], nr: [1,2], fc: 17 },
  { lngs: ['mnk'], nr: [0,1,2], fc: 18 },
  { lngs: ['mt'], nr: [1,2,11,20], fc: 19 },
  { lngs: ['or'], nr: [2,1], fc: 2 },
  { lngs: ['ro'], nr: [1,2,20], fc: 20 },
  { lngs: ['sl'], nr: [5,1,2,3], fc: 21 },
  { lngs: ['he'], nr: [1,2,20,21], fc: 22 }
]

let _rulesPluralsTypes = {
  1: function(n) {return Number(n > 1);},
  2: function(n) {return Number(n != 1);},
  3: function(n) {return 0;},
  4: function(n) {return Number(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);},
  5: function(n) {return Number(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 ? 4 : 5);},
  6: function(n) {return Number((n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2);},
  7: function(n) {return Number(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);},
  8: function(n) {return Number((n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != 11) ? 2 : 3);},
  9: function(n) {return Number(n >= 2);},
  10: function(n) {return Number(n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : 4) ;},
  11: function(n) {return Number((n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : (n > 2 && n < 20) ? 2 : 3);},
  12: function(n) {return Number(n%10!=1 || n%100==11);},
  13: function(n) {return Number(n !== 0);},
  14: function(n) {return Number((n==1) ? 0 : (n==2) ? 1 : (n == 3) ? 2 : 3);},
  15: function(n) {return Number(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);},
  16: function(n) {return Number(n%10==1 && n%100!=11 ? 0 : n !== 0 ? 1 : 2);},
  17: function(n) {return Number(n==1 || n%10==1 ? 0 : 1);},
  18: function(n) {return Number(n==0 ? 0 : n==1 ? 1 : 2);},
  19: function(n) {return Number(n==1 ? 0 : n==0 || ( n%100>1 && n%100<11) ? 1 : (n%100>10 && n%100<20 ) ? 2 : 3);},
  20: function(n) {return Number(n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2);},
  21: function(n) {return Number(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n%100==4 ? 3 : 0); },
  22: function(n) {return Number(n==1 ? 0 : n==2 ? 1 : (n<0 || n>10) && n%10==0 ? 2 : 3); }
};
/* eslint-enable */

function createRules() {
  const rules = {};
  sets.forEach((set) => {
    set.lngs.forEach((l) => {
      rules[l] = {
        numbers: set.nr,
        plurals: _rulesPluralsTypes[set.fc]
      };
    });
  });
  return rules;
}

class PluralResolver {
  constructor(languageUtils, options = {}) {
    this.languageUtils = languageUtils;
    this.options = options;

    this.logger = baseLogger.create('pluralResolver');

    this.rules = createRules();
  }

  addRule(lng, obj) {
    this.rules[lng] = obj;
  }

  getRule(code) {
    return this.rules[code] || this.rules[this.languageUtils.getLanguagePartFromCode(code)];
  }

  needsPlural(code) {
    const rule = this.getRule(code);

    return rule && rule.numbers.length > 1;
  }

  getPluralFormsOfKey(code, key) {
    const ret = [];

    const rule = this.getRule(code);

    if (!rule) return ret;

    rule.numbers.forEach((n) => {
      const suffix = this.getSuffix(code, n);
      ret.push(`${key}${suffix}`);
    });

    return ret;
  }

  getSuffix(code, count) {
    const rule = this.getRule(code);

    if (rule) {
      // if (rule.numbers.length === 1) return ''; // only singular

      const idx = rule.noAbs ? rule.plurals(count) : rule.plurals(Math.abs(count));
      let suffix = rule.numbers[idx];

      // special treatment for lngs only having singular and plural
      if (this.options.simplifyPluralSuffix && rule.numbers.length === 2 && rule.numbers[0] === 1) {
        if (suffix === 2) {
          suffix = 'plural';
        } else if (suffix === 1) {
          suffix = '';
        }
      }

      const returnSuffix = () => (
        this.options.prepend && suffix.toString() ? this.options.prepend + suffix.toString() : suffix.toString()
      );

      // COMPATIBILITY JSON
      // v1
      if (this.options.compatibilityJSON === 'v1') {
        if (suffix === 1) return '';
        if (typeof suffix === 'number') return `_plural_${suffix.toString()}`;
        return returnSuffix();
      } else if (/* v2 */ this.options.compatibilityJSON === 'v2') {
        return returnSuffix();
      } else if (/* v3 - gettext index */ this.options.simplifyPluralSuffix && rule.numbers.length === 2 && rule.numbers[0] === 1) {
        return returnSuffix();
      }
      return this.options.prepend && idx.toString() ? this.options.prepend + idx.toString() : idx.toString();
    }

    this.logger.warn(`no plural rule found for: ${code}`);
    return '';
  }
}

export default PluralResolver;
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2017-present, Facebook, Inc.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

const languages = [
  {
    enabled: true,
    name: 'English',
    tag: 'en',
  },
  {
    enabled: true,
    name: '日本語',
    tag: 'ja',
  },
  {
    enabled: false,
    name: 'العربية',
    tag: 'ar',
  },
  {
    enabled: false,
    name: 'Bosanski',
    tag: 'bs-BA',
  },
  {
    enabled: false,
    name: 'Català',
    tag: 'ca',
  },
  {
    enabled: false,
    name: 'Čeština',
    tag: 'cs',
  },
  {
    enabled: false,
    name: 'Dansk',
    tag: 'da',
  },
  {
    enabled: false,
    name: 'Deutsch',
    tag: 'de',
  },
  {
    enabled: false,
    name: 'Ελληνικά',
    tag: 'el',
  },
  {
    enabled: false,
    name: 'Español',
    tag: 'es-ES',
  },
  {
    enabled: false,
    name: 'فارسی',
    tag: 'fa-IR',
  },
  {
    enabled: false,
    name: 'Suomi',
    tag: 'fi',
  },
  {
    enabled: true,
    name: 'Français',
    tag: 'fr',
  },
  {
    enabled: false,
    name: 'עִברִית',
    tag: 'he',
  },
  {
    enabled: false,
    name: 'Magyar',
    tag: 'hu',
  },
  {
    enabled: false,
    name: 'Bahasa Indonesia',
    tag: 'id-ID',
  },
  {
    enabled: false,
    name: 'Italiano',
    tag: 'it',
  },
  {
    enabled: false,
    name: 'Afrikaans',
    tag: 'af',
  },
  {
    enabled: true,
    name: '한국어',
    tag: 'ko',
  },
  {
    enabled: false,
    name: 'मराठी',
    tag: 'mr-IN',
  },
  {
    enabled: false,
    name: 'Nederlands',
    tag: 'nl',
  },
  {
    enabled: false,
    name: 'Norsk',
    tag: 'no-NO',
  },
  {
    enabled: false,
    name: 'Polskie',
    tag: 'pl',
  },
  {
    enabled: false,
    name: 'Português',
    tag: 'pt-PT',
  },
  {
    enabled: false,
    name: 'Português (Brasil)',
    tag: 'pt-BR',
  },
  {
    enabled: false,
    name: 'Română',
    tag: 'ro',
  },
  {
    enabled: false,
    name: 'Русский',
    tag: 'ru',
  },
  {
    enabled: false,
    name: 'Slovenský',
    tag: 'sk-SK',
  },
  {
    enabled: false,
    name: 'Српски језик (Ћирилица)',
    tag: 'sr',
  },
  {
    enabled: false,
    name: 'Svenska',
    tag: 'sv-SE',
  },
  {
    enabled: false,
    name: 'Türkçe',
    tag: 'tr',
  },
  {
    enabled: false,
    name: 'Українська',
    tag: 'uk',
  },
  {
    enabled: false,
    name: 'Tiếng Việt',
    tag: 'vi',
  },
  {
    enabled: true,
    name: '中文',
    tag: 'zh-CN',
  },
  {
    enabled: true,
    name: '繁體中文',
    tag: 'zh-TW'
  },
];
module.exports = languages;
<commit_msg>update languages.js (#6953)<commit_after>/**
 * Copyright (c) 2017-present, Facebook, Inc.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

const languages = [
  {
    enabled: true,
    name: 'English',
    tag: 'en',
  },
  {
    enabled: true,
    name: '日本語',
    tag: 'ja',
  },
  {
    enabled: false,
    name: 'العربية',
    tag: 'ar',
  },
  {
    enabled: false,
    name: 'Bosanski',
    tag: 'bs-BA',
  },
  {
    enabled: false,
    name: 'Català',
    tag: 'ca',
  },
  {
    enabled: false,
    name: 'Čeština',
    tag: 'cs',
  },
  {
    enabled: false,
    name: 'Dansk',
    tag: 'da',
  },
  {
    enabled: false,
    name: 'Deutsch',
    tag: 'de',
  },
  {
    enabled: false,
    name: 'Ελληνικά',
    tag: 'el',
  },
  {
    enabled: false,
    name: 'Español',
    tag: 'es-ES',
  },
  {
    enabled: false,
    name: 'فارسی',
    tag: 'fa-IR',
  },
  {
    enabled: false,
    name: 'Suomi',
    tag: 'fi',
  },
  {
    enabled: true,
    name: 'Français',
    tag: 'fr',
  },
  {
    enabled: false,
    name: 'עִברִית',
    tag: 'he',
  },
  {
    enabled: false,
    name: 'Magyar',
    tag: 'hu',
  },
  {
    enabled: false,
    name: 'Bahasa Indonesia',
    tag: 'id-ID',
  },
  {
    enabled: false,
    name: 'Italiano',
    tag: 'it',
  },
  {
    enabled: false,
    name: 'Afrikaans',
    tag: 'af',
  },
  {
    enabled: true,
    name: '한국어',
    tag: 'ko',
  },
  {
    enabled: false,
    name: 'मराठी',
    tag: 'mr-IN',
  },
  {
    enabled: false,
    name: 'Nederlands',
    tag: 'nl',
  },
  {
    enabled: false,
    name: 'Norsk',
    tag: 'no-NO',
  },
  {
    enabled: false,
    name: 'Polski',
    tag: 'pl-PL',
  },
  {
    enabled: false,
    name: 'Português',
    tag: 'pt-PT',
  },
  {
    enabled: false,
    name: 'Português (Brasil)',
    tag: 'pt-BR',
  },
  {
    enabled: false,
    name: 'Română',
    tag: 'ro',
  },
  {
    enabled: false,
    name: 'Русский',
    tag: 'ru',
  },
  {
    enabled: false,
    name: 'Slovenský',
    tag: 'sk-SK',
  },
  {
    enabled: false,
    name: 'Српски језик (Ћирилица)',
    tag: 'sr',
  },
  {
    enabled: false,
    name: 'Svenska',
    tag: 'sv-SE',
  },
  {
    enabled: false,
    name: 'Türkçe',
    tag: 'tr',
  },
  {
    enabled: false,
    name: 'Українська',
    tag: 'uk',
  },
  {
    enabled: false,
    name: 'Tiếng Việt',
    tag: 'vi',
  },
  {
    enabled: true,
    name: '中文',
    tag: 'zh-CN',
  },
  {
    enabled: true,
    name: '繁體中文',
    tag: 'zh-TW'
  },
];
module.exports = languages;
<|endoftext|>


<commit_before>const google = require('google');
const request = require('superagent');

const query = {
  filter: 'withbody',
  order: 'desc',
  site: 'stackoverflow',
};

function searchGoogle(term, callback) {
  term = encodeURIComponent(term);
  google(`${term} site:stackoverflow.com`, (err, res) => {
    if (err) {
      callback(err, res);
    }

    console.log(res.links)
    get(res.links, callback);
  });
}

function get(questionId, callback, answers = false) {
  questionId = Array.isArray(questionId) ? parseQuestionId(questionId) : questionId;
  let url = `https://api.stackexchange.com/2.2/questions/${questionId}`;
  if (answers) {
    url += '/answers';
  }

  request
    .get(url)
    .query(query)
    .end(callback);
}

function parseQuestionId(links) {
  const re = /.*stackoverflow.com\/questions\/(\d+)\//;

  return links
    .map(({ link }) => {
      if (link.indexOf('stackoverflow.com') !== -1) {
        const matches = re.exec(link);

        if (matches && matches.length == 2) {
          return matches[1];
        }
      }
    })
    .filter(Boolean)
    .join(';');
}

module.exports = {
  get,
  searchGoogle,
};
<commit_msg>Add api search function<commit_after>const google = require('google');
const request = require('superagent');

const defaultQuery = {
  order: 'desc',
  site: 'stackoverflow',
};

const baseUrl = 'https://api.stackexchange.com/2.2';

function searchGoogle(term, callback) {
  term = encodeURIComponent(term);
  google(`${term} site:stackoverflow.com`, (err, res) => {
    if (err) {
      callback(err, res);
    }

    get(res.links, callback);
  });
}

function searchApi(term, callback) {
  term = encodeURIComponent(term);
  const url = `${baseUrl}/search`;
  request
    .get(url)
    .query(defaultQuery)
    .query({
      sort: 'activity',
      intitle: term,
    })
    .end(callback);
}

function get(questionId, callback, answers = false) {
  questionId = Array.isArray(questionId) ? parseQuestionId(questionId) : questionId;
  let url = `${baseUrl}/questions/${questionId}`;
  if (answers) {
    url += '/answers';
  }

  request
    .get(url)
    .query(defaultQuery)
    .query({
      filter: 'withbody',
    })
    .end(callback);
}

function parseQuestionId(links) {
  const re = /.*stackoverflow.com\/questions\/(\d+)\//;

  return links
    .map(({ link }) => {
      if (link.indexOf('stackoverflow.com') !== -1) {
        const matches = re.exec(link);

        if (matches && matches.length == 2) {
          return matches[1];
        }
      }
    })
    .filter(Boolean)
    .join(';');
}

module.exports = {
  get,
  searchGoogle,
  searchApi,
};
<|endoftext|>


<commit_before>function setup() {
  createCanvas(400, 400);
  console.log("Hallo p5.js in VS Code")
}

function draw() {
  background(0);
}

<commit_msg>Update sketch.js<commit_after>function setup() {
  createCanvas(640, 360);
  console.log("Hallo p5.js in VS Code")
}

function draw() {
  background(146, 82, 161);
}

<|endoftext|>


<commit_before>import React from 'react'
import Metro from '../src/index'

describe('sequence api', () => {
  const testArr = [{ name: 'dog' }, { name: 'cat' }]

  it('transforms an array to a Metro sequence', () => {
    const sequence = Metro.sequence(testArr, [])
    expect(sequence[0].content.name).toBe(testArr[0].name)
  })

  it('uses the default animation settings', () => {
    const sequence = Metro.sequence(testArr, [])

    const defaultAnimation = {
      out: {
        time: 0.4,
        delay: 0
      },
      in: {
        time: 0.4,
        delay: 0
      },
      willEnter: {
        from: { opacity: 0 },
        to: { opacity: 1, ease: 'easeInOut' }
      },
      willLeave: {
        from: {
          opacity: 1
        },
        to: {
          opacity: 0
        }
      }
    }

    expect(sequence[0].animation).toEqual(defaultAnimation)
  })

  it('accepts and overrides default animation settings', () => {
    const defaultAnimationOverrideBase = {
      out: {
        time: 0.5,
        delay: 0
      },
      in: {
        time: 1,
        delay: 0
      },
      willEnter: {
        from: { opacity: 0, y: 50 },
        to: { opacity: 1, y: 0, ease: 'easeInOutQuad' }
      },
      willLeave: {
        from: {
          opacity: 1,
          y: 0
        },
        to: { opacity: 0, y: 50, ease: 'easeInOutQuad' }
      }
    }

    const defaultAnimationOverride = {
      animation: { ...defaultAnimationOverrideBase }
    }

    const sequence = Metro.sequence(testArr, [], defaultAnimationOverride)
    expect(sequence[0].animation).toEqual(defaultAnimationOverrideBase)
  })

  it('overrides default animation per array item though a custom animationmMap', () => {
    const dogMap = {
      in: {
        time: 3,
        delay: 0
      },
      out: {
        time: 1.4,
        delay: 1
      },
      willEnter: {
        from: { opacity: 0, y: 120, x: 30 },
        to: { opacity: 1, y: 0, x: 0, ease: 'easeInOutElastic' }
      }
    }

    const catMap = {
      out: {
        time: 1.4,
        delay: 0
      },
      willEnter: {
        from: { opacity: 0, y: 120, x: -30 },
        to: { opacity: 1, y: 0, x: 0, ease: 'easeInOutElastic' }
      }
    }

    const animationMap = [
      {
        ...dogMap
      },
      {
        ...catMap
      }
    ]
    const sequence = Metro.sequence(testArr, animationMap)

    // dog map
    expect(sequence[0].animation.in).toEqual(dogMap.in)
    expect(sequence[0].animation.out).toEqual(dogMap.out)
    expect(sequence[0].animation.willEnter).toEqual(dogMap.willEnter)
    // cat map
    expect(sequence[1].animation.out).toEqual(catMap.out)
    expect(sequence[1].animation.willEnter).toEqual(catMap.willEnter)
  })
})
<commit_msg>Add tests for combining animation settings<commit_after>import React from 'react'
import Metro from '../src/index'

describe('sequence api', () => {
  const testArr = [{ name: 'dog' }, { name: 'cat' }]

  const defaultAnimation = {
    out: {
      time: 0.4,
      delay: 0
    },
    in: {
      time: 0.4,
      delay: 0
    },
    willEnter: {
      from: { opacity: 0 },
      to: { opacity: 1, ease: 'easeInOut' }
    },
    willLeave: {
      from: { opacity: 1 },
      to: { opacity: 0 }
    }
  }

  it('transforms an array to a Metro sequence', () => {
    const sequence = Metro.sequence(testArr, [])
    expect(sequence[0].content.name).toBe(testArr[0].name)
  })

  it('uses the default animation settings', () => {
    const sequence = Metro.sequence(testArr, [])

    expect(sequence[0].animation).toEqual(defaultAnimation)
  })

  it('accepts and overrides default animation settings', () => {
    const defaultAnimationOverrideBase = {
      out: {
        time: 0.5,
        delay: 0
      },
      in: {
        time: 1,
        delay: 0
      },
      willEnter: {
        from: { opacity: 0, y: 50 },
        to: { opacity: 1, y: 0, ease: 'easeInOutQuad' }
      },
      willLeave: {
        from: {
          opacity: 1,
          y: 0
        },
        to: { opacity: 0, y: 50, ease: 'easeInOutQuad' }
      }
    }

    const defaultAnimationOverride = {
      animation: { ...defaultAnimationOverrideBase }
    }

    const sequence = Metro.sequence(testArr, [], defaultAnimationOverride)
    expect(sequence[0].animation).toEqual(defaultAnimationOverrideBase)
  })

  it('overrides default animation per array item though a custom animationMap', () => {
    const dogMap = {
      in: {
        time: 3,
        delay: 0
      },
      out: {
        time: 1.4,
        delay: 1
      },
      willEnter: {
        from: { opacity: 0, y: 120, x: 30 },
        to: { opacity: 1, y: 0, x: 0, ease: 'easeInOutElastic' }
      }
    }

    const catMap = {
      out: {
        time: 1.4,
        delay: 0
      },
      willEnter: {
        from: { opacity: 0, y: 120, x: -30 },
        to: { opacity: 1, y: 0, x: 0, ease: 'easeInOutElastic' }
      }
    }

    const animationMap = [
      {
        ...dogMap
      },
      {
        ...catMap
      }
    ]
    const sequence = Metro.sequence(testArr, animationMap)

    // dog map
    expect(sequence[0].animation.in).toEqual(dogMap.in)
    expect(sequence[0].animation.out).toEqual(dogMap.out)
    expect(sequence[0].animation.willEnter).toEqual(dogMap.willEnter)
    // cat map
    expect(sequence[1].animation.out).toEqual(catMap.out)
    expect(sequence[1].animation.willEnter).toEqual(catMap.willEnter)
  })

  it('overrides single properties of the default animation settings', () => {
    const defaultAnimationOverride = {
      animation: {
        willEnter: {
          from: { y: -100 },
          to: { y: 0, ease: 'linear' }
        },
        willLeave: {
          from: { y: 100 },
          to: { y: 0 }
        }
      }
    }
    const sequence = Metro.sequence(testArr, [], defaultAnimationOverride)

    const expected = {
      out: {
        time: 0.4,
        delay: 0
      },
      in: {
        time: 0.4,
        delay: 0
      },
      willEnter: {
        from: { opacity: 0, y: -100 },
        to: { opacity: 1, ease: 'linear', y: 0 }
      },
      willLeave: {
        from: { opacity: 1, y: 100 },
        to: { opacity: 0, y: 0 }
      }
    }

    expect(sequence[0].animation).toEqual(expected)
  })

  it('applies single properties in the animationMap to the default animation settings', () => {
    const animationMap = [
      {},
      {
        out: {
          delay: 1
        },
        willLeave: {
          to: { opacity: 0.5 }
        }
      }
    ]
    const sequence = Metro.sequence(testArr, animationMap)

    const expectedSettingsForSecondItem = {
      out: {
        time: 0.4,
        delay: 1
      },
      in: {
        time: 0.4,
        delay: 0
      },
      willEnter: {
        from: { opacity: 0 },
        to: { opacity: 1, ease: 'easeInOut' }
      },
      willLeave: {
        from: { opacity: 1 },
        to: { opacity: 0.5 }
      }
    }

    expect(sequence[0].animation).toEqual(defaultAnimation)
    expect(sequence[1].animation).toEqual(expectedSettingsForSecondItem)
  })

  it('applies single properties in the animationMap to the overridden animation settings', () => {
    const defaultAnimationOverride = {
      animation: {
        willEnter: {
          from: { y: -100 },
          to: { y: 0, ease: 'linear' }
        },
        willLeave: {
          from: { y: 100 },
          to: { y: 0 }
        }
      }
    }
    const animationMap = [
      {},
      {
        out: {
          delay: 1
        },
        willLeave: {
          to: { opacity: 0.5 }
        }
      }
    ]
    const sequence = Metro.sequence(
      testArr,
      animationMap,
      defaultAnimationOverride
    )

    const expectedSettingsForFirstItem = {
      out: {
        time: 0.4,
        delay: 0
      },
      in: {
        time: 0.4,
        delay: 0
      },
      willEnter: {
        from: { opacity: 0, y: -100 },
        to: { opacity: 1, y: 0, ease: 'linear' }
      },
      willLeave: {
        from: { opacity: 1, y: 100 },
        to: { opacity: 0, y: 0 }
      }
    }

    const expectedSettingsForSecondItem = {
      out: {
        time: 0.4,
        delay: 1
      },
      in: {
        time: 0.4,
        delay: 0
      },
      willEnter: {
        from: { opacity: 0, y: -100 },
        to: { opacity: 1, y: 0, ease: 'linear' }
      },
      willLeave: {
        from: { opacity: 1, y: 100 },
        to: { opacity: 0.5, y: 0 }
      }
    }

    expect(sequence[0].animation).toEqual(expectedSettingsForFirstItem)
    expect(sequence[1].animation).toEqual(expectedSettingsForSecondItem)
  })
})
<|endoftext|>


<commit_before>var util = require('util');
var _ = require('lodash');
var Promise = require('bluebird');
var nodemailer = require('nodemailer');
var sendmailTransport = require('nodemailer-sendmail-transport');
var BaseMailer = require('./BaseMailer');

util.inherits(SendMailMailer, BaseMailer);

/**
 * Create new instance of sendmail
 * @constructor
 */
function SendMailMailer() {
  BaseMailer.apply(this, arguments);

  this.setTransporter(nodemailer.createTransport(sendmailTransport(this.get('transporter'))));
}

/**
 * Send mail via sendmail
 * @param {Object} [_config] Additional configuration
 * @returns {Promise}
 */
SendMailMailer.prototype.send = function (_config) {
  var config = _.omit(_.merge({}, this.get(), _config), 'transporter');

  return new Promise(function (resolve, reject) {
    this.getTransporter().sendMail(config, function (error, result) {
      return error ? reject(error) : resolve(result);
    });
  }.bind(this));
};

module.exports = SendMailMailer;
<commit_msg>Rewrite SendMailMailer with ES6<commit_after>import _ from 'lodash';
import nodemailer from 'nodemailer';
import sendmailTransport from 'nodemailer-sendmail-transport';
import BaseMailer from './BaseMailer';

export default class SendMailMailer extends BaseMailer {
  constructor(...args) {
    super(...args);

    this.setProvider(nodemailer.createTransport(sendmailTransport(this.get('provider'))));
  }

  /**
   * Send mail
   * @param {Object} [_config] Additional configuration for overriding
   * @returns {Promise}
   */
  send(_config) {
    let config = _.omit(_.merge({}, this.get(), _config), 'provider');

    return new Promise((resolve, reject) => {
      this.getProvider().sendMail(config, (error, result) => error ? reject(error) : resolve(result));
    });
  }
}
<|endoftext|>


<commit_before>'use strict'
const slapp = require('../slackSetup.js').slapp
const getRadius = require('../radius.js').getRadius
const tinyurl = require('tinyurl');
const request = require('request')

// route functions
const hardcodedLocation = require('./routes/hardcodedGeoRoute.js').hardcodedLocation
const ipGeo = require('./routes/ipGeoRoute.js')
const routeFuncs = require('./routes/routesIndex.js')

//db imports
const firebase    = require('../firebaseSetup.js'),
      db = firebase.db,
      snaps = firebase.snaps,
      tags = firebase.tags,
      users = firebase.users,
      slackDb = firebase.slackDb

let test = function() {
  let state = { requested: Date.now() }
  let teamId = ''
  let teamInfo = {}
  /*
  ifs to determine desktop v mobile
  &&
  browser v slack app
  body.
    token: '', // same as verify_token
    team_id: '',
    team_domain: '',
    channel_id: '',
    channel_name: '',
    user_id: '',
    user_name: ''
  ._slapp.client:
   { api: [Object],
     auth: [Object],
     bots: [Object],
     channels: [Object],
     chat: [Object],
     dnd: [Object],
     emoji: [Object],
     files: [Object],
     groups: [Object],
     im: [Object],
     mpim: [Object],
     oauth: [Object],
     reactions: [Object],
     reminders: [Object],
     pins: [Object],
     rtm: [Object],
     search: [Object],
     stars: [Object],
     team: [Object],
     usergroups: [Object],
     users: [Object] },
  .meta:
    { app_token: '',
      app_user_id: '',
      app_bot_id: '',
      bot_token: '',
      bot_user_id: '',
      bot_user_name: '',
      team_name: '',
      team_domain: '',
      team_resource_id: '',
      error: undefined,
      config: {} },
  */
  slapp.command('/test', (msg, text) => {
    teamInfo = slackDb
      .child(msg.body.team_id)
      .once("value")
      .then(function(obj){
        console.log(obj)
        return obj
      })
    console.log(teamInfo)
    console.log(msg._slapp.client)
    // console.log(msg.meta)
    msg
      .say({
        text: "",
        attachments: [{
          text: 'Where do you want to Jaywalk to?',
          fallback: 'Where to today?',
          callback_id: 'test_callback',
          color: 'good',
          actions: [
          // {
          //     name: 'answer',
          //     text: 'Eventually gets current ip geolocation',
          //     type: 'button',
          //     value: 'ipGeo'
          //   },
          {
              name: 'answer',
              text: 'identity',
              type: 'button',
              value: 'address'
            },
            {
              name: 'answer',
              text: 'WeWork',
              type: 'button',
              value: 'wework'
            },
            {
              name: 'answer',
              text: 'Boomtown',
              type: 'button',
              value: 'boomtown'
            },
            {
              name: 'answer',
              text: 'Download app',
              type: 'button',
              value: 'app'
            },
            {
              name: 'answer',
              text: 'findMe',
              type: 'button',
              value: 'findMe'
            }
          ]
        }]
      })
      .route('requestToDatabase', state, 60)
  })
// slapp.action('test_callback', 'answer', (msg, value) => {
//   msg.respond(msg.body.response_url, `${value} is a good choice!`)
// })

  .route('requestToDatabase', (msg, state) => {
    if(msg.body.action==undefined){
      msg
        .say('Click a button!')
        .route('requestToDatabase', state, 60)
    } else{
      let answer = msg.body.actions[0].value
    }

    if(answer == 'boomtown'){

      // if location is not set -> set location? -> save to team_id in firebase
      // get team_id.location(lat,lng) => ask if they are at that location
      // if no => enter address, zip, or business name
      hardcodedLocation(39.758451,-105.007625, msg, state) //(lat,lng) of boomtown
    }else if(answer == 'wework'){
      hardcodedLocation(40.018689, -105.279993, msg, state) //test: snap #1055
    }else if(answer == 'app'){
      /*
      let device = //variable from device
        if(device == ios){
         // return open("itms-apps://itunes.apple.com/us/app/jaywalk-walk-get-deals/id1171719157?mt=8")

        } else if(device == android){

        }
      */
      return msg.say({
        text: "",
        attachments: [{
          text: '<itms-apps://itunes.apple.com/us/app/jaywalk-walk-get-deals/id1171719157?mt=8|iPhone>',
          callback_id: 'doit_confirm_callback',
          thumb_url: 'https://goo.gl/images/famYEL',
          color: 'good'
        },{
          text: '<market://play.google.com/store/apps/details?id=com.kinetise.appb3e241f4c2ebeba41965ba16c05b2eba&hl=en_GB|Android>',
          callback_id: 'doit_confirm_callback',
          color: 'good'
        }]
      })
    }else if(answer == 'ipGeo'){
      // ipGeo()
      let callback =function(err,res){
      console.log(err,res)
      msg.say(JSON.stringify(res),"this is slack's server location...")
      }

      request.get({
        uri:'http://www.geoplugin.net/json.gp',
        json:true}
        , callback);

    }else if(answer == 'findMe'){
      msg
      .say('<https://jaywalk-geo.herokuapp.com/geoloc.htm|Find me>')//https://jaywalk-geo.herokuapp.com/geoloc.htm
      .route('handleGeoLoc', state, 60)
    }else if(answer == 'address'){
      msg
      .say('')//https://jaywalk-geo.herokuapp.com/geoloc.htm
      .route('handleGeoLoc', state, 60)
    }else{ //handle error
      return msg
        .say("Whoops, you just have to pick a button...")
        .say('Click a button!')
        .route('requestToDatabase', state, 60)
    }
  }) //end .route('requestToDatabase')
  .route('handleGeoLoc',(msg,state) =>{

  }) //end .route( handleGeoLoc
  .route('relaventAsk', (msg,state) => {
    routeFuncs.relaventAsk(msg,state)
  })//end .route(relaventAsk)
}
module.exports = {
  test:test()
}

<commit_msg>value of team obj<commit_after>'use strict'
const slapp = require('../slackSetup.js').slapp
const getRadius = require('../radius.js').getRadius
const tinyurl = require('tinyurl');
const request = require('request')

// route functions
const hardcodedLocation = require('./routes/hardcodedGeoRoute.js').hardcodedLocation
const ipGeo = require('./routes/ipGeoRoute.js')
const routeFuncs = require('./routes/routesIndex.js')

//db imports
const firebase    = require('../firebaseSetup.js'),
      db = firebase.db,
      snaps = firebase.snaps,
      tags = firebase.tags,
      users = firebase.users,
      slackDb = firebase.slackDb

let test = function() {
  let state = { requested: Date.now() }
  let teamId = ''
  let teamInfo = {}
  /*
  ifs to determine desktop v mobile
  &&
  browser v slack app
  body.
    token: '', // same as verify_token
    team_id: '',
    team_domain: '',
    channel_id: '',
    channel_name: '',
    user_id: '',
    user_name: ''
  ._slapp.client:
   { api: [Object],
     auth: [Object],
     bots: [Object],
     channels: [Object],
     chat: [Object],
     dnd: [Object],
     emoji: [Object],
     files: [Object],
     groups: [Object],
     im: [Object],
     mpim: [Object],
     oauth: [Object],
     reactions: [Object],
     reminders: [Object],
     pins: [Object],
     rtm: [Object],
     search: [Object],
     stars: [Object],
     team: [Object],
     usergroups: [Object],
     users: [Object] },
  .meta:
    { app_token: '',
      app_user_id: '',
      app_bot_id: '',
      bot_token: '',
      bot_user_id: '',
      bot_user_name: '',
      team_name: '',
      team_domain: '',
      team_resource_id: '',
      error: undefined,
      config: {} },
  */
  slapp.command('/test', (msg, text) => {
    teamInfo = slackDb
      .child(msg.body.team_id)
      .once("value")
      .then(function(obj){
        console.log(obj.val())
        return obj.val()
      })
    console.log(msg._slapp.client)
    // console.log(msg.meta)
    msg
      .say({
        text: "",
        attachments: [{
          text: 'Where do you want to Jaywalk to?',
          fallback: 'Where to today?',
          callback_id: 'test_callback',
          color: 'good',
          actions: [
          // {
          //     name: 'answer',
          //     text: 'Eventually gets current ip geolocation',
          //     type: 'button',
          //     value: 'ipGeo'
          //   },
          {
              name: 'answer',
              text: 'identity',
              type: 'button',
              value: 'address'
            },
            {
              name: 'answer',
              text: 'WeWork',
              type: 'button',
              value: 'wework'
            },
            {
              name: 'answer',
              text: 'Boomtown',
              type: 'button',
              value: 'boomtown'
            },
            {
              name: 'answer',
              text: 'Download app',
              type: 'button',
              value: 'app'
            },
            {
              name: 'answer',
              text: 'findMe',
              type: 'button',
              value: 'findMe'
            }
          ]
        }]
      })
      .route('requestToDatabase', state, 60)
  })
// slapp.action('test_callback', 'answer', (msg, value) => {
//   msg.respond(msg.body.response_url, `${value} is a good choice!`)
// })

  .route('requestToDatabase', (msg, state) => {
    if(msg.body.action==undefined){
      msg
        .say('Click a button!')
        .route('requestToDatabase', state, 60)
    } else{
      let answer = msg.body.actions[0].value
    }

    if(answer == 'boomtown'){

      // if location is not set -> set location? -> save to team_id in firebase
      // get team_id.location(lat,lng) => ask if they are at that location
      // if no => enter address, zip, or business name
      hardcodedLocation(39.758451,-105.007625, msg, state) //(lat,lng) of boomtown
    }else if(answer == 'wework'){
      hardcodedLocation(40.018689, -105.279993, msg, state) //test: snap #1055
    }else if(answer == 'app'){
      /*
      let device = //variable from device
        if(device == ios){
         // return open("itms-apps://itunes.apple.com/us/app/jaywalk-walk-get-deals/id1171719157?mt=8")

        } else if(device == android){

        }
      */
      return msg.say({
        text: "",
        attachments: [{
          text: '<itms-apps://itunes.apple.com/us/app/jaywalk-walk-get-deals/id1171719157?mt=8|iPhone>',
          callback_id: 'doit_confirm_callback',
          thumb_url: 'https://goo.gl/images/famYEL',
          color: 'good'
        },{
          text: '<market://play.google.com/store/apps/details?id=com.kinetise.appb3e241f4c2ebeba41965ba16c05b2eba&hl=en_GB|Android>',
          callback_id: 'doit_confirm_callback',
          color: 'good'
        }]
      })
    }else if(answer == 'ipGeo'){
      // ipGeo()
      let callback =function(err,res){
      console.log(err,res)
      msg.say(JSON.stringify(res),"this is slack's server location...")
      }

      request.get({
        uri:'http://www.geoplugin.net/json.gp',
        json:true}
        , callback);

    }else if(answer == 'findMe'){
      msg
      .say('<https://jaywalk-geo.herokuapp.com/geoloc.htm|Find me>')//https://jaywalk-geo.herokuapp.com/geoloc.htm
      .route('handleGeoLoc', state, 60)
    }else if(answer == 'address'){
      msg
      .say('')//https://jaywalk-geo.herokuapp.com/geoloc.htm
      .route('handleGeoLoc', state, 60)
    }else{ //handle error
      return msg
        .say("Whoops, you just have to pick a button...")
        .say('Click a button!')
        .route('requestToDatabase', state, 60)
    }
  }) //end .route('requestToDatabase')
  .route('handleGeoLoc',(msg,state) =>{

  }) //end .route( handleGeoLoc
  .route('relaventAsk', (msg,state) => {
    routeFuncs.relaventAsk(msg,state)
  })//end .route(relaventAsk)
}
module.exports = {
  test:test()
}

<|endoftext|>


<commit_before>'use strict'
const slapp = require('../slackSetup.js').slapp
const getRadius = require('../radius.js').getRadius
//db imports
const firebase    = require('../firebaseSetup.js'),
      db = firebase.db,
      snaps = firebase.snaps,
      tags = firebase.tags,
      users = firebase.users

let test = function() {
  let randomNum = 0;

  slapp.command('/test', (msg, text) => {
    randomNum = (Math.floor(Math.random() * 1400) + 200)

    msg
      .say({
        text: '',
        attachments: [{
          text: 'Where do you want to Jaywalk to?',
          fallback: 'Where to today?',
          callback_id: 'doit_confirm_callback',
          actions: [{
              name: 'answer',
              text: 'Suprise Me!',
              type: 'button',
              value: randomNum
            },
            {
              name: 'answer',
              text: 'copy of button',
              type: 'button',
              value: randomNum
            }
          ]
        }]
      })
      .route('getid', {
        id: text
      })
  })
  .route('requestToDatabase', (msg, state) => {
    console.log(randomNum)
    var randSnap = msg.body.actions[0].value || ''
    var randTag = msg.body.actions[0].value || ''

    // user may not have typed text as their next action, ask again and re-route
    if (!randSnap || !randTag) {
      return msg
        .say("Whoops, you just have to pick a button...")
        .say('Click a button!')
        .route('requestToDatabase', state)
    }
    let body
    /*
      function to get client ip and convert to geolocation goes here

    */
    let radius = getRadius(39.752764, -104.877743) //test: snap #1055

    //firebase search by snap lat (start at bottom of circle, end at top)
    let snapLat = snaps
      .orderByChild('lat')
      .startAt(radius[5].lat + "-") // "-"makes a string: required for query
      .endAt(radius[1].lat + "-")
      .once('value')
      .then(function(snap) {
        msg.say(
                // `I found a deal for you:
                // ${body.description}\n
                // ${body.picture}\n
                // ${body.address}\n`
          snap.forEach(function(data) {
            //if returns lng within radius (east/west)
            if (data.val().lng <= radius[0].lng && data.val().lng >= radius[3].lng) {
              // console.log(data.val().title)
              let body = data.val()

                attachments: [{
                text: `I found some deals for you: `,
                // fallback: 'Where to today?',
                // callback_id: 'doit_confirm_callback',
                actions: [{
                    name: 'answer',
                    text: ``,
                    type: 'text',
                    value: randomNum
                    },
                    {
                      name: 'answer',
                      text: 'copy of button',
                      type: 'button',
                      value: randomNum
                    }
                  ]
                }] //end attachments
            } //end if (lng checker)
          }) //end foreach
        ) //end msg.say

      }) //end .then(snap)
    }) //end .route('requestToDatabase')
}
module.exports = {
  test:test()
}

<commit_msg>added return limit<commit_after>'use strict'
const slapp = require('../slackSetup.js').slapp
const getRadius = require('../radius.js').getRadius
//db imports
const firebase    = require('../firebaseSetup.js'),
      db = firebase.db,
      snaps = firebase.snaps,
      tags = firebase.tags,
      users = firebase.users

let test = function() {
  let randomNum = 0;

  slapp.command('/test', (msg, text) => {
    randomNum = (Math.floor(Math.random() * 1400) + 200)

    msg
      .say({
        text: '',
        attachments: [{
          text: 'Where do you want to Jaywalk to?',
          fallback: 'Where to today?',
          callback_id: 'doit_confirm_callback',
          actions: [{
              name: 'answer',
              text: 'Suprise Me!',
              type: 'button',
              value: randomNum
            },
            {
              name: 'answer',
              text: 'test copy of button',
              type: 'button',
              value: randomNum
            }
          ]
        }]
      })
      .route('getid', {
        id: text
      })
  })
  .route('requestToDatabase', (msg, state) => {
    console.log(randomNum)
    var randSnap = msg.body.actions[0].value || ''
    var randTag = msg.body.actions[0].value || ''

    // user may not have typed text as their next action, ask again and re-route
    if (!randSnap || !randTag) {
      return msg
        .say("Whoops, you just have to pick a button...")
        .say('Click a button!')
        .route('requestToDatabase', state)
    }
    let body
    let count = 0
    /*
      function to get client ip and convert to geolocation goes here

    */

    let radius = getRadius(39.752764, -104.877743) //test: snap #1055

    //firebase search by snap lat (start at bottom of circle, end at top)
    let snapLat = snaps
      .orderByChild('lat')
      .startAt(radius[5].lat + "-") // "-"makes a string: required for query
      .endAt(radius[1].lat + "-")
      .once('value')
      .then(function(snap) {
        msg.say(
                // `I found a deal for you:
                // ${body.description}\n
                // ${body.picture}\n
                // ${body.address}\n`
          snap.forEach(function(data) {
            //if returns lng within radius (east/west)
            if (data.val().lng <= radius[0].lng && data.val().lng >= radius[3].lng  && count <3) {
              // console.log(data.val().title)
              let body = data.val()
              count ++

                attachments: [{
                text: `I found some deals for you: `,
                // fallback: 'Where to today?',
                // callback_id: 'doit_confirm_callback',
                actions: [{
                    name: 'answer',
                    text: ``,
                    type: 'text',
                    value: randomNum
                    },
                    {
                      name: 'answer',
                      text: 'copy of button',
                      type: 'button',
                      value: randomNum
                    }
                  ]
                }] //end attachments
            } //end if (lng checker)
          }) //end foreach
        ) //end msg.say

      }) //end .then(snap)
    }) //end .route('requestToDatabase')
}
module.exports = {
  test:test()
}

<|endoftext|>


<commit_before>/*
Copyright 2015 The Kubernetes Authors All rights reserved.

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 app = angular.module('PerfDashApp', ['ngMaterial', 'chart.js']);

var PerfDashApp = function(http, scope) {
    this.http = http;
    this.scope = scope;
    this.metricNames = [];
    this.onClick = this.onClickInternal_.bind(this);
    this.cap = 0;
};

PerfDashApp.prototype.onClickInternal_ = function(data, evt, chart) {
    console.log(this, data, evt, chart);
    if (evt.ctrlKey) {
      this.cap = (chart.scale.min + chart.scale.max) / 2;
      this.labelChanged();
      return;
    }

    // Get location
    // TODO(random-liu): Make the URL configurable if we want to support more
    // buckets in the future.
    window.open("https://k8s-gubernator.appspot.com/build/kubernetes-jenkins/logs/" + this.job + "/" + data[0].label + "/", "_blank");
};

// Fetch data from the server and update the data to display
PerfDashApp.prototype.refresh = function() {
    this.http.get("jobnames")
            .success(function(data) {
                this.jobNames = data;
                //init jobName only if needed
                if (this.jobName == undefined || this.jobNames.indexOf(this.jobName) == -1) {
                    this.jobName = this.jobNames[0];
                }
                this.jobNameChanged();
            }.bind(this))
    .error(function(data) {
        console.log("error fetching result");
        console.log(data);
    });
};

// Update the data to graph, using the selected jobName
PerfDashApp.prototype.jobNameChanged = function() {
    this.http.get("metriccategorynames", {params: {jobname: this.jobName}})
            .success(function(data) {
                    this.metricCategoryNames = data;
                    if (this.metricCategoryNames == undefined ||  this.metricCategoryNames.indexOf(this.metricCategoryName) == -1) {
                         this.metricCategoryName = this.metricCategoryNames[0]
                    }
                    this.metricCategoryNameChanged();
            }.bind(this))
    .error(function(data) {
        console.log("error fetching result");
        console.log(data);
    });
};

// Update the data to graph, using the selected jobName
PerfDashApp.prototype.metricCategoryNameChanged = function() {
    this.http.get("metricnames", {params: {jobname: this.jobName, metriccategoryname: this.metricCategoryName}})
            .success(function(data) {
                    this.metricNames = data;
                    if (this.metricName == undefined ||  this.metricNames.indexOf(this.metricName) == -1) {
                         this.metricName = this.metricNames[0]
                    }
                    this.metricNameChanged();
            }.bind(this))
    .error(function(data) {
        console.log("error fetching result");
        console.log(data);
    });
};

// Update the data to graph, using the selected metricName
PerfDashApp.prototype.metricNameChanged = function() {
    this.http.get("buildsdata", {params: {jobname: this.jobName, metriccategoryname: this.metricCategoryName, metricname: this.metricName}})
            .success(function(data) {
                    this.data = data.builds;
                    this.job = data.job;
                    this.builds = this.getBuilds();
                    this.labels = this.getLabels();
                    this.labelChanged();
            }.bind(this))
    .error(function(data) {
        console.log("error fetching result");
        console.log(data);
    });
};

// Update the data to graph, using selected labels
PerfDashApp.prototype.labelChanged = function() {
    this.seriesData = [];
    this.series = [];
    result = this.getData(this.selectedLabels);
    this.options = null;
    var seriesLabels = null;
    var a = 0;
    for (; a < result.length; a++) {
        if ("unit" in result[a] && "data" in result[a] && result[a].data != {}) {
            // All the unit should be the same
            this.options = {scaleLabel: "<%=value%> "+result[a].unit, animation: false};
            // Start with higher percentiles, since their values are usually strictly higher
            // than lower percentiles, which avoids obscuring graph data. It also orders data
            // in the onHover labels more naturally.
            seriesLabels = Object.keys(result[a].data);
            seriesLabels.sort();
            seriesLabels.reverse();
            break;
        }
    }
    if(this.options == null) {
        return;
    }
    angular.forEach(seriesLabels, function(name) {
        this.seriesData.push(this.getStream(result, name));
        this.series.push(name);
    }, this);
    this.cap = 0;
};

// Get all of the builds for the data set (e.g. build numbers)
PerfDashApp.prototype.getBuilds = function() {
    return Object.keys(this.data)
};

// Verify if selected labels are in label set
function verifySelectedLabels(selectedLabels, allLabels) {
    if (selectedLabels == undefined || allLabels == undefined) {
        return false;
    }

    if (Object.keys(selectedLabels).length != Object.keys(allLabels).length) {
        return false;
    }

    var result = true;
    angular.forEach(selectedLabels, function(value, key) {
        if (!(key in allLabels) || !(value in allLabels[key])) {
            result = false;
        }
    });

   return result;
}

// Get the set of all labels (e.g. 'resources', 'verbs') in the data set
PerfDashApp.prototype.getLabels = function() {
    var set = {};
    angular.forEach(this.data, function(items, build) {
        angular.forEach(items, function(item) {
            angular.forEach(item.labels, function(label, name) {
                if (set[name] == undefined) {
                    set[name] = {}
                }
                set[name][label] = true
            });
        });
    });

    if (!verifySelectedLabels(this.selectedLabels, set)) {
        this.selectedLabels = {}
    }
    var labels = {};
    angular.forEach(set, function(items, name) {
        labels[name] = [];
        angular.forEach(items, function(ignore, item) {
            if (this.selectedLabels[name] == undefined) {
              this.selectedLabels[name] = item;
            }
            labels[name].push(item)
        }, this);
    }, this);
    return labels;
};

// Extract a time series of data for specific labels
PerfDashApp.prototype.getData = function(labels) {
    var result = [];
    angular.forEach(this.data, function(items, build) {
        var hasAnyResult = false;
        angular.forEach(items, function(item) {
            var match = true;
            angular.forEach(labels, function(label, name) {
                if (item.labels[name] != label) {
                    match = false;
                }
            });
            if (match) {
                result.push(item);
                hasAnyResult = true;
            }
        });
        if (!hasAnyResult) {
            // We need to add empty object so result series will still correspond to build series
            result.push({});
        }
    });
    return result;
};

// Given a slice of data, turn it into a time series of numbers
// 'data' is an array of APICallLatency objects
// 'stream' is a selector for latency data, (e.g. 'Perc50')
PerfDashApp.prototype.getStream = function(data, stream) {
    var result = [];
    angular.forEach(data, function(value) {
        var x = undefined
        if ("data" in value) {
            x = value.data[stream];
        }
        //This is a handling for undefined values which cause chart.js to not display plots
        //TODO(krzysied): Check whether new version of chart.js has support for this case
        if (x == undefined) {
            x = 0;
        }
        if (this.cap != 0 && x > this.cap) {
            x = this.cap;
        }
        result.push(x);
    }, this);
    return result;
};

app.controller('AppCtrl', ['$scope', '$http', '$interval', function($scope, $http, $interval) {
    $scope.controller = new PerfDashApp($http, $scope);
    $scope.controller.refresh();

    // Refresh every 10 min.  The data only refreshes every 10 minutes on the server
    $interval($scope.controller.refresh.bind($scope.controller), 600000)
}]);
<commit_msg>omitting stale responses<commit_after>/*
Copyright 2015 The Kubernetes Authors All rights reserved.

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 app = angular.module('PerfDashApp', ['ngMaterial', 'chart.js']);

var PerfDashApp = function(http, scope) {
    this.http = http;
    this.scope = scope;
    this.metricNames = [];
    this.onClick = this.onClickInternal_.bind(this);
    this.cap = 0;
    this.currentCall = 0;
};

PerfDashApp.prototype.onClickInternal_ = function(data, evt, chart) {
    console.log(this, data, evt, chart);
    if (evt.ctrlKey) {
      this.cap = (chart.scale.min + chart.scale.max) / 2;
      this.labelChanged();
      return;
    }

    // Get location
    // TODO(random-liu): Make the URL configurable if we want to support more
    // buckets in the future.
    window.open("https://k8s-gubernator.appspot.com/build/kubernetes-jenkins/logs/" + this.job + "/" + data[0].label + "/", "_blank");
};

// Fetch data from the server and update the data to display
PerfDashApp.prototype.refresh = function() {
    this.http.get("jobnames")
            .success(function(data) {
                this.jobNames = data;
                //init jobName only if needed
                if (this.jobName == undefined || this.jobNames.indexOf(this.jobName) == -1) {
                    this.jobName = this.jobNames[0];
                }
                this.jobNameChanged();
            }.bind(this))
    .error(function(data) {
        console.log("error fetching result");
        console.log(data);
    });
};

// Update the data to graph, using the selected jobName
PerfDashApp.prototype.jobNameChanged = function() {
    this.http.get("metriccategorynames", {params: {jobname: this.jobName}})
            .success(function(data) {
                    this.metricCategoryNames = data;
                    if (this.metricCategoryNames == undefined ||  this.metricCategoryNames.indexOf(this.metricCategoryName) == -1) {
                         this.metricCategoryName = this.metricCategoryNames[0]
                    }
                    this.metricCategoryNameChanged();
            }.bind(this))
    .error(function(data) {
        console.log("error fetching result");
        console.log(data);
    });
};

// Update the data to graph, using the selected jobName
PerfDashApp.prototype.metricCategoryNameChanged = function() {
    this.http.get("metricnames", {params: {jobname: this.jobName, metriccategoryname: this.metricCategoryName}})
            .success(function(data) {
                    this.metricNames = data;
                    if (this.metricName == undefined ||  this.metricNames.indexOf(this.metricName) == -1) {
                         this.metricName = this.metricNames[0]
                    }
                    this.metricNameChanged();
            }.bind(this))
    .error(function(data) {
        console.log("error fetching result");
        console.log(data);
    });
};

// Update the data to graph, using the selected metricName
PerfDashApp.prototype.metricNameChanged = function() {
    var callId = ++this.currentCall;
    this.http.get("buildsdata", {params: {jobname: this.jobName, metriccategoryname: this.metricCategoryName, metricname: this.metricName}})
            .success(function(data) {
                    if (this.currentCall != callId) {
                            return;
                    }
                    this.data = data.builds;
                    this.job = data.job;
                    this.builds = this.getBuilds();
                    this.labels = this.getLabels();
                    this.labelChanged();
            }.bind(this))
    .error(function(data) {
        console.log("error fetching result");
        console.log(data);
    });
};

// Update the data to graph, using selected labels
PerfDashApp.prototype.labelChanged = function() {
    this.seriesData = [];
    this.series = [];
    result = this.getData(this.selectedLabels);
    this.options = null;
    var seriesLabels = null;
    var a = 0;
    for (; a < result.length; a++) {
        if ("unit" in result[a] && "data" in result[a] && result[a].data != {}) {
            // All the unit should be the same
            this.options = {scaleLabel: "<%=value%> "+result[a].unit, animation: false};
            // Start with higher percentiles, since their values are usually strictly higher
            // than lower percentiles, which avoids obscuring graph data. It also orders data
            // in the onHover labels more naturally.
            seriesLabels = Object.keys(result[a].data);
            seriesLabels.sort();
            seriesLabels.reverse();
            break;
        }
    }
    if(this.options == null) {
        return;
    }
    angular.forEach(seriesLabels, function(name) {
        this.seriesData.push(this.getStream(result, name));
        this.series.push(name);
    }, this);
    this.cap = 0;
};

// Get all of the builds for the data set (e.g. build numbers)
PerfDashApp.prototype.getBuilds = function() {
    return Object.keys(this.data)
};

// Verify if selected labels are in label set
function verifySelectedLabels(selectedLabels, allLabels) {
    if (selectedLabels == undefined || allLabels == undefined) {
        return false;
    }

    if (Object.keys(selectedLabels).length != Object.keys(allLabels).length) {
        return false;
    }

    var result = true;
    angular.forEach(selectedLabels, function(value, key) {
        if (!(key in allLabels) || !(value in allLabels[key])) {
            result = false;
        }
    });

   return result;
}

// Get the set of all labels (e.g. 'resources', 'verbs') in the data set
PerfDashApp.prototype.getLabels = function() {
    var set = {};
    angular.forEach(this.data, function(items, build) {
        angular.forEach(items, function(item) {
            angular.forEach(item.labels, function(label, name) {
                if (set[name] == undefined) {
                    set[name] = {}
                }
                set[name][label] = true
            });
        });
    });

    if (!verifySelectedLabels(this.selectedLabels, set)) {
        this.selectedLabels = {}
    }
    var labels = {};
    angular.forEach(set, function(items, name) {
        labels[name] = [];
        angular.forEach(items, function(ignore, item) {
            if (this.selectedLabels[name] == undefined) {
              this.selectedLabels[name] = item;
            }
            labels[name].push(item)
        }, this);
    }, this);
    return labels;
};

// Extract a time series of data for specific labels
PerfDashApp.prototype.getData = function(labels) {
    var result = [];
    angular.forEach(this.data, function(items, build) {
        var hasAnyResult = false;
        angular.forEach(items, function(item) {
            var match = true;
            angular.forEach(labels, function(label, name) {
                if (item.labels[name] != label) {
                    match = false;
                }
            });
            if (match) {
                result.push(item);
                hasAnyResult = true;
            }
        });
        if (!hasAnyResult) {
            // We need to add empty object so result series will still correspond to build series
            result.push({});
        }
    });
    return result;
};

// Given a slice of data, turn it into a time series of numbers
// 'data' is an array of APICallLatency objects
// 'stream' is a selector for latency data, (e.g. 'Perc50')
PerfDashApp.prototype.getStream = function(data, stream) {
    var result = [];
    angular.forEach(data, function(value) {
        var x = undefined
        if ("data" in value) {
            x = value.data[stream];
        }
        //This is a handling for undefined values which cause chart.js to not display plots
        //TODO(krzysied): Check whether new version of chart.js has support for this case
        if (x == undefined) {
            x = 0;
        }
        if (this.cap != 0 && x > this.cap) {
            x = this.cap;
        }
        result.push(x);
    }, this);
    return result;
};

app.controller('AppCtrl', ['$scope', '$http', '$interval', function($scope, $http, $interval) {
    $scope.controller = new PerfDashApp($http, $scope);
    $scope.controller.refresh();

    // Refresh every 10 min.  The data only refreshes every 10 minutes on the server
    $interval($scope.controller.refresh.bind($scope.controller), 600000)
}]);
<|endoftext|>


<commit_before>//TEST
/**
 * Example for creating and working with the Slack RTM API.
 */

/* eslint no-console:0 */

/*******************************************************************************
 * Globals
 */
const RtmClient = require('@slack/client').RtmClient;
const WebClient = require('@slack/client').WebClient;
const MemoryDataStore = require('@slack/client').MemoryDataStore;
const RTM_EVENTS = require('@slack/client').RTM_EVENTS;
const CLIENT_EVENTS = require('@slack/client').CLIENT_EVENTS;
const AWS = require('./AWS_API.js');
const GIT = require('./GITHUB_API.js');
const MAINCTL = require('./mainController.js');
const token = process.env.SLACK_API_TOKEN || '';
const DEBUG = process.env.DEBUG || false;

AWS.DEBUG = DEBUG;

var rtm;
var slackWeb = new WebClient(token);
var problemMessage = 'Looks like there was a problem processing your request.';
var activeConv = [];

/*Jarvis Include*/
var mainController = require('./mainController');

/*******************************************************************************
 * Functions
 */

var handleRtmMessage = function(message) {
    if (DEBUG) { console.log('Message:', message) }
    var text = message.text;
    var firstChar = message.channel.substring(0, 1);

    var initCommands = new RegExp ("^(hey jarvis,? ?)|^(jarvis,? ?)|^(<@"+rtm.activeUserId+">,? ?)", "i");

    //Message is from a channel or group
    if (firstChar === 'C' | firstChar === 'G') {
        if (initCommands.test(text)){
            text = text.replace(initCommands, "");
            if(text.length > 0){
                if (DEBUG) { console.log("Greeting + Command")}
                message.text = text;
                parseCommand(message);
            }else{
                 if (DEBUG) { console.log("Greeting w/o Command")}
                var temp = new Conversation(message.user, message.channel);
                activeConv.push(temp);
                rtm.sendMessage("yes?", message.channel);
            }
        } else{
            var convIndex = getActiveConv(message.user,message.channel);
            if (typeof convIndex == "number"){
                console.log(""+activeConv[convIndex].cmdForResp + message.text);
                message.text = activeConv[convIndex].cmdForResp + message.text;
              parseCommand(message);
              activeConv.splice(convIndex,1);
            }

        }
    }    //Direct Message to Jarvis
    else if (firstChar === 'D') {
        if (initCommands.test(text)){
            text = text.replace(initCommands, "");
            if(text.length > 0){
                 if (DEBUG) { console.log("DM Greeting + Command")}
                rtm.sendMessage("No need for initial commands in Direct Messages.", message.channel);
                message.text = text;
                parseCommand(message);
            }else{
                 if (DEBUG) { console.log("DM Greeting w/o Command")}
                rtm.sendMessage("No need to include initial commands in Direct Messages. Please enter command.", message.channel);
            }
        } else {
            parseCommand(message);
        }
    }

}
var parseCommand = function(message) {
    var text = message.text;
     if (DEBUG) { console.log("Parsing Command: "+text)}
    if (keyMessage(text, 'aws ')) {
        text = text.substring('aws '.length, text.length);
        if (keyMessage(text, 'check ec2 ')) {
            text = text.substring('check ec2 '.length, text.length);
            if (keyMessage(text, 'instance ')) {
                handleMessagePromise(AWS.checkEC2Instance(text.substring('instance '.length, text.length)), message);
            } else {
                handleMessagePromise(AWS.checkEC2(), message);
            }
        } else if (keyMessage(text, 'check number of instances ')) {
            handleMessagePromise(AWS.checkNumInstances(), message);
        } else {
            rtm.sendMessage(rtm.dataStore.getUserById(message.user).name+" I'm sorry, this isn't an AWS command I'm familiar with.", message.channel);
        }
    } else if (keyMessage(text, 'slack ')) {
        text = text.substring('slack '.length, text.length);
        var userRegex = /<@([A-Z|1-9]+.)>/g;
        var channelRegex = /<?#([A-Z0-9]+)(\|\w+>)?/g;
        if (userRegex.test(text)) {
            var user = rtm.dataStore.getUserById(text.replace(userRegex, '$1'));
            handleMessagePromise(slackUserName(user), message);
        } else if (channelRegex.test(text)) {
            var key = text.replace(channelRegex, '$1');
            handleMessagePromise(slackChannelInfo(key), message);
        } else if (keyMessage(text, 'list users ')) {
            handleMessagePromise(slackTeamList(), message);
        } else if (keyMessage(text, 'whoami ')) {
            handleMessagePromise(slackWhoAmI(), message);
        } else if (keyMessage(text, 'whos online ')) {
            handleMessagePromise(slackWhoseOnline(), message);
        } else if (keyMessage(text, 'debug ')) {
            rtm.sendMessage("Debug: "+JSON.stringify(message), message.channel);
        } else {
            rtm.sendMessage("Slack command DNE", message.channel);
        }
    } else if (keyMessage(text, 'git ')) {
		text = text.substring('git '.length, text.length);
			if (keyMessage(text, 'branches')) {
				handleMessagePromise(GIT.checkNumberofFeatureBranches(), message);
			}else if (keyMessage(text, 'pushed')){
				handleMessagePromise(GIT.checkLastPushedtoBranchName(), message);
			}else if (keyMessage(text, 'open pull')){
				handleMessagePromise(GIT.checkLatestPullRequest(), message);
			}else if (keyMessage(text, 'closed pull')){
				handleMessagePromise(GIT.checkLatestClosedPullRequest(), message);
			}else if (keyMessage(text, 'time')){
			     handleMessagePromise(GIT.checkLatestBranchUpdatgeTime(), message);
			}else if (keyMessage(text, 'contributors')){
			     handleMessagePromise(GIT.checkContributors(), message);
			}else {
				    rtm.sendMessage("Git Command does not exist", message.channel);
			}
    }else if (keyMessage(text, 'help ')) {

        handleMessagePromise(MAINCTL.getActiveCommands(), message);

    }
    else if (keyMessage(text, 'wait ')) {
		text = text.substring('wait '.length, text.length);

        if(text.length == 0){
            var temp = new Conversation(message.user, message.channel);
            temp.cmdForResp = 'wait -1 ';
            activeConv.push(temp);
            rtm.sendMessage("I'm Listening for another command", message.channel);
        }else if (keyMessage(text, 'wait -1 ')){
            text = text.substring('wait -1 '.length, text.length);
            console.log("i got to waiting.")
            if (keyMessage(text, 'don\'t wait')){
                var convIndex = getActiveConv(message.user,message.channel);
                    if (convIndex){
                        activeConv.splice(i,1);
                        rtm.sendMessage("Okay, I wont.", message.channel);
                    }
            } else {
                var word = /\w+/i;
                var num = /\d+/i;
                if(word.test(text)){
                    rtm.sendMessage("Weeerddd.", message.channel);
                }else if(num.text(text)){
                    rtm.sendMessage("Numbers.", message.channel);
                }else{
                    rtm.sendMessage("meh.", message.channel);
                }
            }
        }

    }
    else {
        rtm.sendMessage("I'm sorry, this isn't a command I'm familiar with. use `help` command for list of commands", message.channel);
    }
}

/*******************************************************************************
 * Helper functions
 */

function keyMessage(text, key) {
    var temptext = text + ' ';
    if (temptext.length >= key.length && temptext.substring(0, key.length).toLowerCase() === key) {
        return true;
    }
    return false;
}

function handleMessagePromise(promise, message) {
    promise.then(function (resp) {
        rtm.sendMessage(resp, message.channel);
    }, function (err) {
        rtm.sendMessage(problemMessage, message.channel);
        console.log(err);
    });
}

function Conversation(user, channel){
    this.user = user;
    this.channel = channel;
    this.cmdForResp = "";
}
function getActiveConv(user, channel){
    for (var i = 0, len = activeConv.length; i < len; i++){
        if(activeConv[i].user == user && activeConv[i].channel == channel){
             if (DEBUG) {
                console.log("Conversation");
                rtm.sendMessage("processing command .. conversation continued", message.channel);
             }
            return i;
        }

        }
    return undefined;
}
/*******************************************************************************
 * Test stuff
 */
/*
Sample inputs:
aws describe ec2 instance i-0a681657adec3b3ee
aws describe ec2
 */
var mockRTM = function() {
    var readline = require('readline');
    var rl = readline.createInterface({
        input: process.stdin,
        output: process.stdout
    });

    process.stdout.write("Please input your test message text: ");
    rl.on('line', function (line) {
        var message = {
            'text': line,
            'channel': 'D'
        };

        // mocking rtm
        rtm = {};
        rtm.sendMessage = function(message, channel) {
            console.log('----------Response message----------');
            console.log('Text: ' + message);
            console.log('Channel: ' + channel);
        }

        // run the test
        handleRtmMessage(message);
    });
}

/*******************************************************************************
 * main()
 */

var main = function() {
    rtm = new RtmClient(token);
    rtm.start();

    rtm.on(RTM_EVENTS.MESSAGE, handleRtmMessage);

    rtm.on(CLIENT_EVENTS.RTM.AUTHENTICATED, function handleRTMAuthenticated() {
        console.log('Jarvis is Online.');
    });

    rtm.on(RTM_EVENTS.REACTION_ADDED, function handleRtmReactionAdded(reaction) {
        if (DEBUG) { console.log('Reaction added:', reaction)}
        if(reaction.item_user == rtm.activeUserId){
        rtm.sendMessage("Thanks "+rtm.dataStore.getUserById(reaction.user).name,reaction.item.channel);}
    });

    rtm.on(RTM_EVENTS.REACTION_REMOVED, function handleRtmReactionRemoved(reaction) {
        if (DEBUG) { console.log('Reaction removed:', reaction)}
        if(reaction.item_user == rtm.activeUserId){
        rtm.sendMessage(":unamused: :"+reaction.reaction+":",reaction.item.channel);}
    });
}
process.on('SIGINT', function() {
    if(rtm.connected){
      rtm.disconnect();
      console.log("\nJarvis is going offline.")
    }

    process.exit();
});

if (DEBUG) {
    mockRTM();
} else {
    main();
}

/*******************************************************************************
 * SLACK API CALLS
 */
/**
 * Checks the status of all of the EC2 Instances
 * @return {Promise}
 */
var slackWhoseOnline = function() {
    if (exports.DEBUG) { console.log('Slack Web API Called, Who is Online Command') }

    return new Promise(function(fulfill, reject) {
        //query for the status of all instances
        slackWeb.users.list({presence:true}, function teamInfoCb(err, info) {
             if (err) {
                return reject(err);
              } else {
                  var tResponse = "";
                  for(var i = 0; i < info.members.length;i++){
                     if(info.members[i].presence && info.members[i].presence == "active"){
                         if(info.members[i].real_name != "")
                             {
                                 tResponse += info.members[i].profile.first_name + " "
                             }else{
                                 tResponse += info.members[i].name + " "
                             }

                  }
                  }

                fulfill("Online: "+tResponse);
              }
            });
    });
}
/**
 * Checks the status of all of the EC2 Instances
 * @return {Promise}
 */
var slackTeamList = function() {
    if (exports.DEBUG) { console.log('Slack Web API Called, Team Member List Command') }

    return new Promise(function(fulfill, reject) {
        slackWeb.users.list(function teamInfoCb(err, info) {
              if (err) {
                return reject(err);
              } else {
                var userList = info.members
                var tMessage = "There users on this team are: ";
                for(var i = 0; i < userList.length; i++){
                    tMessage += userList[i].real_name+" ("+userList[i].name+"), "
                }
                fulfill(tMessage);
              }
            });
        //query for the status of all instances
    });
}
/**
 * Checks the status of all of the EC2 Instances
 * @return {Promise}
 */
var slackWhoAmI = function() {
    if (exports.DEBUG) { console.log('Slack Web API Called, Team Member List Command') }

    return new Promise(function(fulfill, reject) {
                fulfill("Jarvis Info: <@"+rtm.dataStore.getUserById(rtm.activeUserId).name+"> on team: " + rtm.dataStore.getTeamById(rtm.activeTeamId).name);
    });
}

/**
 * Checks the status of all of the EC2 Instances
 * @return {Promise}
 */
var slackChannelInfo = function(channelName) {
    if (exports.DEBUG) { console.log('Slack Web API Called, Team Member List Command') }

    return new Promise(function(fulfill, reject) {
        slackWeb.channels.info(channelName,function teamInfoCb(err, info) {
              if (err) {
                return reject(err);
              } else {
                  var tResponse = "Channel Lookup: <#" +info.channel.id+"> Members: ";
                  var members = info.channel.members;
                  for (var i = 0; i < members.length; i++){
                      tResponse += rtm.dataStore.getUserById(members[i]).name + " ";
                  }

                fulfill(tResponse);
              }
            });
        //query for the status of all instances
    });
}
/**
 * Checks the status of all of the EC2 Instances
 * @return {Promise}
 */
var slackUserName = function(nameToLook) {
    if (exports.DEBUG) { console.log('Slack Web API Called, Team Member List Command') }

    return new Promise(function(fulfill, reject) {
                fulfill("User lookup: "+nameToLook.real_name/*+" "+JSON.stringify(user)*/);
    });
}<commit_msg>More Code Cleaning, Finished Conversation Construct<commit_after>//TEST
/**
 * Example for creating and working with the Slack RTM API.
 */

/* eslint no-console:0 */

/*******************************************************************************
 * Globals
 */
const RtmClient = require('@slack/client').RtmClient;
const WebClient = require('@slack/client').WebClient;
const MemoryDataStore = require('@slack/client').MemoryDataStore;
const RTM_EVENTS = require('@slack/client').RTM_EVENTS;
const CLIENT_EVENTS = require('@slack/client').CLIENT_EVENTS;
const AWS = require('./AWS_API.js');
const GIT = require('./GITHUB_API.js');
const MAINCTL = require('./mainController.js');
const token = process.env.SLACK_API_TOKEN || '';
const DEBUG = process.env.DEBUG || false;

AWS.DEBUG = DEBUG;

var rtm;
var slackWeb = new WebClient(token);
var problemMessage = 'Looks like there was a problem processing your request.';
var activeConv = [];

/*Jarvis Include*/
var mainController = require('./mainController');

/*******************************************************************************
 * Functions
 */

var handleRtmMessage = function(message) {
    if (DEBUG) { console.log('Message:', message) }
    var text = message.text;
    var firstChar = message.channel.substring(0, 1);

    var initCommands = new RegExp ("^(hey jarvis,? ?)|^(jarvis,? ?)|^(<@"+rtm.activeUserId+">,? ?)", "i");

    //Message is from a channel or group
    if (firstChar === 'C' | firstChar === 'G') {
        if (initCommands.test(text)){
            text = text.replace(initCommands, "");
            if(text.length > 0){
                if (DEBUG) { console.log("Greeting + Command")}
                message.text = text;
                parseCommand(message);
            }else{
                 if (DEBUG) { console.log("Greeting w/o Command")}
                startConversation("", message);
                rtm.sendMessage("yes?", message.channel);
            }
        } else{
            continueConversation(message);
        }
    }    //Direct Message to Jarvis
    else if (firstChar === 'D') {
        if (initCommands.test(text)){
            text = text.replace(initCommands, "");
            if(text.length > 0){
                 if (DEBUG) { console.log("DM Greeting + Command")}
                rtm.sendMessage("No need for initial commands in Direct Messages.", message.channel);
                message.text = text;
                parseCommand(message);
            }else{
                 if (DEBUG) { console.log("DM Greeting w/o Command")}
                rtm.sendMessage("No need to include initial commands in Direct Messages. Please enter command.", message.channel);
            }
        } else {
            parseCommand(message);
        }
    }

}
var parseCommand = function(message) {
    var text = message.text;
     if (DEBUG) { console.log("Parsing Command: "+text)}
    if (keyMessage(text, 'aws ')) {
        text = text.substring('aws '.length, text.length);
        if (keyMessage(text, 'check ec2 ')) {
            text = text.substring('check ec2 '.length, text.length);
            if (keyMessage(text, 'instance ')) {
                handleMessagePromise(AWS.checkEC2Instance(text.substring('instance '.length, text.length)), message);
            } else {
                handleMessagePromise(AWS.checkEC2(), message);
            }
        } else if (keyMessage(text, 'check number of instances ')) {
            handleMessagePromise(AWS.checkNumInstances(), message);
        } else {
            rtm.sendMessage("AWS command does not exist", message.channel);
        }
    } else if (keyMessage(text, 'slack ')) {
        text = text.substring('slack '.length, text.length);
        var userRegex = /<@([A-Z|1-9]+.)>/g;
        var channelRegex = /<?#([A-Z0-9]+)(\|\w+>)?/g;
        if (userRegex.test(text)) {
            var user = rtm.dataStore.getUserById(text.replace(userRegex, '$1'));
            handleMessagePromise(slackUserName(user), message);
        } else if (channelRegex.test(text)) {
            var key = text.replace(channelRegex, '$1');
            handleMessagePromise(slackChannelInfo(key), message);
        } else if (keyMessage(text, 'list users ')) {
            handleMessagePromise(slackTeamList(), message);
        } else if (keyMessage(text, 'whoami ')) {
            handleMessagePromise(slackWhoAmI(), message);
        } else if (keyMessage(text, 'whos online ')) {
            handleMessagePromise(slackWhoseOnline(), message);
        } else if (keyMessage(text, 'debug ')) {
            rtm.sendMessage("Debug: "+JSON.stringify(message), message.channel);
        } else {
            rtm.sendMessage("Slack command does not exist", message.channel);
        }
    } else if (keyMessage(text, 'git ')) {
		text = text.substring('git '.length, text.length);
			if (keyMessage(text, 'branches')) {
				handleMessagePromise(GIT.checkNumberofFeatureBranches(), message);
			}else if (keyMessage(text, 'pushed')){
				handleMessagePromise(GIT.checkLastPushedtoBranchName(), message);
			}else if (keyMessage(text, 'open pull')){
				handleMessagePromise(GIT.checkLatestPullRequest(), message);
			}else if (keyMessage(text, 'closed pull')){
				handleMessagePromise(GIT.checkLatestClosedPullRequest(), message);
			}else if (keyMessage(text, 'time')){
			     handleMessagePromise(GIT.checkLatestBranchUpdatgeTime(), message);
			}else if (keyMessage(text, 'contributors')){
			     handleMessagePromise(GIT.checkContributors(), message);
			}else {
				rtm.sendMessage("Git Command does not exist", message.channel);
			}
    }else if (keyMessage(text, 'help ')) {
        handleMessagePromise(MAINCTL.getActiveCommands(), message);
    }
    //SAMPLE CONVERSATION CONSTRUCT
    else if (keyMessage(text, 'wait ')) {
		text = text.substring('wait '.length, text.length);
        if(text.length == 0){
            startConversation("wait -1 ",message);
            rtm.sendMessage("I'm Listening for another command", message.channel);
        }else if (keyMessage(text, '-1 ')){
            text = text.substring('-1 '.length, text.length);
            if (keyMessage(text, 'don\'t wait ')){
                rtm.sendMessage(endConversation(message)?"Okay, I wont.":"Didn't work.", message.channel);
            } else {
                var word = /[a-z]+/i;
                var num = /[0-9]+/i;
                if(word.test(text)){
                    rtm.sendMessage("Letters.", message.channel);
                }else if(num.test(text)){
                    rtm.sendMessage("Numbers.", message.channel);
                }else{
                    rtm.sendMessage("Neither letters nor numbers.", message.channel);
                }
            }
        }
    }
    else {
        rtm.sendMessage("I'm sorry, this isn't a command I'm familiar with. use `help` command for list of commands", message.channel);
    }
}

/*******************************************************************************
 * Helper functions
 */

function keyMessage(text, key) {
    var temptext = text + ' ';
    if (temptext.length >= key.length && temptext.substring(0, key.length).toLowerCase() === key) {
        return true;
    }
    return false;
}

function handleMessagePromise(promise, message) {
    promise.then(function (resp) {
        rtm.sendMessage(resp, message.channel);
    }, function (err) {
        rtm.sendMessage(problemMessage, message.channel);
        console.log(err);
    });
}
function startConversation (respCmd, message){
    var temp = new Conversation(message.user, message.channel);
    temp.cmdForResp = respCmd;
    activeConv.push(temp);
    if (DEBUG) { console.log("Started Conversatoion: " + message.user + " "+respCmd+". Number of Convos: "+activeConv.length);}
}
function continueConversation (message){
    var convIndex = getActiveConv(message.user,message.channel);
    if (typeof convIndex == "number"){
        if (DEBUG) { console.log("Response Altered Command: "+activeConv[convIndex].cmdForResp + message.text);}
        message.text = activeConv[convIndex].cmdForResp + message.text;
        endConversation(message);
        parseCommand(message);
    }

}
function endConversation (message){
    var convIndex = getActiveConv(message.user,message.channel);
    if (typeof convIndex == "number"){
        activeConv.splice(convIndex,1);
        if (DEBUG) { console.log("ending Conversation:" + message.user+ ". Number of Convos: "+activeConv.length);}
        return true;
    }
    else{
        return false;
    }
}

function Conversation(user, channel){
    this.user = user;
    this.channel = channel;
    this.cmdForResp = "";
}
function getActiveConv(user, channel){
    for (var i = 0, len = activeConv.length; i < len; i++){
        if(activeConv[i].user == user && activeConv[i].channel == channel){
             if (DEBUG) {
                console.log("Conversation");
                rtm.sendMessage("processing command .. conversation continued", message.channel);
             }
            return i;
        }

    }
    return undefined;
}
/*******************************************************************************
 * Test stuff
 */
/*
Sample inputs:
aws describe ec2 instance i-0a681657adec3b3ee
aws describe ec2
 */
var mockRTM = function() {
    var readline = require('readline');
    var rl = readline.createInterface({
        input: process.stdin,
        output: process.stdout
    });

    process.stdout.write("Please input your test message text: ");
    rl.on('line', function (line) {
        var message = {
            'text': line,
            'channel': 'D'
        };

        // mocking rtm
        rtm = {};
        rtm.sendMessage = function(message, channel) {
            console.log('----------Response message----------');
            console.log('Text: ' + message);
            console.log('Channel: ' + channel);
        }

        // run the test
        handleRtmMessage(message);
    });
}

/*******************************************************************************
 * main()
 */

var main = function() {
    rtm = new RtmClient(token);
    rtm.start();

    rtm.on(RTM_EVENTS.MESSAGE, handleRtmMessage);

    rtm.on(CLIENT_EVENTS.RTM.AUTHENTICATED, function handleRTMAuthenticated() {
        console.log('Jarvis is Online.');
    });

    rtm.on(RTM_EVENTS.REACTION_ADDED, function handleRtmReactionAdded(reaction) {
        if (DEBUG) { console.log('Reaction added:', reaction)}
        if(reaction.item_user == rtm.activeUserId){
        rtm.sendMessage("Thanks "+rtm.dataStore.getUserById(reaction.user).name,reaction.item.channel);}
    });

    rtm.on(RTM_EVENTS.REACTION_REMOVED, function handleRtmReactionRemoved(reaction) {
        if (DEBUG) { console.log('Reaction removed:', reaction)}
        if(reaction.item_user == rtm.activeUserId){
        rtm.sendMessage(":unamused: :"+reaction.reaction+":",reaction.item.channel);}
    });
}
process.on('SIGINT', function() {
    if(rtm.connected){
      rtm.disconnect();
      console.log("\nJarvis is going offline.")
    }

    process.exit();
});

if (DEBUG) {
    mockRTM();
} else {
    main();
}

/*******************************************************************************
 * SLACK API CALLS
 */
/**
 * Checks the status of all of the EC2 Instances
 * @return {Promise}
 */
var slackWhoseOnline = function() {
    if (exports.DEBUG) { console.log('Slack Web API Called, Who is Online Command') }

    return new Promise(function(fulfill, reject) {
        //query for the status of all instances
        slackWeb.users.list({presence:true}, function teamInfoCb(err, info) {
             if (err) {
                return reject(err);
              } else {
                  var tResponse = "";
                  for(var i = 0; i < info.members.length;i++){
                     if(info.members[i].presence && info.members[i].presence == "active"){
                         if(info.members[i].real_name != "")
                             {
                                 tResponse += info.members[i].profile.first_name + " "
                             }else{
                                 tResponse += info.members[i].name + " "
                             }

                  }
                  }

                fulfill("Online: "+tResponse);
              }
            });
    });
}
/**
 * Checks the status of all of the EC2 Instances
 * @return {Promise}
 */
var slackTeamList = function() {
    if (exports.DEBUG) { console.log('Slack Web API Called, Team Member List Command') }

    return new Promise(function(fulfill, reject) {
        slackWeb.users.list(function teamInfoCb(err, info) {
              if (err) {
                return reject(err);
              } else {
                var userList = info.members
                var tMessage = "There users on this team are: ";
                for(var i = 0; i < userList.length; i++){
                    tMessage += userList[i].real_name+" ("+userList[i].name+"), "
                }
                fulfill(tMessage);
              }
            });
        //query for the status of all instances
    });
}
/**
 * Checks the status of all of the EC2 Instances
 * @return {Promise}
 */
var slackWhoAmI = function() {
    if (exports.DEBUG) { console.log('Slack Web API Called, Team Member List Command') }

    return new Promise(function(fulfill, reject) {
                fulfill("Jarvis Info: <@"+rtm.dataStore.getUserById(rtm.activeUserId).name+"> on team: " + rtm.dataStore.getTeamById(rtm.activeTeamId).name);
    });
}

/**
 * Checks the status of all of the EC2 Instances
 * @return {Promise}
 */
var slackChannelInfo = function(channelName) {
    if (exports.DEBUG) { console.log('Slack Web API Called, Team Member List Command') }

    return new Promise(function(fulfill, reject) {
        slackWeb.channels.info(channelName,function teamInfoCb(err, info) {
              if (err) {
                return reject(err);
              } else {
                  var tResponse = "Channel Lookup: <#" +info.channel.id+"> Members: ";
                  var members = info.channel.members;
                  for (var i = 0; i < members.length; i++){
                      tResponse += rtm.dataStore.getUserById(members[i]).name + " ";
                  }

                fulfill(tResponse);
              }
            });
        //query for the status of all instances
    });
}
/**
 * Checks the status of all of the EC2 Instances
 * @return {Promise}
 */
var slackUserName = function(nameToLook) {
    if (exports.DEBUG) { console.log('Slack Web API Called, Team Member List Command') }

    return new Promise(function(fulfill, reject) {
                fulfill("User lookup: "+nameToLook.real_name/*+" "+JSON.stringify(user)*/);
    });
}<|endoftext|>