@tiledesk/tiledesk-tybot-connector 0.1.21 → 0.1.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/CHANGELOG.md +10 -1
  2. package/ExtApi.js +37 -0
  3. package/index backup.js +656 -0
  4. package/index.js +58 -461
  5. package/models/IntentForm.js +12 -13
  6. package/models/MockBotsDataSource.js +74 -0
  7. package/models/MockIntentsMachine.js +39 -0
  8. package/models/MongodbBotsDataSource.js +73 -0
  9. package/models/MongodbIntentsMachine.js +55 -0
  10. package/models/{TiledeskChatbot_Intents_Adapter.js → TiledeskChatbot backup.js } +0 -1
  11. package/models/TiledeskChatbot.js +206 -180
  12. package/models/TiledeskIntentsMachine.js +90 -0
  13. package/models/faqKbService.js +27 -0
  14. package/models/faqService.js +22 -0
  15. package/models/faq_kb.js +11 -28
  16. package/package.json +2 -2
  17. package/test/close_directive_test.js +49 -0
  18. package/test/directives_test.js +24 -26
  19. package/test/disable_input_text_directive_test.js +88 -0
  20. package/test/mock_query_test.js +276 -0
  21. package/test/single_test.sh +4 -0
  22. package/test/when_open_directive_test.js +167 -0
  23. package/tiledeskChatbotPlugs/CHANGELOG.md +2 -0
  24. package/tiledeskChatbotPlugs/DirectivesChatbotPlug.js +66 -46
  25. package/tiledeskChatbotPlugs/directives/DirClose.js +25 -0
  26. package/tiledeskChatbotPlugs/directives/DirDeflectToHelpCenter.js +6 -6
  27. package/tiledeskChatbotPlugs/directives/DirDepartment.js +52 -0
  28. package/tiledeskChatbotPlugs/directives/DirDisableInputText.js +45 -0
  29. package/tiledeskChatbotPlugs/directives/DirIntent.js +50 -0
  30. package/tiledeskChatbotPlugs/directives/DirMessage.js +5 -4
  31. package/tiledeskChatbotPlugs/directives/DirWhenOpen.js +95 -0
  32. package/tiledeskChatbotPlugs/directives/Directives.js +3 -0
  33. package/tiledeskChatbotPlugs/package.json +1 -1
  34. package/models/MongoDBIntentsDataSource.js +0 -22
  35. package/models/StaticIntentsDataSource.js +0 -110
  36. package/test/chatbot_query_test.js_ +0 -41
