UNPKG

7.15 kBJavaScriptView Raw
1const AWSLambdaCaller = require('./services/AWSLambdaCaller');
2const accounting = require('accounting');
3const fallbackIntents = require('./util/fallbackIntent');
4const _ = require('lodash');
5const request = require('request');
6
7const str = [
8 'oi',
9 'oi',
10 'ola',
11 'bom dia',
12 'boa tarde',
13 'boa noite',
14 'como vai',
15 'ei',
16 'oii',
17 'oiii',
18 'oiiii',
19 'oiiiii',
20 'oiiiiii',
21 'oiiiiiii',
22 'ooi',
23 'oooi',
24 'oooii',
25 'ooooii',
26 'ooooiii',
27 'oola',
28 'olaa',
29 'olaaa',
30 'hola',
31 'holaa',
32 'heloo',
33 'hello',
34 'helooo',
35 'hellooo',
36 'booa',
37 'boaa',
38 'tudo bem',
39 'tudo bem',
40 'como vai',
41 'tudo certo',
42 'obrigado',
43 'certo',
44 'entendi',
45 'entendi mas',
46 'certo mas',
47 'olá!',
48 'ola!',
49];
50
51class Util {
52 static isPhrase(phrase) {
53 return phrase.split(' ').length >= 3;
54 }
55
56 static wordInString(s, words, replacement) {
57 s = Util.removeDotsAndComma(s);
58
59 const re = new RegExp('(\\s|^)(?:' + words.join('|') + ')(?=\\s|$)');
60 return s.replace(re, replacement);
61 }
62
63 static removeDotsAndComma(phrase) {
64 const regex = /[.,]/g;
65 return phrase.replace(regex, '');
66 }
67
68 static replaceIfIsPhrase(phrase) {
69 phrase = phrase.toLowerCase();
70 phrase = phrase.trim();
71 return Util.isPhrase(phrase) ? Util.wordInString(phrase, str, '').trim() : phrase;
72 }
73
74 static capitalizeFirstLetter(string) {
75 return string.charAt(0).toUpperCase() + string.slice(1);
76 }
77
78 static dateDiffInDays(a, b) {
79 const _MS_PER_DAY = 1000 * 60 * 60 * 24;
80 // Discard the time and time-zone information.
81 const utc1 = Date.UTC(a.getFullYear(), a.getMonth(), a.getDate());
82 const utc2 = Date.UTC(b.getFullYear(), b.getMonth(), b.getDate());
83
84 return Math.floor((utc2 - utc1) / _MS_PER_DAY);
85 }
86
87 static toReal(numero) {
88 let num = numero;
89
90 if (typeof numero === 'string') {
91 num = Number.parseFloat(numero);
92 }
93
94 return accounting.formatMoney(num, 'R$ ', 2, '.', ',');
95 }
96
97 static letterCount(str) {
98 let i = 0,
99 seq = 0;
100 const results = [];
101
102 while (i < str.length) {
103 const current = str[i],
104 next = str[i + 1];
105
106 if (typeof results[seq] === 'undefined') {
107 results[seq] = [current, 0];
108 }
109
110 results[seq][1]++;
111
112 if (current !== next) {
113 seq++;
114 }
115
116 i++;
117 }
118
119 return results;
120 }
121
122 static isNumeric(n) {
123 return !isNaN(parseFloat(n)) && isFinite(n);
124 }
125
126 static existsletterCount(str, letterMaxCount = 3) {
127 let value = false;
128
129 if (str != null) {
130 const letterCount = Util.letterCount(str);
131 if (letterCount && letterCount.length > 0) {
132 const find = letterCount.find(item => {
133 return item[1] >= letterMaxCount;
134 });
135
136 value = find != null;
137 }
138 }
139 return value;
140 }
141
142 static isNaoentendi(intent) {
143 const namesFallbackIntents = _.chain(fallbackIntents)
144 .values()
145 .map('intent')
146 .value();
147 if (intent && namesFallbackIntents.indexOf(intent) > -1) {
148 return true;
149 }
150 return false;
151 }
152
153 static getPriceAsFloat(string) {
154 try {
155 const numberString = string.match(/(?:[\d\.,])+/)[0];
156
157 const dot = numberString.length - numberString.lastIndexOf('.') - 1;
158 const comma = numberString.length - numberString.lastIndexOf(',') - 1;
159 const decimal = dot < comma ? dot : comma;
160
161 let number = numberString.replace(/\D/g, '');
162 number = Number(number) / Math.pow(10, decimal);
163
164 return number;
165 } catch (e) {
166 return null;
167 }
168 }
169
170 static getPriceExtremes(results) {
171 if (!Array.isArray(results) || !results.length) {
172 return { minimumPrice: null, maximumPrice: null };
173 }
174
175 const sortedPrices = _.chain(results)
176 .map(e => Util.getPriceAsFloat(e.price))
177 .sortBy()
178 .value();
179
180 return {
181 minimumPrice: _.head(sortedPrices),
182 maximumPrice: _.last(sortedPrices),
183 };
184 }
185
186 static getDateAndTimeFromDateISO(dateISO) {
187 if (dateISO && dateISO.length >= 10) {
188 const [date, time] = dateISO.split('T');
189 const timeOrNull = time ? time.split('.')[0] : null;
190
191 return [date, timeOrNull];
192 } else {
193 return [null, null];
194 }
195 }
196
197 static appendTimeISOStringToDate(
198 date,
199 hour = '00',
200 minutes = '00',
201 seconds = '00',
202 milliseconds = '000',
203 ) {
204 return date ? `${date}T${hour}:${minutes}:${seconds}.${milliseconds}` : null;
205 }
206
207 /**
208 * Returns a function that caches any promise return from a 1-arity function, using the parameter as the cache key.
209 * If the original promise rejects, tries to hit the cache, else, continues the rejection chain.
210 *
211 * Usage:
212 * ```
213 * const cacheWrapper = fallbackCacheFactory(new Map());
214 * cacheWrapper(x => new Promise( /* Implementation *\/ ))
215 * ```
216 *
217 * @param cache<Map>
218 * @returns {function(Map): function(*): Promise<*>}
219 */
220 static fallbackCacheFactory(cache) {
221 return f => x =>
222 f(x)
223 .then(
224 result => new Promise(resolve => cache.set(x, _.cloneDeep(result)) && resolve(result)),
225 )
226 .catch(
227 err =>
228 new Promise(
229 (resolve, reject) =>
230 (cache.has(x) && resolve(_.cloneDeep(cache.get(x)))) || reject(err),
231 ),
232 );
233 }
234
235 static wrapperSaveRequestOnQueue(config) {
236 const addCreatedAtAndUpdatedAtOnUrl = url => {
237 url += /\?|&/.test(url) ? '&' : '?';
238 const date = new Date().getTime();
239 url += `createdAt=${date}&updatedAt=${date}`;
240 return url;
241 };
242
243 const isErrorToSaveOnQueue = ({ error, response }) => {
244 if (error) {
245 return ['ENOTFOUND', 'ECONNREFUSED', 'ESOCKETTIMEDOUT'].includes(error.code);
246 }
247
248 if (response) {
249 return [404].includes(response.statusCode);
250 }
251 };
252
253 const awsLambdaCaller = new AWSLambdaCaller(config.CORE_LAMBDA_AWS);
254
255 return (wrapped, requestInfo) => {
256 return wrapped(requestInfo).catch(async error => {
257 if (!isErrorToSaveOnQueue(error)) {
258 return Promise.reject(error);
259 }
260
261 if (process.env.NODE_ENV === 'dev') {
262 console.log('not send request to lambda');
263 return Promise.reject(error);
264 }
265
266 console.log('sending request to lambda control-requests');
267
268 const clonnedRequestInfo = _.cloneDeep(requestInfo);
269
270 clonnedRequestInfo.request.url = addCreatedAtAndUpdatedAtOnUrl(
271 clonnedRequestInfo.request.url,
272 );
273
274 await awsLambdaCaller.call(
275 clonnedRequestInfo,
276 'asksuite-lambda-sqs-dev-control-requests-insert',
277 );
278 return Promise.reject(error);
279 });
280 };
281 }
282
283 static executeRequestAndSaveOnError(requestInfo, config) {
284 return Util.wrapperSaveRequestOnQueue(config)(() => {
285 return new Promise((resolve, reject) => {
286 request(requestInfo.request, function(err, _resp, _body) {
287 if (err || _resp.statusCode >= 400) {
288 reject({ error: err, response: _resp });
289 } else {
290 resolve(_body);
291 }
292 });
293 });
294 }, requestInfo);
295 }
296}
297
298module.exports = Util;