asksuite-core
Version:
299 lines (251 loc) • 7.15 kB
JavaScript
const AWSLambdaCaller = require('./services/AWSLambdaCaller');
const accounting = require('accounting');
const fallbackIntents = require('./util/fallbackIntent');
const _ = require('lodash');
const request = require('request');
const str = [
'oi',
'oi',
'ola',
'bom dia',
'boa tarde',
'boa noite',
'como vai',
'ei',
'oii',
'oiii',
'oiiii',
'oiiiii',
'oiiiiii',
'oiiiiiii',
'ooi',
'oooi',
'oooii',
'ooooii',
'ooooiii',
'oola',
'olaa',
'olaaa',
'hola',
'holaa',
'heloo',
'hello',
'helooo',
'hellooo',
'booa',
'boaa',
'tudo bem',
'tudo bem',
'como vai',
'tudo certo',
'obrigado',
'certo',
'entendi',
'entendi mas',
'certo mas',
'olá!',
'ola!',
];
class Util {
static isPhrase(phrase) {
return phrase.split(' ').length >= 3;
}
static wordInString(s, words, replacement) {
s = Util.removeDotsAndComma(s);
const re = new RegExp('(\\s|^)(?:' + words.join('|') + ')(?=\\s|$)');
return s.replace(re, replacement);
}
static removeDotsAndComma(phrase) {
const regex = /[.,]/g;
return phrase.replace(regex, '');
}
static replaceIfIsPhrase(phrase) {
phrase = phrase.toLowerCase();
phrase = phrase.trim();
return Util.isPhrase(phrase) ? Util.wordInString(phrase, str, '').trim() : phrase;
}
static capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
static dateDiffInDays(a, b) {
const _MS_PER_DAY = 1000 * 60 * 60 * 24;
// Discard the time and time-zone information.
const utc1 = Date.UTC(a.getFullYear(), a.getMonth(), a.getDate());
const utc2 = Date.UTC(b.getFullYear(), b.getMonth(), b.getDate());
return Math.floor((utc2 - utc1) / _MS_PER_DAY);
}
static toReal(numero) {
let num = numero;
if (typeof numero === 'string') {
num = Number.parseFloat(numero);
}
return accounting.formatMoney(num, 'R$ ', 2, '.', ',');
}
static letterCount(str) {
let i = 0,
seq = 0;
const results = [];
while (i < str.length) {
const current = str[i],
next = str[i + 1];
if (typeof results[seq] === 'undefined') {
results[seq] = [current, 0];
}
results[seq][1]++;
if (current !== next) {
seq++;
}
i++;
}
return results;
}
static isNumeric(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
static existsletterCount(str, letterMaxCount = 3) {
let value = false;
if (str != null) {
const letterCount = Util.letterCount(str);
if (letterCount && letterCount.length > 0) {
const find = letterCount.find(item => {
return item[1] >= letterMaxCount;
});
value = find != null;
}
}
return value;
}
static isNaoentendi(intent) {
const namesFallbackIntents = _.chain(fallbackIntents)
.values()
.map('intent')
.value();
if (intent && namesFallbackIntents.indexOf(intent) > -1) {
return true;
}
return false;
}
static getPriceAsFloat(string) {
try {
const numberString = string.match(/(?:[\d\.,])+/)[0];
const dot = numberString.length - numberString.lastIndexOf('.') - 1;
const comma = numberString.length - numberString.lastIndexOf(',') - 1;
const decimal = dot < comma ? dot : comma;
let number = numberString.replace(/\D/g, '');
number = Number(number) / Math.pow(10, decimal);
return number;
} catch (e) {
return null;
}
}
static getPriceExtremes(results) {
if (!Array.isArray(results) || !results.length) {
return { minimumPrice: null, maximumPrice: null };
}
const sortedPrices = _.chain(results)
.map(e => Util.getPriceAsFloat(e.price))
.sortBy()
.value();
return {
minimumPrice: _.head(sortedPrices),
maximumPrice: _.last(sortedPrices),
};
}
static getDateAndTimeFromDateISO(dateISO) {
if (dateISO && dateISO.length >= 10) {
const [date, time] = dateISO.split('T');
const timeOrNull = time ? time.split('.')[0] : null;
return [date, timeOrNull];
} else {
return [null, null];
}
}
static appendTimeISOStringToDate(
date,
hour = '00',
minutes = '00',
seconds = '00',
milliseconds = '000',
) {
return date ? `${date}T${hour}:${minutes}:${seconds}.${milliseconds}` : null;
}
/**
* Returns a function that caches any promise return from a 1-arity function, using the parameter as the cache key.
* If the original promise rejects, tries to hit the cache, else, continues the rejection chain.
*
* Usage:
* ```
* const cacheWrapper = fallbackCacheFactory(new Map());
* cacheWrapper(x => new Promise( /* Implementation *\/ ))
* ```
*
* @param cache<Map>
* @returns {function(Map): function(*): Promise<*>}
*/
static fallbackCacheFactory(cache) {
return f => x =>
f(x)
.then(
result => new Promise(resolve => cache.set(x, _.cloneDeep(result)) && resolve(result)),
)
.catch(
err =>
new Promise(
(resolve, reject) =>
(cache.has(x) && resolve(_.cloneDeep(cache.get(x)))) || reject(err),
),
);
}
static wrapperSaveRequestOnQueue(config) {
const addCreatedAtAndUpdatedAtOnUrl = url => {
url += /\?|&/.test(url) ? '&' : '?';
const date = new Date().getTime();
url += `createdAt=${date}&updatedAt=${date}`;
return url;
};
const isErrorToSaveOnQueue = ({ error, response }) => {
if (error) {
return ['ENOTFOUND', 'ECONNREFUSED', 'ESOCKETTIMEDOUT'].includes(error.code);
}
if (response) {
return [404].includes(response.statusCode);
}
};
const awsLambdaCaller = new AWSLambdaCaller(config.CORE_LAMBDA_AWS);
return (wrapped, requestInfo) => {
return wrapped(requestInfo).catch(async error => {
if (!isErrorToSaveOnQueue(error)) {
return Promise.reject(error);
}
if (process.env.NODE_ENV === 'dev') {
console.log('not send request to lambda');
return Promise.reject(error);
}
console.log('sending request to lambda control-requests');
const clonnedRequestInfo = _.cloneDeep(requestInfo);
clonnedRequestInfo.request.url = addCreatedAtAndUpdatedAtOnUrl(
clonnedRequestInfo.request.url,
);
await awsLambdaCaller.call(
clonnedRequestInfo,
'asksuite-lambda-sqs-dev-control-requests-insert',
);
return Promise.reject(error);
});
};
}
static executeRequestAndSaveOnError(requestInfo, config) {
return Util.wrapperSaveRequestOnQueue(config)(() => {
return new Promise((resolve, reject) => {
request(requestInfo.request, function(err, _resp, _body) {
if (err || _resp.statusCode >= 400) {
reject({ error: err, response: _resp });
} else {
resolve(_body);
}
});
});
}, requestInfo);
}
}
module.exports = Util;