@@ -0,0 +1,167 @@
1
+ var assert = require('assert');
2
+ const { ExtUtil } = require('../ExtUtil');
3
+ const { DirectivesChatbotPlug } = require('../tiledeskChatbotPlugs/DirectivesChatbotPlug');
4
+ const { DirWhenOpen } = require('../tiledeskChatbotPlugs/directives/DirWhenOpen');
5
+ const supportRequest = require('./support_request.js').request;
6
+
7
+ describe('Directive DirWhenOpen', function () {
8
+
9
+ it('test DirWhenOpen (only one directive) checkOpen=true, matching isopen=true', async () => {
10
+ let directives = [
11
+ {
12
+ "name": "whenopen",
13
+ "parameter": "\\_tdintent start"
14
+ }
15
+ ];
16
+
17
+ class MockTdClient {
18
+ openNow(callback) {
19
+ callback(null, { isopen: true });
20
+ }
21
+ };
22
+ current_index = 0;
23
+ when_directive = directives[current_index]
24
+ let dir = new DirWhenOpen({
25
+ tdclient: new MockTdClient()
26
+ });
27
+ dir.execute(when_directive, directives, current_index, () => {
28
+ assert(directives.length == 2);
29
+ assert(directives[1].name === "intent");
30
+ assert(directives[1].parameter === "start");
31
+ });
32
+ });
33
+
34
+ it('test DirWhenOpen (first directive) checkOpen=true, !matching because => isopen=false', async () => {
35
+ let directives = [
36
+ {
37
+ "name": "whenopen",
38
+ "parameter": "\\_tdintent start"
39
+ },
40
+ {
41
+ "name": "dir1"
42
+ },
43
+ {
44
+ "name": "dir3"
45
+ }
46
+ ];
47
+
48
+ class MockTdClient {
49
+ openNow(callback) {
50
+ callback(null, { isopen: false }); // closed
51
+ }
52
+ };
53
+ current_index = 0;
54
+ when_directive = directives[current_index]
55
+ let dir = new DirWhenOpen({
56
+ tdclient: new MockTdClient(),
57
+ checkOpen: true // checking open
58
+ });
59
+ dir.execute(when_directive, directives, current_index, () => {
60
+ assert(directives.length == 3); // keeps the same length
61
+ assert(directives[1].name === "dir1"); // no directives are added
62
+ assert(directives[1].parameter == null);
63
+ });
64
+ });
65
+
66
+ it('test DirWhenOpen (first directive) checkOpen=false, !matching because => isopen=true', async () => {
67
+ let directives = [
68
+ {
69
+ "name": "whenopen",
70
+ "parameter": "\\_tdintent start"
71
+ },
72
+ {
73
+ "name": "dir1"
74
+ },
75
+ {
76
+ "name": "dir3"
77
+ }
78
+ ];
79
+
80
+ class MockTdClient {
81
+ openNow(callback) {
82
+ callback(null, { isopen: true }); // closed
83
+ }
84
+ };
85
+ current_index = 0;
86
+ when_directive = directives[current_index]
87
+ let dir = new DirWhenOpen({
88
+ tdclient: new MockTdClient(),
89
+ checkOpen: false // checking open
90
+ });
91
+ dir.execute(when_directive, directives, current_index, () => {
92
+ assert(directives.length == 3); // keeps the same length
93
+ assert(directives[1].name === "dir1"); // no directives are added
94
+ assert(directives[1].parameter == null);
95
+ });
96
+ });
97
+
98
+ it('test DirWhenOpen (middle directive) checkOpen=true, matching isopen=true', async () => {
99
+ let directives = [
100
+ {
101
+ "name": "dir1"
102
+ },
103
+ {
104
+ "name": "whenopen",
105
+ "parameter": "\\_tdintent start"
106
+ },
107
+ {
108
+ "name": "dir3"
109
+ }
110
+ ];
111
+
112
+ class MockTdClient {
113
+ openNow(callback) {
114
+ callback(null, { isopen: true });
115
+ }
116
+ };
117
+ current_index = 1;
118
+ when_directive = directives[current_index]
119
+ let dir = new DirWhenOpen({
120
+ tdclient: new MockTdClient()
121
+ });
122
+ dir.execute(when_directive, directives, current_index, () => {
123
+ assert(directives.length == 4);
124
+ assert(directives[2].name === "intent");
125
+ assert(directives[2].parameter === "start");
126
+ // done();
127
+ });
128
+ });
129
+
130
+ it('test DirWhenOpen (last directive) checkOpen=false (closed), matching isopen=false', () => {
131
+ let directives = [
132
+ {
133
+ "name": "dir1"
134
+ },
135
+ {
136
+ "name": "dir3"
137
+ },
138
+ {
139
+ "name": "whenopen",
140
+ "parameter": "\\_tdfakedirective --m \"...\""
141
+ }
142
+ ];
143
+
144
+ class MockTdClient {
145
+ openNow(callback) {
146
+ callback(null, { isopen: false }); // closed
147
+ }
148
+ };
149
+ current_index = 2;
150
+ when_directive = directives[current_index]
151
+ let dir = new DirWhenOpen({
152
+ tdclient: new MockTdClient(),
153
+ checkOpen: false, // checks closed
154
+ log: false
155
+ });
156
+ dir.execute(when_directive, directives, current_index, () => {
157
+ assert(directives.length === 4);
158
+ assert(directives[3].name === "fakedirective");
159
+ assert(directives[3].parameter === "--m \"...\"");
160
+ });
161
+
162
+ });
163
+
164
+ });
165
+
166
+
167
+
@@ -1,5 +1,7 @@
1
1
  # Tiledesk Plugs
2
2
 
3
+ ### 0.1.9 DirClose added
4
+
3
5
  ### 0.1.8 online - minor fixes
4
6
 
5
7
  ### 0.1.7 added \_tdDeflectToAgent
@@ -8,7 +8,13 @@ const { DirWait } = require('./directives/DirWait');
8
8
  const { DirReplaceBot } = require('./directives/DirReplaceBot');
