@app-connect/core 1.7.10 → 1.7.12
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.
- package/connector/developerPortal.js +43 -0
- package/connector/proxy/index.js +10 -3
- package/connector/registry.js +8 -6
- package/handlers/admin.js +135 -22
- package/handlers/auth.js +89 -67
- package/handlers/calldown.js +10 -4
- package/handlers/contact.js +4 -104
- package/handlers/disposition.js +7 -145
- package/handlers/log.js +174 -258
- package/handlers/user.js +19 -6
- package/index.js +280 -47
- package/lib/analytics.js +3 -1
- package/lib/authSession.js +68 -0
- package/lib/callLogComposer.js +498 -420
- package/lib/errorHandler.js +206 -0
- package/lib/jwt.js +2 -0
- package/lib/logger.js +190 -0
- package/lib/oauth.js +21 -10
- package/lib/ringcentral.js +2 -10
- package/lib/sharedSMSComposer.js +471 -0
- package/mcp/SupportedPlatforms.md +12 -0
- package/mcp/lib/validator.js +91 -0
- package/mcp/mcpHandler.js +166 -0
- package/mcp/tools/checkAuthStatus.js +110 -0
- package/mcp/tools/collectAuthInfo.js +91 -0
- package/mcp/tools/createCallLog.js +308 -0
- package/mcp/tools/createContact.js +117 -0
- package/mcp/tools/createMessageLog.js +283 -0
- package/mcp/tools/doAuth.js +190 -0
- package/mcp/tools/findContactByName.js +92 -0
- package/mcp/tools/findContactByPhone.js +101 -0
- package/mcp/tools/getCallLog.js +98 -0
- package/mcp/tools/getGoogleFilePicker.js +103 -0
- package/mcp/tools/getHelp.js +44 -0
- package/mcp/tools/getPublicConnectors.js +53 -0
- package/mcp/tools/index.js +64 -0
- package/mcp/tools/logout.js +68 -0
- package/mcp/tools/rcGetCallLogs.js +78 -0
- package/mcp/tools/setConnector.js +69 -0
- package/mcp/tools/updateCallLog.js +122 -0
- package/models/cacheModel.js +3 -0
- package/package.json +71 -70
- package/releaseNotes.json +24 -0
- package/test/handlers/log.test.js +11 -4
- package/test/lib/logger.test.js +206 -0
- package/test/lib/ringcentral.test.js +0 -6
- package/test/lib/sharedSMSComposer.test.js +1084 -0
- package/test/mcp/tools/collectAuthInfo.test.js +234 -0
- package/test/mcp/tools/createCallLog.test.js +425 -0
- package/test/mcp/tools/createMessageLog.test.js +580 -0
- package/test/mcp/tools/doAuth.test.js +376 -0
- package/test/mcp/tools/findContactByName.test.js +263 -0
- package/test/mcp/tools/findContactByPhone.test.js +284 -0
- package/test/mcp/tools/getCallLog.test.js +286 -0
- package/test/mcp/tools/getGoogleFilePicker.test.js +281 -0
- package/test/mcp/tools/getPublicConnectors.test.js +128 -0
- package/test/mcp/tools/logout.test.js +169 -0
- package/test/mcp/tools/setConnector.test.js +177 -0
- package/test/mcp/tools/updateCallLog.test.js +346 -0
package/lib/callLogComposer.js
CHANGED
|
@@ -26,7 +26,7 @@ const { LOG_DETAILS_FORMAT_TYPE } = require('./constants');
|
|
|
26
26
|
* @param {string} params.result - Call result
|
|
27
27
|
* @returns {Promise<string>} Composed log body
|
|
28
28
|
*/
|
|
29
|
-
|
|
29
|
+
function composeCallLog(params) {
|
|
30
30
|
const {
|
|
31
31
|
logFormat = LOG_DETAILS_FORMAT_TYPE.PLAIN_TEXT,
|
|
32
32
|
existingBody = '',
|
|
@@ -45,8 +45,7 @@ async function composeCallLog(params) {
|
|
|
45
45
|
ringSenseSummary,
|
|
46
46
|
ringSenseAIScore,
|
|
47
47
|
ringSenseBulletedSummary,
|
|
48
|
-
ringSenseLink
|
|
49
|
-
platform
|
|
48
|
+
ringSenseLink
|
|
50
49
|
} = params;
|
|
51
50
|
|
|
52
51
|
let body = existingBody;
|
|
@@ -158,150 +157,161 @@ async function composeCallLog(params) {
|
|
|
158
157
|
function upsertCallAgentNote({ body, note, logFormat }) {
|
|
159
158
|
if (!note) return body;
|
|
160
159
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
160
|
+
let noteRegex = null;
|
|
161
|
+
switch (logFormat) {
|
|
162
|
+
case LOG_DETAILS_FORMAT_TYPE.HTML:
|
|
163
|
+
// HTML logFormat with proper Agent notes section handling
|
|
164
|
+
noteRegex = RegExp('<b>Agent notes</b>([\\s\\S]+?)Call details</b>');
|
|
165
|
+
if (noteRegex.test(body)) {
|
|
166
|
+
return body.replace(noteRegex, `<b>Agent notes</b><br>${note}<br><br><b>Call details</b>`);
|
|
167
|
+
}
|
|
168
|
+
return `<b>Agent notes</b><br>${note}<br><br><b>Call details</b><br>` + body;
|
|
169
|
+
case LOG_DETAILS_FORMAT_TYPE.MARKDOWN:
|
|
170
|
+
// Markdown logFormat with proper Agent notes section handling
|
|
171
|
+
noteRegex = /## Agent notes\n([\s\S]*?)\n## Call details/;
|
|
172
|
+
if (noteRegex.test(body)) {
|
|
173
|
+
return body.replace(noteRegex, `## Agent notes\n${note}\n\n## Call details`);
|
|
174
|
+
}
|
|
175
|
+
if (body.startsWith('## Call details')) {
|
|
176
|
+
return `## Agent notes\n${note}\n\n` + body;
|
|
177
|
+
}
|
|
178
|
+
return `## Agent notes\n${note}\n\n## Call details\n` + body;
|
|
179
|
+
case LOG_DETAILS_FORMAT_TYPE.PLAIN_TEXT:
|
|
180
|
+
// Plain text logFormat - FIXED REGEX for multi-line notes with blank lines
|
|
181
|
+
noteRegex = /- (?:Note|Agent notes): ([\s\S]*?)(?=\n- [A-Z][a-zA-Z\s/]*:|\n$|$)/;
|
|
182
|
+
if (noteRegex.test(body)) {
|
|
183
|
+
return body.replace(noteRegex, `- Note: ${note}`);
|
|
184
|
+
}
|
|
185
|
+
return `- Note: ${note}\n` + body;
|
|
185
186
|
}
|
|
186
187
|
}
|
|
187
188
|
|
|
188
189
|
function upsertCallSessionId({ body, id, logFormat }) {
|
|
189
190
|
if (!id) return body;
|
|
190
191
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
192
|
+
let idRegex = null;
|
|
193
|
+
switch (logFormat) {
|
|
194
|
+
case LOG_DETAILS_FORMAT_TYPE.HTML:
|
|
195
|
+
// More flexible regex that handles both <li> wrapped and unwrapped content
|
|
196
|
+
idRegex = /(?:<li>)?<b>Session Id<\/b>:\s*([^<\n]+)(?:<\/li>|(?=<|$))/i;
|
|
197
|
+
if (idRegex.test(body)) {
|
|
198
|
+
return body.replace(idRegex, `<li><b>Session Id</b>: ${id}</li>`);
|
|
199
|
+
}
|
|
200
|
+
return body + `<li><b>Session Id</b>: ${id}</li>`;
|
|
201
|
+
case LOG_DETAILS_FORMAT_TYPE.MARKDOWN:
|
|
202
|
+
// Markdown format: **Session Id**: value
|
|
203
|
+
idRegex = /\*\*Session Id\*\*: [^\n]*\n*/;
|
|
204
|
+
if (idRegex.test(body)) {
|
|
205
|
+
return body.replace(idRegex, `**Session Id**: ${id}\n`);
|
|
206
|
+
}
|
|
207
|
+
return body + `**Session Id**: ${id}\n`;
|
|
208
|
+
case LOG_DETAILS_FORMAT_TYPE.PLAIN_TEXT:
|
|
209
|
+
// Match Session Id field and any trailing newlines, replace with single newline
|
|
210
|
+
idRegex = /- Session Id: [^\n]*\n*/;
|
|
211
|
+
if (idRegex.test(body)) {
|
|
212
|
+
return body.replace(idRegex, `- Session Id: ${id}\n`);
|
|
213
|
+
}
|
|
214
|
+
return body + `- Session Id: ${id}\n`;
|
|
212
215
|
}
|
|
213
216
|
}
|
|
214
217
|
|
|
215
218
|
function upsertRingCentralUserName({ body, userName, logFormat }) {
|
|
216
219
|
if (!userName) return body;
|
|
217
220
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
221
|
+
let userNameRegex = null;
|
|
222
|
+
let match = null;
|
|
223
|
+
switch (logFormat) {
|
|
224
|
+
case LOG_DETAILS_FORMAT_TYPE.HTML:
|
|
225
|
+
userNameRegex = /(?:<li>)?<b>RingCentral user name<\/b>:\s*([^<\n]+)(?:<\/li>|(?=<|$))/i;
|
|
226
|
+
match = body.match(userNameRegex);
|
|
227
|
+
if (match) {
|
|
228
|
+
// Only replace if existing value is (pending...)
|
|
229
|
+
if (match[1].trim() === '(pending...)') {
|
|
230
|
+
return body.replace(userNameRegex, `<li><b>RingCentral user name</b>: ${userName}</li>`);
|
|
231
|
+
}
|
|
232
|
+
return body;
|
|
233
|
+
} else {
|
|
234
|
+
return body + `<li><b>RingCentral user name</b>: ${userName}</li>`;
|
|
235
|
+
}
|
|
236
|
+
case LOG_DETAILS_FORMAT_TYPE.MARKDOWN:
|
|
237
|
+
userNameRegex = /\*\*RingCentral user name\*\*: ([^\n]*)\n*/i;
|
|
238
|
+
match = body.match(userNameRegex);
|
|
239
|
+
if (match) {
|
|
240
|
+
// Only replace if existing value is (pending...)
|
|
241
|
+
if (match[1].trim() === '(pending...)') {
|
|
242
|
+
return body.replace(userNameRegex, `**RingCentral user name**: ${userName}\n`);
|
|
243
|
+
}
|
|
244
|
+
return body;
|
|
245
|
+
} else {
|
|
246
|
+
return body + `**RingCentral user name**: ${userName}\n`;
|
|
247
|
+
}
|
|
248
|
+
case LOG_DETAILS_FORMAT_TYPE.PLAIN_TEXT:
|
|
249
|
+
userNameRegex = /- RingCentral user name: ([^\n]*)\n*/;
|
|
250
|
+
match = body.match(userNameRegex);
|
|
251
|
+
if (match) {
|
|
252
|
+
// Only replace if existing value is (pending...)
|
|
253
|
+
if (match[1].trim() === '(pending...)') {
|
|
254
|
+
return body.replace(userNameRegex, `- RingCentral user name: ${userName}\n`);
|
|
255
|
+
}
|
|
256
|
+
return body;
|
|
257
|
+
} else {
|
|
258
|
+
return body + `- RingCentral user name: ${userName}\n`;
|
|
225
259
|
}
|
|
226
|
-
return body;
|
|
227
|
-
} else {
|
|
228
|
-
return body + `<li><b>RingCentral user name</b>: ${userName}</li>`;
|
|
229
|
-
}
|
|
230
|
-
} else if (logFormat === LOG_DETAILS_FORMAT_TYPE.MARKDOWN) {
|
|
231
|
-
const userNameRegex = /\*\*RingCentral user name\*\*: ([^\n]*)\n*/i;
|
|
232
|
-
const match = body.match(userNameRegex);
|
|
233
|
-
if (match) {
|
|
234
|
-
// Only replace if existing value is (pending...)
|
|
235
|
-
if (match[1].trim() === '(pending...)') {
|
|
236
|
-
return body.replace(userNameRegex, `**RingCentral user name**: ${userName}\n`);
|
|
237
|
-
}
|
|
238
|
-
return body;
|
|
239
|
-
} else {
|
|
240
|
-
return body + `**RingCentral user name**: ${userName}\n`;
|
|
241
|
-
}
|
|
242
|
-
} else {
|
|
243
|
-
const userNameRegex = /- RingCentral user name: ([^\n]*)\n*/;
|
|
244
|
-
const match = body.match(userNameRegex);
|
|
245
|
-
if (match) {
|
|
246
|
-
// Only replace if existing value is (pending...)
|
|
247
|
-
if (match[1].trim() === '(pending...)') {
|
|
248
|
-
return body.replace(userNameRegex, `- RingCentral user name: ${userName}\n`);
|
|
249
|
-
}
|
|
250
|
-
return body;
|
|
251
|
-
} else {
|
|
252
|
-
return body + `- RingCentral user name: ${userName}\n`;
|
|
253
|
-
}
|
|
254
260
|
}
|
|
255
261
|
}
|
|
256
262
|
|
|
257
263
|
function upsertRingCentralNumberAndExtension({ body, number, extension, logFormat }) {
|
|
258
264
|
if (!number && !extension) return body;
|
|
259
265
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
266
|
+
let numberAndExtensionRegex = null;
|
|
267
|
+
switch (logFormat) {
|
|
268
|
+
case LOG_DETAILS_FORMAT_TYPE.HTML:
|
|
269
|
+
numberAndExtensionRegex = /(?:<li>)?<b>RingCentral number and extension<\/b>:\s*([^<\n]+)(?:<\/li>|(?=<|$))/i;
|
|
270
|
+
if (numberAndExtensionRegex.test(body)) {
|
|
271
|
+
return body.replace(numberAndExtensionRegex, `<li><b>RingCentral number and extension</b>: ${number} ${extension}</li>`);
|
|
272
|
+
}
|
|
273
|
+
return body + `<li><b>RingCentral number and extension</b>: ${number} ${extension}</li>`;
|
|
274
|
+
case LOG_DETAILS_FORMAT_TYPE.MARKDOWN:
|
|
275
|
+
numberAndExtensionRegex = /\*\*RingCentral number and extension\*\*: [^\n]*\n*/i;
|
|
276
|
+
if (numberAndExtensionRegex.test(body)) {
|
|
277
|
+
return body.replace(numberAndExtensionRegex, `**RingCentral number and extension**: ${number} ${extension}\n`);
|
|
278
|
+
}
|
|
279
|
+
return body + `**RingCentral number and extension**: ${number} ${extension}\n`;
|
|
280
|
+
case LOG_DETAILS_FORMAT_TYPE.PLAIN_TEXT:
|
|
281
|
+
numberAndExtensionRegex = /- RingCentral number and extension: [^\n]*\n*/;
|
|
282
|
+
if (numberAndExtensionRegex.test(body)) {
|
|
283
|
+
return body.replace(numberAndExtensionRegex, `- RingCentral number and extension: ${number} ${extension}\n`);
|
|
284
|
+
}
|
|
285
|
+
return body + `- RingCentral number and extension: ${number} ${extension}\n`;
|
|
278
286
|
}
|
|
279
287
|
}
|
|
280
288
|
|
|
281
289
|
function upsertCallSubject({ body, subject, logFormat }) {
|
|
282
290
|
if (!subject) return body;
|
|
283
291
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
292
|
+
let subjectRegex = null;
|
|
293
|
+
switch (logFormat) {
|
|
294
|
+
case LOG_DETAILS_FORMAT_TYPE.HTML:
|
|
295
|
+
// More flexible regex that handles both <li> wrapped and unwrapped content
|
|
296
|
+
subjectRegex = /(?:<li>)?<b>Summary<\/b>:\s*([^<\n]+)(?:<\/li>|(?=<|$))/i;
|
|
297
|
+
if (subjectRegex.test(body)) {
|
|
298
|
+
return body.replace(subjectRegex, `<li><b>Summary</b>: ${subject}</li>`);
|
|
299
|
+
}
|
|
300
|
+
return body + `<li><b>Summary</b>: ${subject}</li>`;
|
|
301
|
+
case LOG_DETAILS_FORMAT_TYPE.MARKDOWN:
|
|
302
|
+
// Markdown format: **Summary**: value
|
|
303
|
+
subjectRegex = /\*\*Summary\*\*: [^\n]*\n*/;
|
|
304
|
+
if (subjectRegex.test(body)) {
|
|
305
|
+
return body.replace(subjectRegex, `**Summary**: ${subject}\n`);
|
|
306
|
+
}
|
|
307
|
+
return body + `**Summary**: ${subject}\n`;
|
|
308
|
+
case LOG_DETAILS_FORMAT_TYPE.PLAIN_TEXT:
|
|
309
|
+
// Match Summary field and any trailing newlines, replace with single newline
|
|
310
|
+
subjectRegex = /- Summary: [^\n]*\n*/;
|
|
311
|
+
if (subjectRegex.test(body)) {
|
|
312
|
+
return body.replace(subjectRegex, `- Summary: ${subject}\n`);
|
|
313
|
+
}
|
|
314
|
+
return body + `- Summary: ${subject}\n`;
|
|
305
315
|
}
|
|
306
316
|
}
|
|
307
317
|
|
|
@@ -311,30 +321,35 @@ function upsertContactPhoneNumber({ body, phoneNumber, direction, logFormat }) {
|
|
|
311
321
|
const label = direction === 'Outbound' ? 'Recipient' : 'Caller';
|
|
312
322
|
let result = body;
|
|
313
323
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
result
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
324
|
+
let phoneNumberRegex = null;
|
|
325
|
+
switch (logFormat) {
|
|
326
|
+
case LOG_DETAILS_FORMAT_TYPE.HTML:
|
|
327
|
+
// More flexible regex that handles both <li> wrapped and unwrapped content
|
|
328
|
+
phoneNumberRegex = new RegExp(`(?:<li>)?<b>${label} phone number</b>:\\s*([^<\\n]+)(?:</li>|(?=<|$))`, 'i');
|
|
329
|
+
if (phoneNumberRegex.test(result)) {
|
|
330
|
+
result = result.replace(phoneNumberRegex, `<li><b>${label} phone number</b>: ${phoneNumber}</li>`);
|
|
331
|
+
} else {
|
|
332
|
+
result += `<li><b>${label} phone number</b>: ${phoneNumber}</li>`;
|
|
333
|
+
}
|
|
334
|
+
break;
|
|
335
|
+
case LOG_DETAILS_FORMAT_TYPE.MARKDOWN:
|
|
336
|
+
// Markdown format: **Contact Number**: value
|
|
337
|
+
phoneNumberRegex = /\*\*Contact Number\*\*: [^\n]*\n*/;
|
|
338
|
+
if (phoneNumberRegex.test(result)) {
|
|
339
|
+
result = result.replace(phoneNumberRegex, `**Contact Number**: ${phoneNumber}\n`);
|
|
340
|
+
} else {
|
|
341
|
+
result += `**Contact Number**: ${phoneNumber}\n`;
|
|
342
|
+
}
|
|
343
|
+
break;
|
|
344
|
+
case LOG_DETAILS_FORMAT_TYPE.PLAIN_TEXT:
|
|
345
|
+
// More flexible regex that handles both with and without newlines
|
|
346
|
+
phoneNumberRegex = /- Contact Number: ([^\n-]+)(?=\n-|\n|$)/;
|
|
347
|
+
if (phoneNumberRegex.test(result)) {
|
|
348
|
+
result = result.replace(phoneNumberRegex, `- Contact Number: ${phoneNumber}\n`);
|
|
349
|
+
} else {
|
|
350
|
+
result += `- Contact Number: ${phoneNumber}\n`;
|
|
351
|
+
}
|
|
352
|
+
break;
|
|
338
353
|
}
|
|
339
354
|
return result;
|
|
340
355
|
}
|
|
@@ -357,30 +372,35 @@ function upsertCallDateTime({ body, startTime, timezoneOffset, logFormat, logDat
|
|
|
357
372
|
const formattedDateTime = momentTime.format(logDateFormat || 'YYYY-MM-DD hh:mm:ss A');
|
|
358
373
|
let result = body;
|
|
359
374
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
result
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
375
|
+
let dateTimeRegex = null;
|
|
376
|
+
switch (logFormat) {
|
|
377
|
+
case LOG_DETAILS_FORMAT_TYPE.HTML:
|
|
378
|
+
// More flexible regex that handles both <li> wrapped and unwrapped content
|
|
379
|
+
dateTimeRegex = /(?:<li>)?<b>Date\/time<\/b>:\s*([^<\n]+)(?:<\/li>|(?=<|$))/i;
|
|
380
|
+
if (dateTimeRegex.test(result)) {
|
|
381
|
+
result = result.replace(dateTimeRegex, `<li><b>Date/time</b>: ${formattedDateTime}</li>`);
|
|
382
|
+
} else {
|
|
383
|
+
result += `<li><b>Date/time</b>: ${formattedDateTime}</li>`;
|
|
384
|
+
}
|
|
385
|
+
break;
|
|
386
|
+
case LOG_DETAILS_FORMAT_TYPE.MARKDOWN:
|
|
387
|
+
// Markdown format: **Date/Time**: value
|
|
388
|
+
dateTimeRegex = /\*\*Date\/Time\*\*: [^\n]*\n*/;
|
|
389
|
+
if (dateTimeRegex.test(result)) {
|
|
390
|
+
result = result.replace(dateTimeRegex, `**Date/Time**: ${formattedDateTime}\n`);
|
|
391
|
+
} else {
|
|
392
|
+
result += `**Date/Time**: ${formattedDateTime}\n`;
|
|
393
|
+
}
|
|
394
|
+
break;
|
|
395
|
+
case LOG_DETAILS_FORMAT_TYPE.PLAIN_TEXT:
|
|
396
|
+
// Handle duplicated Date/Time entries and match complete date/time values
|
|
397
|
+
dateTimeRegex = /^(- Date\/Time:).*$/m;
|
|
398
|
+
if (dateTimeRegex.test(result)) {
|
|
399
|
+
result = result.replace(dateTimeRegex, `- Date/Time: ${formattedDateTime}`);
|
|
400
|
+
} else {
|
|
401
|
+
result += `- Date/Time: ${formattedDateTime}\n`;
|
|
402
|
+
}
|
|
403
|
+
break;
|
|
384
404
|
}
|
|
385
405
|
return result;
|
|
386
406
|
}
|
|
@@ -390,31 +410,35 @@ function upsertCallDuration({ body, duration, logFormat }) {
|
|
|
390
410
|
|
|
391
411
|
const formattedDuration = secondsToHoursMinutesSeconds(duration);
|
|
392
412
|
let result = body;
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
result
|
|
417
|
-
|
|
413
|
+
let durationRegex = null;
|
|
414
|
+
switch (logFormat) {
|
|
415
|
+
case LOG_DETAILS_FORMAT_TYPE.HTML:
|
|
416
|
+
// More flexible regex that handles both <li> wrapped and unwrapped content
|
|
417
|
+
durationRegex = /(?:<li>)?<b>Duration<\/b>:\s*([^<\n]+)(?:<\/li>|(?=<|$))/i;
|
|
418
|
+
if (durationRegex.test(result)) {
|
|
419
|
+
result = result.replace(durationRegex, `<li><b>Duration</b>: ${formattedDuration}</li>`);
|
|
420
|
+
} else {
|
|
421
|
+
result += `<li><b>Duration</b>: ${formattedDuration}</li>`;
|
|
422
|
+
}
|
|
423
|
+
break;
|
|
424
|
+
case LOG_DETAILS_FORMAT_TYPE.MARKDOWN:
|
|
425
|
+
// Markdown format: **Duration**: value
|
|
426
|
+
durationRegex = /\*\*Duration\*\*: [^\n]*\n*/;
|
|
427
|
+
if (durationRegex.test(result)) {
|
|
428
|
+
result = result.replace(durationRegex, `**Duration**: ${formattedDuration}\n`);
|
|
429
|
+
} else {
|
|
430
|
+
result += `**Duration**: ${formattedDuration}\n`;
|
|
431
|
+
}
|
|
432
|
+
break;
|
|
433
|
+
case LOG_DETAILS_FORMAT_TYPE.PLAIN_TEXT:
|
|
434
|
+
// More flexible regex that handles both with and without newlines
|
|
435
|
+
durationRegex = /- Duration: ([^\n-]+)(?=\n-|\n|$)/;
|
|
436
|
+
if (durationRegex.test(result)) {
|
|
437
|
+
result = result.replace(durationRegex, `- Duration: ${formattedDuration}`);
|
|
438
|
+
} else {
|
|
439
|
+
result += `- Duration: ${formattedDuration}\n`;
|
|
440
|
+
}
|
|
441
|
+
break;
|
|
418
442
|
}
|
|
419
443
|
return result;
|
|
420
444
|
}
|
|
@@ -424,30 +448,35 @@ function upsertCallResult({ body, result, logFormat }) {
|
|
|
424
448
|
|
|
425
449
|
let bodyResult = body;
|
|
426
450
|
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
bodyResult
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
+
let resultRegex = null;
|
|
452
|
+
switch (logFormat) {
|
|
453
|
+
case LOG_DETAILS_FORMAT_TYPE.HTML:
|
|
454
|
+
// More flexible regex that handles both <li> wrapped and unwrapped content
|
|
455
|
+
resultRegex = /(?:<li>)?<b>Result<\/b>:\s*([^<\n]+)(?:<\/li>|(?=<|$))/i;
|
|
456
|
+
if (resultRegex.test(bodyResult)) {
|
|
457
|
+
bodyResult = bodyResult.replace(resultRegex, `<li><b>Result</b>: ${result}</li>`);
|
|
458
|
+
} else {
|
|
459
|
+
bodyResult += `<li><b>Result</b>: ${result}</li>`;
|
|
460
|
+
}
|
|
461
|
+
break;
|
|
462
|
+
case LOG_DETAILS_FORMAT_TYPE.MARKDOWN:
|
|
463
|
+
// Markdown format: **Result**: value
|
|
464
|
+
resultRegex = /\*\*Result\*\*: [^\n]*\n*/;
|
|
465
|
+
if (resultRegex.test(bodyResult)) {
|
|
466
|
+
bodyResult = bodyResult.replace(resultRegex, `**Result**: ${result}\n`);
|
|
467
|
+
} else {
|
|
468
|
+
bodyResult += `**Result**: ${result}\n`;
|
|
469
|
+
}
|
|
470
|
+
break;
|
|
471
|
+
case LOG_DETAILS_FORMAT_TYPE.PLAIN_TEXT:
|
|
472
|
+
// More flexible regex that handles both with and without newlines
|
|
473
|
+
resultRegex = /- Result: ([^\n-]+)(?=\n-|\n|$)/;
|
|
474
|
+
if (resultRegex.test(bodyResult)) {
|
|
475
|
+
bodyResult = bodyResult.replace(resultRegex, `- Result: ${result}`);
|
|
476
|
+
} else {
|
|
477
|
+
bodyResult += `- Result: ${result}\n`;
|
|
478
|
+
}
|
|
479
|
+
break;
|
|
451
480
|
}
|
|
452
481
|
return bodyResult;
|
|
453
482
|
}
|
|
@@ -456,11 +485,12 @@ function upsertCallRecording({ body, recordingLink, logFormat }) {
|
|
|
456
485
|
if (!recordingLink) return body;
|
|
457
486
|
|
|
458
487
|
let result = body;
|
|
488
|
+
let recordingLinkRegex = null;
|
|
459
489
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
490
|
+
switch (logFormat) {
|
|
491
|
+
case LOG_DETAILS_FORMAT_TYPE.HTML:
|
|
492
|
+
// More flexible regex that handles both <li> wrapped and unwrapped content, and existing <a> anchors
|
|
493
|
+
recordingLinkRegex = /(?:<li>)?<b>Call recording link<\/b>:\s*(?:<a[^>]*>[^<]*<\/a>|[^<]+)(?:<\/li>|(?=<|$))/i;
|
|
464
494
|
if (recordingLinkRegex.test(result)) {
|
|
465
495
|
if (recordingLink.startsWith('http')) {
|
|
466
496
|
result = result.replace(recordingLinkRegex, `<li><b>Call recording link</b>: <a target="_blank" href="${recordingLink}">open</a></li>`);
|
|
@@ -480,26 +510,28 @@ function upsertCallRecording({ body, recordingLink, logFormat }) {
|
|
|
480
510
|
result = result.replace('</ul>', `${text}</ul>`);
|
|
481
511
|
}
|
|
482
512
|
}
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
}
|
|
492
|
-
} else {
|
|
493
|
-
// Match recording link field and any trailing content, replace with single newline
|
|
494
|
-
const recordingLinkRegex = /- Call recording link: [^\n]*\n*/;
|
|
495
|
-
if (recordingLinkRegex.test(result)) {
|
|
496
|
-
result = result.replace(recordingLinkRegex, `- Call recording link: ${recordingLink}\n`);
|
|
497
|
-
} else {
|
|
498
|
-
if (result && !result.endsWith('\n')) {
|
|
499
|
-
result += '\n';
|
|
513
|
+
break;
|
|
514
|
+
case LOG_DETAILS_FORMAT_TYPE.MARKDOWN:
|
|
515
|
+
// Markdown format: **Call recording link**: value
|
|
516
|
+
recordingLinkRegex = /\*\*Call recording link\*\*: [^\n]*\n*/;
|
|
517
|
+
if (recordingLinkRegex.test(result)) {
|
|
518
|
+
result = result.replace(recordingLinkRegex, `**Call recording link**: ${recordingLink}\n`);
|
|
519
|
+
} else {
|
|
520
|
+
result += `**Call recording link**: ${recordingLink}\n`;
|
|
500
521
|
}
|
|
501
|
-
|
|
502
|
-
|
|
522
|
+
break;
|
|
523
|
+
case LOG_DETAILS_FORMAT_TYPE.PLAIN_TEXT:
|
|
524
|
+
// Match recording link field and any trailing content, replace with single newline
|
|
525
|
+
recordingLinkRegex = /- Call recording link: [^\n]*\n*/;
|
|
526
|
+
if (recordingLinkRegex.test(result)) {
|
|
527
|
+
result = result.replace(recordingLinkRegex, `- Call recording link: ${recordingLink}\n`);
|
|
528
|
+
} else {
|
|
529
|
+
if (result && !result.endsWith('\n')) {
|
|
530
|
+
result += '\n';
|
|
531
|
+
}
|
|
532
|
+
result += `- Call recording link: ${recordingLink}\n`;
|
|
533
|
+
}
|
|
534
|
+
break;
|
|
503
535
|
}
|
|
504
536
|
return result;
|
|
505
537
|
}
|
|
@@ -509,30 +541,35 @@ function upsertAiNote({ body, aiNote, logFormat }) {
|
|
|
509
541
|
|
|
510
542
|
const clearedAiNote = aiNote.replace(/\n+$/, '');
|
|
511
543
|
let result = body;
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
result
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
544
|
+
let aiNoteRegex = null;
|
|
545
|
+
|
|
546
|
+
switch (logFormat) {
|
|
547
|
+
case LOG_DETAILS_FORMAT_TYPE.HTML:
|
|
548
|
+
const formattedAiNote = clearedAiNote.replace(/(?:\r\n|\r|\n)/g, '<br>');
|
|
549
|
+
aiNoteRegex = /<div><b>AI Note<\/b><br>(.+?)<\/div>/;
|
|
550
|
+
if (aiNoteRegex.test(result)) {
|
|
551
|
+
result = result.replace(aiNoteRegex, `<div><b>AI Note</b><br>${formattedAiNote}</div>`);
|
|
552
|
+
} else {
|
|
553
|
+
result += `<div><b>AI Note</b><br>${formattedAiNote}</div><br>`;
|
|
554
|
+
}
|
|
555
|
+
break;
|
|
556
|
+
case LOG_DETAILS_FORMAT_TYPE.MARKDOWN:
|
|
557
|
+
// Markdown format: ### AI Note
|
|
558
|
+
aiNoteRegex = /### AI Note\n([\s\S]*?)(?=\n### |\n$|$)/;
|
|
559
|
+
if (aiNoteRegex.test(result)) {
|
|
560
|
+
result = result.replace(aiNoteRegex, `### AI Note\n${clearedAiNote}\n`);
|
|
561
|
+
} else {
|
|
562
|
+
result += `### AI Note\n${clearedAiNote}\n`;
|
|
563
|
+
}
|
|
564
|
+
break;
|
|
565
|
+
case LOG_DETAILS_FORMAT_TYPE.PLAIN_TEXT:
|
|
566
|
+
aiNoteRegex = /- AI Note:([\s\S]*?)--- END/;
|
|
567
|
+
if (aiNoteRegex.test(result)) {
|
|
568
|
+
result = result.replace(aiNoteRegex, `- AI Note:\n${clearedAiNote}\n--- END`);
|
|
569
|
+
} else {
|
|
570
|
+
result += `\n- AI Note:\n${clearedAiNote}\n--- END\n`;
|
|
571
|
+
}
|
|
572
|
+
break;
|
|
536
573
|
}
|
|
537
574
|
return result;
|
|
538
575
|
}
|
|
@@ -541,30 +578,35 @@ function upsertTranscript({ body, transcript, logFormat }) {
|
|
|
541
578
|
if (!transcript) return body;
|
|
542
579
|
|
|
543
580
|
let result = body;
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
result
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
581
|
+
let transcriptRegex = null;
|
|
582
|
+
|
|
583
|
+
switch (logFormat) {
|
|
584
|
+
case LOG_DETAILS_FORMAT_TYPE.HTML:
|
|
585
|
+
const formattedTranscript = transcript.replace(/(?:\r\n|\r|\n)/g, '<br>');
|
|
586
|
+
transcriptRegex = /<div><b>Transcript<\/b><br>(.+?)<\/div>/;
|
|
587
|
+
if (transcriptRegex.test(result)) {
|
|
588
|
+
result = result.replace(transcriptRegex, `<div><b>Transcript</b><br>${formattedTranscript}</div>`);
|
|
589
|
+
} else {
|
|
590
|
+
result += `<div><b>Transcript</b><br>${formattedTranscript}</div><br>`;
|
|
591
|
+
}
|
|
592
|
+
break;
|
|
593
|
+
case LOG_DETAILS_FORMAT_TYPE.MARKDOWN:
|
|
594
|
+
// Markdown format: ### Transcript
|
|
595
|
+
transcriptRegex = /### Transcript\n([\s\S]*?)(?=\n### |\n$|$)/;
|
|
596
|
+
if (transcriptRegex.test(result)) {
|
|
597
|
+
result = result.replace(transcriptRegex, `### Transcript\n${transcript}\n`);
|
|
598
|
+
} else {
|
|
599
|
+
result += `### Transcript\n${transcript}\n`;
|
|
600
|
+
}
|
|
601
|
+
break;
|
|
602
|
+
case LOG_DETAILS_FORMAT_TYPE.PLAIN_TEXT:
|
|
603
|
+
transcriptRegex = /- Transcript:([\s\S]*?)--- END/;
|
|
604
|
+
if (transcriptRegex.test(result)) {
|
|
605
|
+
result = result.replace(transcriptRegex, `- Transcript:\n${transcript}\n--- END`);
|
|
606
|
+
} else {
|
|
607
|
+
result += `\n- Transcript:\n${transcript}\n--- END\n`;
|
|
608
|
+
}
|
|
609
|
+
break;
|
|
568
610
|
}
|
|
569
611
|
return result;
|
|
570
612
|
}
|
|
@@ -617,28 +659,34 @@ function upsertLegs({ body, legs, logFormat }) {
|
|
|
617
659
|
|
|
618
660
|
let result = body;
|
|
619
661
|
let legsJourney = getLegsJourney(legs);
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
result
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
662
|
+
let legsRegex = null;
|
|
663
|
+
|
|
664
|
+
switch (logFormat) {
|
|
665
|
+
case LOG_DETAILS_FORMAT_TYPE.HTML:
|
|
666
|
+
legsJourney = legsJourney.replace(/(?:\r\n|\r|\n)/g, '<br>');
|
|
667
|
+
legsRegex = /<div><b>Call journey<\/b><br>(.+?)<\/div>/;
|
|
668
|
+
if (legsRegex.test(result)) {
|
|
669
|
+
result = result.replace(legsRegex, `<div><b>Call journey</b><br>${legsJourney}</div>`);
|
|
670
|
+
} else {
|
|
671
|
+
result += `<div><b>Call journey</b><br>${legsJourney}</div>`;
|
|
672
|
+
}
|
|
673
|
+
break;
|
|
674
|
+
case LOG_DETAILS_FORMAT_TYPE.MARKDOWN:
|
|
675
|
+
legsRegex = /### Call journey\n([\s\S]*?)(?=\n### |\n$|$)/;
|
|
676
|
+
if (legsRegex.test(result)) {
|
|
677
|
+
result = result.replace(legsRegex, `### Call journey\n${legsJourney}\n`);
|
|
678
|
+
} else {
|
|
679
|
+
result += `### Call journey\n${legsJourney}\n`;
|
|
680
|
+
}
|
|
681
|
+
break;
|
|
682
|
+
case LOG_DETAILS_FORMAT_TYPE.PLAIN_TEXT:
|
|
683
|
+
legsRegex = /- Call journey:([\s\S]*?)--- JOURNEY END/;
|
|
684
|
+
if (legsRegex.test(result)) {
|
|
685
|
+
result = result.replace(legsRegex, `- Call journey:\n${legsJourney}\n--- JOURNEY END`);
|
|
686
|
+
} else {
|
|
687
|
+
result += `- Call journey:\n${legsJourney}\n--- JOURNEY END\n`;
|
|
688
|
+
}
|
|
689
|
+
break;
|
|
642
690
|
}
|
|
643
691
|
|
|
644
692
|
return result;
|
|
@@ -649,28 +697,34 @@ function upsertRingSenseTranscript({ body, transcript, logFormat }) {
|
|
|
649
697
|
|
|
650
698
|
let result = body;
|
|
651
699
|
const clearedTranscript = transcript.replace(/\n+$/, '');
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
result
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
700
|
+
let transcriptRegex = null;
|
|
701
|
+
|
|
702
|
+
switch (logFormat) {
|
|
703
|
+
case LOG_DETAILS_FORMAT_TYPE.HTML:
|
|
704
|
+
const formattedTranscript = clearedTranscript.replace(/(?:\r\n|\r|\n)/g, '<br>');
|
|
705
|
+
transcriptRegex = /<div><b>RingSense transcript<\/b><br>(.+?)<\/div>/;
|
|
706
|
+
if (transcriptRegex.test(result)) {
|
|
707
|
+
result = result.replace(transcriptRegex, `<div><b>RingSense transcript</b><br>${formattedTranscript}</div>`);
|
|
708
|
+
} else {
|
|
709
|
+
result += `<div><b>RingSense transcript</b><br>${formattedTranscript}</div>`;
|
|
710
|
+
}
|
|
711
|
+
break;
|
|
712
|
+
case LOG_DETAILS_FORMAT_TYPE.MARKDOWN:
|
|
713
|
+
transcriptRegex = /### RingSense transcript\n([\s\S]*?)(?=\n### |\n$|$)/;
|
|
714
|
+
if (transcriptRegex.test(result)) {
|
|
715
|
+
result = result.replace(transcriptRegex, `### RingSense transcript\n${clearedTranscript}\n`);
|
|
716
|
+
} else {
|
|
717
|
+
result += `### RingSense transcript\n${clearedTranscript}\n`;
|
|
718
|
+
}
|
|
719
|
+
break;
|
|
720
|
+
case LOG_DETAILS_FORMAT_TYPE.PLAIN_TEXT:
|
|
721
|
+
transcriptRegex = /- RingSense transcript:([\s\S]*?)--- END/;
|
|
722
|
+
if (transcriptRegex.test(result)) {
|
|
723
|
+
result = result.replace(transcriptRegex, `- RingSense transcript:\n${clearedTranscript}\n--- END`);
|
|
724
|
+
} else {
|
|
725
|
+
result += `\n- RingSense transcript:\n${clearedTranscript}\n--- END\n`;
|
|
726
|
+
}
|
|
727
|
+
break;
|
|
674
728
|
}
|
|
675
729
|
return result;
|
|
676
730
|
}
|
|
@@ -681,28 +735,34 @@ function upsertRingSenseSummary({ body, summary, logFormat }) {
|
|
|
681
735
|
let result = body;
|
|
682
736
|
// remove new line in last line of summary
|
|
683
737
|
const clearedSummary = summary.replace(/\n+$/, '');
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
result
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
738
|
+
let summaryRegex = null;
|
|
739
|
+
|
|
740
|
+
switch (logFormat) {
|
|
741
|
+
case LOG_DETAILS_FORMAT_TYPE.HTML:
|
|
742
|
+
summaryRegex = /<div><b>RingSense summary<\/b><br>(.+?)<\/div>/;
|
|
743
|
+
const formattedSummary = clearedSummary.replace(/(?:\r\n|\r|\n)/g, '<br>');
|
|
744
|
+
if (summaryRegex.test(result)) {
|
|
745
|
+
result = result.replace(summaryRegex, `<div><b>RingSense summary</b><br>${formattedSummary}</div>`);
|
|
746
|
+
} else {
|
|
747
|
+
result += `<div><b>RingSense summary</b><br>${formattedSummary}</div>`;
|
|
748
|
+
}
|
|
749
|
+
break;
|
|
750
|
+
case LOG_DETAILS_FORMAT_TYPE.MARKDOWN:
|
|
751
|
+
summaryRegex = /### RingSense summary\n([\s\S]*?)(?=\n### |\n$|$)/;
|
|
752
|
+
if (summaryRegex.test(result)) {
|
|
753
|
+
result = result.replace(summaryRegex, `### RingSense summary\n${summary}\n`);
|
|
754
|
+
} else {
|
|
755
|
+
result += `### RingSense summary\n${summary}\n`;
|
|
756
|
+
}
|
|
757
|
+
break;
|
|
758
|
+
case LOG_DETAILS_FORMAT_TYPE.PLAIN_TEXT:
|
|
759
|
+
summaryRegex = /- RingSense summary:([\s\S]*?)--- END/;
|
|
760
|
+
if (summaryRegex.test(result)) {
|
|
761
|
+
result = result.replace(summaryRegex, `- RingSense summary:\n${summary}\n--- END`);
|
|
762
|
+
} else {
|
|
763
|
+
result += `\n- RingSense summary:\n${summary}\n--- END\n`;
|
|
764
|
+
}
|
|
765
|
+
break;
|
|
706
766
|
}
|
|
707
767
|
return result;
|
|
708
768
|
}
|
|
@@ -711,27 +771,33 @@ function upsertRingSenseAIScore({ body, score, logFormat }) {
|
|
|
711
771
|
if (!score) return body;
|
|
712
772
|
|
|
713
773
|
let result = body;
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
result
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
774
|
+
let scoreRegex = null;
|
|
775
|
+
|
|
776
|
+
switch (logFormat) {
|
|
777
|
+
case LOG_DETAILS_FORMAT_TYPE.HTML:
|
|
778
|
+
scoreRegex = /(?:<li>)?<b>Call score<\/b>:\s*([^<\n]+)(?:<\/li>|(?=<|$))/i;
|
|
779
|
+
if (scoreRegex.test(result)) {
|
|
780
|
+
result = result.replace(scoreRegex, `<li><b>Call score</b>: ${score}</li>`);
|
|
781
|
+
} else {
|
|
782
|
+
result += `<li><b>Call score</b>: ${score}</li>`;
|
|
783
|
+
}
|
|
784
|
+
break;
|
|
785
|
+
case LOG_DETAILS_FORMAT_TYPE.MARKDOWN:
|
|
786
|
+
scoreRegex = /\*\*Call score\*\*: [^\n]*\n*/;
|
|
787
|
+
if (scoreRegex.test(result)) {
|
|
788
|
+
result = result.replace(scoreRegex, `**Call score**: ${score}\n`);
|
|
789
|
+
} else {
|
|
790
|
+
result += `**Call score**: ${score}\n`;
|
|
791
|
+
}
|
|
792
|
+
break;
|
|
793
|
+
case LOG_DETAILS_FORMAT_TYPE.PLAIN_TEXT:
|
|
794
|
+
scoreRegex = /- Call score:\s*([^<\n]+)(?=\n|$)/i;
|
|
795
|
+
if (scoreRegex.test(result)) {
|
|
796
|
+
result = result.replace(scoreRegex, `- Call score: ${score}`);
|
|
797
|
+
} else {
|
|
798
|
+
result += `- Call score: ${score}\n`;
|
|
799
|
+
}
|
|
800
|
+
break;
|
|
735
801
|
}
|
|
736
802
|
return result;
|
|
737
803
|
}
|
|
@@ -741,28 +807,34 @@ function upsertRingSenseBulletedSummary({ body, summary, logFormat }) {
|
|
|
741
807
|
|
|
742
808
|
let result = body;
|
|
743
809
|
const clearedSummary = summary.replace(/\n+$/, '');
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
result
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
810
|
+
let summaryRegex = null;
|
|
811
|
+
|
|
812
|
+
switch (logFormat) {
|
|
813
|
+
case LOG_DETAILS_FORMAT_TYPE.HTML:
|
|
814
|
+
summaryRegex = /<div><b>RingSense bulleted summary<\/b><br>(.+?)<\/div>/;
|
|
815
|
+
const formattedSummary = clearedSummary.replace(/(?:\r\n|\r|\n)/g, '<br>');
|
|
816
|
+
if (summaryRegex.test(result)) {
|
|
817
|
+
result = result.replace(summaryRegex, `<div><b>RingSense bulleted summary</b><br>${formattedSummary}</div>`);
|
|
818
|
+
} else {
|
|
819
|
+
result += `<div><b>RingSense bulleted summary</b><br>${formattedSummary}</div>`;
|
|
820
|
+
}
|
|
821
|
+
break;
|
|
822
|
+
case LOG_DETAILS_FORMAT_TYPE.MARKDOWN:
|
|
823
|
+
summaryRegex = /### RingSense bulleted summary\n([\s\S]*?)(?=\n### |\n$|$)/;
|
|
824
|
+
if (summaryRegex.test(result)) {
|
|
825
|
+
result = result.replace(summaryRegex, `### RingSense bulleted summary\n${summary}\n`);
|
|
826
|
+
} else {
|
|
827
|
+
result += `### RingSense bulleted summary\n${summary}\n`;
|
|
828
|
+
}
|
|
829
|
+
break;
|
|
830
|
+
case LOG_DETAILS_FORMAT_TYPE.PLAIN_TEXT:
|
|
831
|
+
summaryRegex = /- RingSense bulleted summary:\s*([^<\n]+)(?=\n|$)/i;
|
|
832
|
+
if (summaryRegex.test(result)) {
|
|
833
|
+
result = result.replace(summaryRegex, `- RingSense bulleted summary:\n${summary}\n--- END`);
|
|
834
|
+
} else {
|
|
835
|
+
result += `\n- RingSense bulleted summary:\n${summary}\n--- END\n`;
|
|
836
|
+
}
|
|
837
|
+
break;
|
|
766
838
|
}
|
|
767
839
|
return result;
|
|
768
840
|
}
|
|
@@ -771,27 +843,33 @@ function upsertRingSenseLink({ body, link, logFormat }) {
|
|
|
771
843
|
if (!link) return body;
|
|
772
844
|
|
|
773
845
|
let result = body;
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
result
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
846
|
+
let linkRegex = null;
|
|
847
|
+
|
|
848
|
+
switch (logFormat) {
|
|
849
|
+
case LOG_DETAILS_FORMAT_TYPE.HTML:
|
|
850
|
+
linkRegex = /(?:<li>)?<b>RingSense recording link<\/b>:\s*(?:<a[^>]*>[^<]*<\/a>|[^<]+)(?:<\/li>|(?=<|$))/i;
|
|
851
|
+
if (linkRegex.test(result)) {
|
|
852
|
+
result = result.replace(linkRegex, `<li><b>RingSense recording link</b>: <a target="_blank" href="${link}">open</a></li>`);
|
|
853
|
+
} else {
|
|
854
|
+
result += `<li><b>RingSense recording link</b>: <a target="_blank" href="${link}">open</a></li>`;
|
|
855
|
+
}
|
|
856
|
+
break;
|
|
857
|
+
case LOG_DETAILS_FORMAT_TYPE.MARKDOWN:
|
|
858
|
+
linkRegex = /\*\*RingSense recording link\*\*:\s*([^<\n]+)(?=\n|$)/i;
|
|
859
|
+
if (linkRegex.test(result)) {
|
|
860
|
+
result = result.replace(linkRegex, `**RingSense recording link**: ${link}\n`);
|
|
861
|
+
} else {
|
|
862
|
+
result += `**RingSense recording link**: ${link}\n`;
|
|
863
|
+
}
|
|
864
|
+
break;
|
|
865
|
+
case LOG_DETAILS_FORMAT_TYPE.PLAIN_TEXT:
|
|
866
|
+
linkRegex = /- RingSense recording link:\s*([^<\n]+)(?=\n|$)/i;
|
|
867
|
+
if (linkRegex.test(result)) {
|
|
868
|
+
result = result.replace(linkRegex, `- RingSense recording link: ${link}`);
|
|
869
|
+
} else {
|
|
870
|
+
result += `- RingSense recording link: ${link}\n`;
|
|
871
|
+
}
|
|
872
|
+
break;
|
|
795
873
|
}
|
|
796
874
|
return result;
|
|
797
875
|
}
|