1 | const promisesTranslateTree = {};
|
2 | const _ = require('lodash');
|
3 | const PromiseBlue = require('bluebird');
|
4 |
|
5 | class AsksuiteTreeManagerGeneral {
|
6 | constructor({
|
7 | CompanyMap,
|
8 | TreeMap,
|
9 | IntentsMap,
|
10 | AsksuiteUtil,
|
11 | AsksuiteService,
|
12 | InitMap,
|
13 | getLanguages,
|
14 | translator,
|
15 | wait,
|
16 | }) {
|
17 | this.CompanyMap = CompanyMap;
|
18 | this.TreeMap = TreeMap;
|
19 | this.getLanguages = getLanguages;
|
20 | this.IntentsMap = IntentsMap;
|
21 | this.AsksuiteUtil = AsksuiteUtil;
|
22 | this.translator = translator;
|
23 | this.AsksuiteService = AsksuiteService;
|
24 | this.InitMap = InitMap;
|
25 | this.wait = wait;
|
26 | }
|
27 |
|
28 | getLanguagesByCompany(chatTreeId) {
|
29 | const company =
|
30 | this.CompanyMap.get(chatTreeId) || this.CompanyMap.get(chatTreeId.split('.')[1]);
|
31 | if (company && !_.isEmpty(company.languages)) {
|
32 | return company.languages;
|
33 | }
|
34 |
|
35 | const languages = [];
|
36 |
|
37 | let flag = null;
|
38 | let languageFlag = null;
|
39 | const regex = /https:\/\/lipis\.github\.io\/flag-icon-css\/flags\/4x3\/(\w+)\.svg/;
|
40 |
|
41 | if (company && company.languageFlags) {
|
42 | const addLanguage = (attrLanguageFlag, defaultFlag, prefixLanguage, defaultLanguage) => {
|
43 | if ((languageFlag = _.get(company.languageFlags, attrLanguageFlag, ''))) {
|
44 | flag = _.get(languageFlag.match(regex), '1', defaultFlag);
|
45 | languages.push(`${prefixLanguage}-${flag}`);
|
46 | } else {
|
47 | languages.push(defaultLanguage);
|
48 | }
|
49 | };
|
50 |
|
51 | addLanguage('pt_br', 'br', 'pt', 'pt-br');
|
52 | languages.push('en-us');
|
53 | addLanguage('es', 'es', 'es', 'es-es');
|
54 | } else {
|
55 | return ['pt-br', 'en-us', 'es-es'];
|
56 | }
|
57 |
|
58 | return languages;
|
59 | }
|
60 |
|
61 | resolveDefaultLanguage(languages, language) {
|
62 | if (languages.includes(language)) {
|
63 | return language;
|
64 | }
|
65 |
|
66 | return _.find(languages, l => l.substring(0, 2) === language.substring(0, 2)) || language;
|
67 | }
|
68 |
|
69 | resolveLanguage(paramLanguage, companyId) {
|
70 | let languages = this.getLanguages();
|
71 | companyId = companyId || '';
|
72 | const company = this.CompanyMap.get(companyId) || this.CompanyMap.get(companyId.split('.')[1]);
|
73 | if (company && !_.isEmpty(company.languages)) {
|
74 | languages = _.filter(languages, l => _.includes(company.languages, l.formatIso));
|
75 | }
|
76 | return this.AsksuiteUtil.resolveLanguage(paramLanguage, languages);
|
77 | }
|
78 |
|
79 | flushTreeMapKeys(keys) {
|
80 | const languages = this.getLanguages();
|
81 | if (keys && Array.isArray(keys)) {
|
82 | languages.forEach(({ formatIso }) => {
|
83 | keys.forEach(key => {
|
84 | const treeInstance = this.resolveTreeInstance(formatIso);
|
85 | if (treeInstance.has(key)) {
|
86 | treeInstance.delete(key);
|
87 | }
|
88 | });
|
89 | });
|
90 | }
|
91 | }
|
92 |
|
93 | resolveTreeInstance(language, companyId) {
|
94 | language = this.resolveLanguage(language, companyId);
|
95 | if (!this.TreeMap.has(language)) {
|
96 | this.TreeMap.set(language, new Map());
|
97 | }
|
98 |
|
99 | return this.TreeMap.get(language);
|
100 | }
|
101 |
|
102 | isTreeAlreadyRegistred(chatTreeId, paramLanguage) {
|
103 | const company =
|
104 | this.CompanyMap.get(chatTreeId) || this.CompanyMap.get(chatTreeId.split('.')[1]);
|
105 | if (!paramLanguage && company) {
|
106 | return this.resolveTreeInstance(company.defaultLanguage, chatTreeId).has(chatTreeId);
|
107 | }
|
108 | return this.resolveTreeInstance(paramLanguage, chatTreeId).has(chatTreeId);
|
109 | }
|
110 |
|
111 | async recursiveDialog(map, node) {
|
112 | if (node.children) {
|
113 | node.children.forEach(async item => {
|
114 | map.set(item.dialog, item);
|
115 | await this.recursiveDialog(map, item);
|
116 | });
|
117 | }
|
118 | }
|
119 |
|
120 | async initTreeMap(map, tree) {
|
121 | map.set(tree.json.dialog, tree.json);
|
122 | await this.recursiveDialog(map, tree.json);
|
123 | }
|
124 |
|
125 | initTreeByLanguage(language, languageFrom, tree, needTranslate, languages) {
|
126 | const treeInstance = this.resolveTreeInstance(language, tree.chatTreeId);
|
127 |
|
128 | return new Promise((resolve, reject) => {
|
129 | (async () => {
|
130 | if (needTranslate) {
|
131 | console.time(`${tree.chatTreeId}: ${languageFrom} -> ${language}`);
|
132 | tree = await this.translator
|
133 | .translate(tree, language, languageFrom, languages)
|
134 | .catch(reject);
|
135 | console.timeEnd(`${tree.chatTreeId}: ${languageFrom} -> ${language}`);
|
136 | }
|
137 | await this.initTreeMap(treeInstance, tree).catch(reject);
|
138 |
|
139 | resolve();
|
140 | })();
|
141 | });
|
142 | }
|
143 |
|
144 | async initTreesByCompanyIDIfNeeded(idsTrees, paramLanguage) {
|
145 | return Promise.all(
|
146 | _.map(idsTrees, async idTree => {
|
147 | const language = this.resolveLanguage(paramLanguage, idTree);
|
148 | if (!this.isTreeAlreadyRegistred(idTree, language)) {
|
149 | await this.initTreeByCompanyID(idTree, language);
|
150 | }
|
151 | }),
|
152 | );
|
153 | }
|
154 |
|
155 | async initTreeByCompanyID(idTree, paramLanguage) {
|
156 | const language = this.resolveLanguage(paramLanguage, idTree);
|
157 | let key = `${idTree}`;
|
158 | if (language) {
|
159 | key += `-${language}`;
|
160 | }
|
161 | if (!this.InitMap.get(idTree) && !(language && this.InitMap.get(key))) {
|
162 | this.InitMap.set(key, true);
|
163 | const tree = await this.AsksuiteService.findTreeByCompanyId(idTree);
|
164 | const result = await this.initTree(tree, language).catch(e => {
|
165 | return { error: true, e };
|
166 | });
|
167 | this.InitMap.delete(key);
|
168 | if (result && result.error) {
|
169 | throw result.e;
|
170 | }
|
171 | } else {
|
172 | await this.wait.until(function() {
|
173 | return !this.InitMap.get(idTree) && !(language && this.InitMap.get(key));
|
174 | });
|
175 | }
|
176 | }
|
177 |
|
178 | async initTree(tree, language) {
|
179 | if (promisesTranslateTree[tree.chatTreeId]) {
|
180 | return promisesTranslateTree[tree.chatTreeId]
|
181 | .catch(e => console.log('error initTree', e))
|
182 | .then(() => this.initTree(tree, language));
|
183 | }
|
184 |
|
185 | promisesTranslateTree[tree.chatTreeId] = new Promise(resolve => {
|
186 | (async () => {
|
187 | console.log('init initTree', tree.chatTreeId);
|
188 | this.IntentsMap.set(tree.chatTreeId, tree.intents);
|
189 |
|
190 | let languages = this.getLanguagesByCompany(tree.chatTreeId);
|
191 | const defaultLanguage = this.resolveDefaultLanguage(languages, tree.defaultLanguage);
|
192 |
|
193 | if (language) {
|
194 | const lang = this.resolveDefaultLanguage(languages, language);
|
195 | languages = _.filter(languages, l => l === lang);
|
196 |
|
197 | if (
|
198 | !this.isTreeAlreadyRegistred(tree.chatTreeId, defaultLanguage) &&
|
199 | !_.includes(languages, defaultLanguage)
|
200 | ) {
|
201 | languages.push(defaultLanguage);
|
202 | }
|
203 | }
|
204 |
|
205 | const allLanguages = this.getLanguages();
|
206 |
|
207 | try {
|
208 | await PromiseBlue.map(
|
209 | languages,
|
210 | lang => {
|
211 | return this.initTreeByLanguage(
|
212 | lang,
|
213 | defaultLanguage,
|
214 | tree,
|
215 | lang !== defaultLanguage,
|
216 | allLanguages,
|
217 | );
|
218 | },
|
219 | { concurrency: 1 },
|
220 | );
|
221 | } catch (e) {
|
222 | console.log('error on initTree', e);
|
223 | } finally {
|
224 | console.log('end initTree', tree.chatTreeId);
|
225 | resolve();
|
226 | delete promisesTranslateTree[tree.chatTreeId];
|
227 | }
|
228 | })();
|
229 | });
|
230 |
|
231 | return promisesTranslateTree[tree.chatTreeId];
|
232 | }
|
233 | }
|
234 |
|
235 | module.exports = {
|
236 | AsksuiteTreeManagerGeneral,
|
237 | };
|