9
9
  const { DirLockIntent } = require('./directives/DirLockIntent');
10
10
  const { DirUnlockIntent } = require('./directives/DirUnlockIntent');
11
+ const { DirDepartment } = require('./directives/DirDepartment');
12
+ const { DirIntent } = require('./directives/DirIntent');
13
+ const { DirWhenOpen } = require('./directives/DirWhenOpen');
14
+ const { DirDisableInputText } = require('./directives/DirDisableInputText');
15
+ const { DirClose } = require('./directives/DirClose');
11
16
  const { Directives } = require('./directives/Directives');
17
+ // const { ExtApi } = require('../ExtApi.js');
12
18
 
13
19
  class DirectivesChatbotPlug {
14
20
 
@@ -21,6 +27,7 @@ class DirectivesChatbotPlug {
21
27
  constructor(config) {
22
28
  this.supportRequest = config.supportRequest;
23
29
  this.API_URL = config.TILEDESK_API_ENDPOINT;
30
+ this.TILEBOT_ENDPOINT = config.TILEBOT_ENDPOINT;
24
31
  this.token = config.token;
25
32
  this.log = config.log;
26
33
  this.HELP_CENTER_API_ENDPOINT = config.HELP_CENTER_API_ENDPOINT;
@@ -61,39 +68,8 @@ class DirectivesChatbotPlug {
61
68
 
62
69
  }
63
70
 
64
-
65
-
66
- moveToDepartment(tdclient, requestId, depName, callback) {
67
- tdclient.getAllDepartments((err, deps) => {
68
- console.log("deps:", deps, err);
69
- if (err) {
70
- console.error("getAllDepartments() error:", err);
71
- callback(err);
72
- return;
73
- }
74
- let dep = null;
75
- for (i = 0; i < deps.length; i++) {
76
- d = deps[i];
77
- if (d.name.toLowerCase() === depName.toLowerCase()) {
78
- dep = d;
79
- break;
80
- }
81
- }
82
- if (dep) {
83
- tdclient.updateRequestDepartment(requestId, dep._id, null, (err) => {
84
- if (err) {
85
- console.error("An error:", err);
86
- callback(err);
87
- }
88
- else {
89
- callback();
90
- }
91
- });
92
- }
93
- });
94
- }
95
-
96
- processDirectives(theend) {
71
+ processDirectives(message, theend) {
72
+ if (this.log) { console.log("Directives on message:", message); }
97
73
  const directives = this.directives;
98
74
  if (!directives || directives.length === 0) {
99
75
  if (this.log) { console.log("No directives to process."); }
@@ -103,6 +79,7 @@ class DirectivesChatbotPlug {
103
79
  const supportRequest = this.supportRequest;
104
80
  const token = this.token;
105
81
  const API_URL = this.API_URL;
82
+ const TILEBOT_ENDPOINT = this.TILEBOT_ENDPOINT;
106
83
 
107
84
  const requestId = supportRequest.request_id
108
85
  const depId = supportRequest.department._id;
@@ -118,7 +95,7 @@ class DirectivesChatbotPlug {
118
95
  log: false
119
96
  });
120
97
 
121
- let i = -1;
98
+ let curr_directive_index = -1;
122
99
  if (this.log) { console.log("processing directives:", directives); }
123
100
  function process(directive) {
124
101
  if (directive) {
@@ -137,9 +114,8 @@ class DirectivesChatbotPlug {
137
114
  if (directive.parameter) {
138
115
  dep_name = directive.parameter;
139
116
  }
140
- console.log("department:", dep_name);
141
- moveToDepartment(tdclient, requestId, dep_name, () => {
142
- console.log("moved to department:", dep_name);
117
+ const departmentDir = new DirDepartment({tdclient: tdclient, log: false});
118
+ departmentDir.execute(requestId, dep_name, () => {
143
119
  process(nextDirective());
144
120
  });
145
121
  }
@@ -154,29 +130,68 @@ class DirectivesChatbotPlug {
154
130
  subtype: "info"
155
131
  }
156
132
  };
157
- console.log("Message:", message)
158
133
  tdclient.sendSupportMessage(requestId, message, () => {
159
134
  process(nextDirective());
160
135
  });
161
136
  }
162
137
  }
138
+ else if (directive_name === Directives.INTENT) {
139
+ const intentDir = new DirIntent(
140
+ {
141
+ API_ENDPOINT: API_URL,
142
+ TILEBOT_ENDPOINT:TILEBOT_ENDPOINT,
143
+ log: false
144
+ }
145
+ );
146
+ intentDir.execute(directive, message, projectId, requestId, token, () => {
147
+ process(nextDirective());
148
+ });
149
+ }
163
150
  else if (directive_name === Directives.MESSAGE) {
164
- const messageDir = new DirMessage({API_ENDPOINT: API_URL});
151
+ const messageDir = new DirMessage(
152
+ {
153
+ API_ENDPOINT: API_URL,
154
+ TILEBOT_ENDPOINT:TILEBOT_ENDPOINT,
155
+ log: true
156
+ }
157
+ );
165
158
  messageDir.execute(directive, projectId, requestId, token, () => {
166
159
  process(nextDirective());
167
160
  });
168
161
  }
162
+ else if (directive_name === Directives.WHEN_OPEN) {
163
+ const whenOpenDir = new DirWhenOpen(
164
+ {
165
+ tdclient: tdclient // matches open hours
166
+ });
167
+ whenOpenDir.execute(directive, directives, curr_directive_index, () => {
168
+ process(nextDirective());
169
+ });
170
+ }
171
+ else if (directive_name === Directives.WHEN_CLOSED) {
172
+ const whenOpenDir = new DirWhenOpen(
173
+ {
174
+ tdclient: tdclient,
175
+ checkOpen: false // matches closed hours
176
+ });
177
+ whenOpenDir.execute(directive, directives, curr_directive_index, () => {
178
+ process(nextDirective());
179
+ });
180
+ }
169
181
  else if (directive_name === Directives.AGENT) {
170
- tdclient.log = false;
171
182
  const agentDir = new DirMoveToAgent(tdclient);
172
183
  directive.whenOnlineOnly = false;
173
184
  agentDir.execute(directive, requestId, depId, () => {
174
185
  process(nextDirective());
175
186
  });
176
187
  }
188
+ else if (directive_name === Directives.CLOSE) {
189
+ const closeDir = new DirClose({tdclient: tdclient});
190
+ closeDir.execute(directive, requestId, () => {
191
+ process(nextDirective());
192
+ });
193
+ }
177
194
  else if (directive_name === Directives.WHEN_ONLINE_MOVE_TO_AGENT) {
178
- // TODO remove this directive and
179
- // improve: \agent -whenonline
180
195
  const agentDir = new DirMoveToAgent(tdclient);
181
196
  directive.whenOnlineOnly = true;
182
197
  agentDir.execute(directive, requestId, depId, () => {
@@ -189,7 +204,6 @@ class DirectivesChatbotPlug {
189
204
  });
190
205
  }
191
206
  else if (directive_name === Directives.REPLACE_BOT) {
192
- console.log("REPLACE_BOT, requestId:", requestId);
193
207
  new DirReplaceBot(tdclient).execute(directive, requestId, () => {
194
208
  process(nextDirective());
195
209
  });
@@ -217,9 +231,9 @@ class DirectivesChatbotPlug {
217
231
  process(nextDirective());
218
232
 
219
233
  function nextDirective() {
220
- i += 1;
221
- if (i < directives.length) {
222
- let nextd = directives[i];
234
+ curr_directive_index += 1;
235
+ if (curr_directive_index < directives.length) {
236
+ let nextd = directives[curr_directive_index];
223
237
  return nextd;
224
238
  }
225
239
  else {
@@ -270,6 +284,12 @@ class DirectivesChatbotPlug {
270
284
  process(nextDirective());
271
285
  });
272
286
  }
287
+ else if (directive_name === Directives.DISABLE_INPUT_TEXT) {
288
+ const disableInputTextDir = new DirDisableInputText();
289
+ disableInputTextDir.execute(directive, pipeline, () => {
290
+ process(nextDirective());
291
+ });
292
+ }
273
293
  else if (directive_name === Directives.DEFLECT_TO_HELP_CENTER) {
274
294
  const helpDir = new DirDeflectToHelpCenter({HELP_CENTER_API_ENDPOINT: this.HELP_CENTER_API_ENDPOINT, projectId: projectId});
275
295
  helpDir.execute(directive, pipeline, 3, () => {
@@ -0,0 +1,25 @@
1
+
2
+ class DirClose {
3
+
4
+ constructor(config) {
5
+ if (!config.tdclient) {
6
+ throw new Error('config.tdclient (TiledeskClient) object is mandatory.');
7
+ }
8
+ this.tdclient = config.tdclient;
9
+ }
10
+
11
+ execute(directive, requestId, callback) {
12
+ this.tdclient.closeRequest(requestId, (err) => {
13
+ if (err) {
14
+ console.error("Error in 'close directive':", err);
15
+ }
16
+ else {
17
+ //console.log("Successfully moved to agent during online hours");
18
+ }
19
+ callback();
20
+ });
21
+ }
22
+
23
+ }
24
+
25
+ module.exports = { DirClose };
@@ -44,7 +44,7 @@ class DirDeflectToHelpCenter {
44
44
  APIKEY: "__",
45
45
  APIURL: this.helpcenter_api_endpoint,
46
46
  projectId: this.projectId,
47
- log: false
47
+ log: true
48
48
  });
49
49
  if (!workspace_id) {
50
50
  try {
@@ -52,10 +52,10 @@ class DirDeflectToHelpCenter {
52
52
  const workspaces = await helpcenter.allWorkspaces();
53
53
  if (workspaces.length > 0) {
54
54
  workspace_id = workspaces[0]._id;
55
- //console.log("First Workspace selected", workspaces[0]);
55
+ console.log("First Workspace selected", workspaces[0]);
56
56
  }
57
57
  else {
58
- //console.log("No Workspace found");
58
+ console.log("No Workspace found");
59
59
  completion();
60
60
  }
61
61
  }
@@ -64,12 +64,12 @@ class DirDeflectToHelpCenter {
64
64
  completion();
65
65
  }
66
66
  }
67
-
67
+ console.log("searching on workspace_id:", workspace_id);
68
68
  try {
69
69
  const results = await helpcenter.search(workspace_id, original_text, maxresults);
70
70
  if (results && results.length > 0) {
71
- //console.log("Successfully got results", results);
72
- //console.log("Sending REPL", hc_reply);
71
+ console.log("Successfully got results", results);
72
+ console.log("Sending REPL", hc_reply);
73
73
  pipeline.message.text = hc_reply;
74
74
  results.forEach(content => {
75
75
  if (content.url.charAt(content.url.length -1) != "/") {
@@ -0,0 +1,52 @@
1
+
2
+ class DirDepartment {
3
+
4
+ constructor(config) {
5
+ if (!config.tdclient) {
6
+ throw new Error('tdclient (TiledeskClient) object is mandatory.');
7
+ }
8
+ this.tdclient = config.tdclient;
9
+ this.log = config.log;
10
+ }
11
+
12
+ moveToDepartment(requestId, depName, callback) {
13
+ this.tdclient.getAllDepartments((err, deps) => {
14
+ if (this.log) {console.log("deps:", deps, err);}
15
+ if (err) {
16
+ console.error("getAllDepartments() error:", err);
17
+ callback(err);
18
+ return;
19
+ }
20
+ let dep = null;
21
+ let i;
22
+ for (i = 0; i < deps.length; i++) {
23
+ let d = deps[i];
24
+ if (d.name.toLowerCase() === depName.toLowerCase()) {
25
+ dep = d;
26
+ break;
27
+ }
28
+ }
29
+ if (dep) {
30
+ this.tdclient.updateRequestDepartment(requestId, dep._id, null, (err) => {
31
+ if (err) {
32
+ console.error("An error:", err);
33
+ callback(err);
34
+ }
35
+ else {
36
+ callback();
37
+ }
38
+ });
39
+ }
40
+ });
41
+ }
42
+
43
+ execute(requestId, dep_name, callback) {
44
+ if (this.log) {console.log("DirDepartment:", dep_name);}
45
+ this.moveToDepartment(requestId, dep_name, () => {
46
+ callback();
47
+ });
48
+ }
49
+
50
+ }
51
+
52
+ module.exports = { DirDepartment };
@@ -0,0 +1,45 @@
1
+ const ms = require('minimist-string');
2
+
3
+ class DirDisableInputText {
4
+
5
+ constructor() {
6
+ }
7
+
8
+ execute(directive, pipeline, callback) {
9
+ // console.log("disable input text...pipeline");
10
+ let message = pipeline.message
11
+ if (!message.attributes) {
12
+ message.attributes = {}
13
+ }
14
+ message.attributes.disableInputMessage = true;
15
+ if (directive.parameter) {
16
+ const options = this.parseParams(directive.parameter);
17
+ // console.log("Options", options)
18
+ directive.options = options;
19
+ if (options.label) {
20
+ // console.log("options.label", options.label)
21
+ message.attributes.inputMessagePlaceholder = options.label;
22
+ }
23
+ }
24
+ callback();
25
+ }
26
+
27
+ parseParams(directive_parameter) {
28
+ let label = null;
29
+ const params = ms(directive_parameter);
30
+ // console.log("params:", params);
31
+ if (params.l) {
32
+ // console.log("_param l", params.l);
33
+ label = params.l;
34
+ }
35
+ if (params.label) {
36
+ // console.log("_param label", params.label);
37
+ label = params.label;
38
+ }
39
+ return {
40
+ label: label
41
+ }
42
+ }
43
+ }
44
+
45
+ module.exports = { DirDisableInputText };
@@ -0,0 +1,50 @@
1
+ const { ExtApi } = require('../../ExtApi.js');
2
+
3
+ class DirIntent {
4
+
5
+ constructor(settings) {
6
+ if (!settings.API_ENDPOINT) {
7
+ throw new Error("settings.API_ENDPOINT is mandatory!");
8
+ }
9
+ this.API_ENDPOINT = settings.API_ENDPOINT;
10
+ this.TILEBOT_ENDPOINT = settings.TILEBOT_ENDPOINT;
11
+ }
12
+
13
+ execute(directive, message, projectId, requestId, token, callback) {
14
+ if (directive.parameter) {
15
+ let intent_name = directive.parameter.trim();
16
+ let message_to_bot = {
17
+ sender: "system22", // bot doesn't reply to himself
18
+ text: "/" + intent_name,
19
+ request: {
20
+ request_id: requestId
21
+ },
22
+ id_project: projectId
23
+ };
24
+ // send message to /ext/botId
25
+ const req_body = {
26
+ payload: message_to_bot,
27
+ token: token
28
+ }
29
+ let extEndpoint = `${this.API_ENDPOINT}/modules/tilebot`;
30
+ if (this.TILEBOT_ENDPOINT) {
31
+ extEndpoint = `${this.TILEBOT_ENDPOINT}`;
32
+ }
33
+ const extapi = new ExtApi({
34
+ ENDPOINT: extEndpoint,
35
+ log: true
36
+ });
37
+ console.log("(sending to bot) incoming message:", message);
38
+ console.log("(sending to bot) the req_body:", req_body);
39
+ extapi.sendMessageToBot(req_body, message.attributes.intent_info.botId, token, () => {
40
+ console.log("sendMessageToBot() req_body sent:", req_body);
41
+ callback();
42
+ });
43
+ }
44
+ else {
45
+ callback();
46
+ }
47
+ }
48
+ }
49
+
50
+ module.exports = { DirIntent };
@@ -7,6 +7,7 @@ class DirMessage {
7
7
  throw new Error("settings.API_ENDPOINT is mandatory!");
8
8
  }
9
9
  this.API_ENDPOINT = settings.API_ENDPOINT;
10
+ this.TILEBOT_ENDPOINT = settings.TILEBOT_ENDPOINT;
10
11
  }
11
12
 
12
13
  execute(directive, projectId, requestId, token, callback) {
@@ -20,11 +21,11 @@ class DirMessage {
20
21
  subtype: "info"
21
22
  }
22
23
  }
23
- //console.log("Message:", message);
24
+ if (this.log) {console.log("Message to extEndpoint:", message)};
24
25
  let extEndpoint = `${this.API_ENDPOINT}/modules/tilebot`;
25
- //if (process.env.TYBOT_ENDPOINT) {
26
- // extEndpoint = `${process.env.TYBOT_ENDPOINT}`;
27
- //}
26
+ if (this.TILEBOT_ENDPOINT) {
27
+ extEndpoint = `${this.TILEBOT_ENDPOINT}`;
28
+ }
28
29
  const apiext = new ExtApi({
29
30
  ENDPOINT: extEndpoint,
30
31
  log: true