@app-connect/core 1.6.4 → 1.7.0-beta.1
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/handlers/admin.js +267 -0
- package/handlers/auth.js +29 -3
- package/handlers/calldown.js +60 -0
- package/handlers/log.js +28 -6
- package/index.js +310 -3
- package/lib/callLogComposer.js +110 -15
- package/lib/ringcentral.js +275 -0
- package/lib/util.js +26 -1
- package/models/adminConfigModel.js +18 -1
- package/models/callDownListModel.js +35 -0
- package/models/userModel.js +4 -0
- package/package.json +3 -3
- package/releaseNotes.json +44 -0
package/index.js
CHANGED
|
@@ -4,6 +4,8 @@ const bodyParser = require('body-parser');
|
|
|
4
4
|
const dynamoose = require('dynamoose');
|
|
5
5
|
const axios = require('axios');
|
|
6
6
|
const { UserModel } = require('./models/userModel');
|
|
7
|
+
const { CallDownListModel } = require('./models/callDownListModel');
|
|
8
|
+
const { Op } = require('sequelize');
|
|
7
9
|
const { CallLogModel } = require('./models/callLogModel');
|
|
8
10
|
const { MessageLogModel } = require('./models/messageLogModel');
|
|
9
11
|
const { AdminConfigModel } = require('./models/adminConfigModel');
|
|
@@ -20,6 +22,7 @@ const releaseNotes = require('./releaseNotes.json');
|
|
|
20
22
|
const analytics = require('./lib/analytics');
|
|
21
23
|
const util = require('./lib/util');
|
|
22
24
|
const adapterRegistry = require('./adapter/registry');
|
|
25
|
+
const calldown = require('./handlers/calldown');
|
|
23
26
|
|
|
24
27
|
let packageJson = null;
|
|
25
28
|
try {
|
|
@@ -44,6 +47,7 @@ async function initDB() {
|
|
|
44
47
|
await MessageLogModel.sync();
|
|
45
48
|
await AdminConfigModel.sync();
|
|
46
49
|
await CacheModel.sync();
|
|
50
|
+
await CallDownListModel.sync();
|
|
47
51
|
}
|
|
48
52
|
}
|
|
49
53
|
|
|
@@ -331,6 +335,58 @@ function createCoreRouter() {
|
|
|
331
335
|
});
|
|
332
336
|
});
|
|
333
337
|
|
|
338
|
+
router.post('/admin/userMapping', async function (req, res) {
|
|
339
|
+
const requestStartTime = new Date().getTime();
|
|
340
|
+
let platformName = null;
|
|
341
|
+
let success = false;
|
|
342
|
+
const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
|
|
343
|
+
try {
|
|
344
|
+
const jwtToken = req.query.jwtToken;
|
|
345
|
+
if (jwtToken) {
|
|
346
|
+
const unAuthData = jwt.decodeJwt(jwtToken);
|
|
347
|
+
platformName = unAuthData?.platform ?? 'Unknown';
|
|
348
|
+
const user = await UserModel.findByPk(unAuthData?.id);
|
|
349
|
+
if (!user) {
|
|
350
|
+
res.status(400).send('User not found');
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
const { isValidated, rcAccountId } = await adminCore.validateAdminRole({ rcAccessToken: req.query.rcAccessToken });
|
|
354
|
+
const hashedRcAccountId = util.getHashValue(rcAccountId, process.env.HASH_KEY);
|
|
355
|
+
if (isValidated) {
|
|
356
|
+
const userMapping = await adminCore.getUserMapping({ user, hashedRcAccountId, rcExtensionList: req.body.rcExtensionList });
|
|
357
|
+
res.status(200).send(userMapping);
|
|
358
|
+
success = true;
|
|
359
|
+
}
|
|
360
|
+
else {
|
|
361
|
+
res.status(401).send('Admin validation failed');
|
|
362
|
+
success = true;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
else {
|
|
366
|
+
res.status(400).send('Please go to Settings and authorize CRM platform');
|
|
367
|
+
success = false;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
catch (e) {
|
|
371
|
+
console.log(`${e.stack}`);
|
|
372
|
+
res.status(400).send(e);
|
|
373
|
+
}
|
|
374
|
+
const requestEndTime = new Date().getTime();
|
|
375
|
+
analytics.track({
|
|
376
|
+
eventName: 'Get user mapping',
|
|
377
|
+
interfaceName: 'getUserMapping',
|
|
378
|
+
adapterName: platformName,
|
|
379
|
+
accountId: hashedAccountId,
|
|
380
|
+
extensionId: hashedExtensionId,
|
|
381
|
+
success,
|
|
382
|
+
requestDuration: (requestEndTime - requestStartTime) / 1000,
|
|
383
|
+
userAgent,
|
|
384
|
+
ip,
|
|
385
|
+
author,
|
|
386
|
+
eventAddedVia
|
|
387
|
+
});
|
|
388
|
+
});
|
|
389
|
+
|
|
334
390
|
router.get('/admin/serverLoggingSettings', async function (req, res) {
|
|
335
391
|
const requestStartTime = new Date().getTime();
|
|
336
392
|
let platformName = null;
|
|
@@ -948,7 +1004,7 @@ function createCoreRouter() {
|
|
|
948
1004
|
}
|
|
949
1005
|
const { id: userId, platform } = decodedToken;
|
|
950
1006
|
platformName = platform;
|
|
951
|
-
const { successful, logId, returnMessage, extraDataTracking } = await logCore.createCallLog({ platform, userId, incomingData: req.body, isFromSSCL: userAgent === 'SSCL' });
|
|
1007
|
+
const { successful, logId, returnMessage, extraDataTracking } = await logCore.createCallLog({ platform, userId, incomingData: req.body, hashedAccountId: hashedAccountId ?? util.getHashValue(req.body.logInfo?.accountId, process.env.HASH_KEY), isFromSSCL: userAgent === 'SSCL' });
|
|
952
1008
|
if (extraDataTracking) {
|
|
953
1009
|
extraData = extraDataTracking;
|
|
954
1010
|
}
|
|
@@ -1000,7 +1056,7 @@ function createCoreRouter() {
|
|
|
1000
1056
|
}
|
|
1001
1057
|
const { id: userId, platform } = decodedToken;
|
|
1002
1058
|
platformName = platform;
|
|
1003
|
-
const { successful, logId, updatedNote, returnMessage, extraDataTracking } = await logCore.updateCallLog({ platform, userId, incomingData: req.body, isFromSSCL: userAgent === 'SSCL' });
|
|
1059
|
+
const { successful, logId, updatedNote, returnMessage, extraDataTracking } = await logCore.updateCallLog({ platform, userId, incomingData: req.body, hashedAccountId: hashedAccountId ?? util.getHashValue(req.body.accountId, process.env.HASH_KEY), isFromSSCL: userAgent === 'SSCL' });
|
|
1004
1060
|
if (extraDataTracking) {
|
|
1005
1061
|
extraData = extraDataTracking;
|
|
1006
1062
|
}
|
|
@@ -1147,6 +1203,174 @@ function createCoreRouter() {
|
|
|
1147
1203
|
});
|
|
1148
1204
|
});
|
|
1149
1205
|
|
|
1206
|
+
router.post('/calldown', async function (req, res) {
|
|
1207
|
+
const requestStartTime = new Date().getTime();
|
|
1208
|
+
let platformName = null;
|
|
1209
|
+
let success = false;
|
|
1210
|
+
let statusCode = 200;
|
|
1211
|
+
const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
|
|
1212
|
+
try {
|
|
1213
|
+
const jwtToken = req.query.jwtToken;
|
|
1214
|
+
if (!jwtToken) {
|
|
1215
|
+
res.status(400).send('Please go to Settings and authorize CRM platform');
|
|
1216
|
+
return;
|
|
1217
|
+
}
|
|
1218
|
+
const { id } = await calldown.schedule({ jwtToken, rcAccessToken: req.query.rcAccessToken, body: req.body });
|
|
1219
|
+
success = true;
|
|
1220
|
+
res.status(200).send({ successful: true, id });
|
|
1221
|
+
} catch (e) {
|
|
1222
|
+
console.log(`platform: ${platformName} \n${e.stack}`);
|
|
1223
|
+
statusCode = e.response?.status ?? 'unknown';
|
|
1224
|
+
res.status(400).send(e);
|
|
1225
|
+
success = false;
|
|
1226
|
+
}
|
|
1227
|
+
const requestEndTime = new Date().getTime();
|
|
1228
|
+
analytics.track({
|
|
1229
|
+
eventName: 'Schedule call down',
|
|
1230
|
+
interfaceName: 'scheduleCallDown',
|
|
1231
|
+
adapterName: platformName,
|
|
1232
|
+
accountId: hashedAccountId,
|
|
1233
|
+
extensionId: hashedExtensionId,
|
|
1234
|
+
success,
|
|
1235
|
+
requestDuration: (requestEndTime - requestStartTime) / 1000,
|
|
1236
|
+
userAgent,
|
|
1237
|
+
ip,
|
|
1238
|
+
author,
|
|
1239
|
+
extras: {
|
|
1240
|
+
statusCode
|
|
1241
|
+
},
|
|
1242
|
+
eventAddedVia
|
|
1243
|
+
});
|
|
1244
|
+
});
|
|
1245
|
+
|
|
1246
|
+
|
|
1247
|
+
router.get('/calldown', async function (req, res) {
|
|
1248
|
+
const requestStartTime = new Date().getTime();
|
|
1249
|
+
let platformName = null;
|
|
1250
|
+
let success = false;
|
|
1251
|
+
let statusCode = 200;
|
|
1252
|
+
const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
|
|
1253
|
+
try {
|
|
1254
|
+
const jwtToken = req.query.jwtToken;
|
|
1255
|
+
if (!jwtToken) {
|
|
1256
|
+
res.status(400).send('Please go to Settings and authorize CRM platform');
|
|
1257
|
+
return;
|
|
1258
|
+
}
|
|
1259
|
+
const { items } = await calldown.list({ jwtToken, status: req.query.status });
|
|
1260
|
+
success = true;
|
|
1261
|
+
res.status(200).send({ successful: true, items });
|
|
1262
|
+
} catch (e) {
|
|
1263
|
+
console.log(`platform: ${platformName} \n${e.stack}`);
|
|
1264
|
+
statusCode = e.response?.status ?? 'unknown';
|
|
1265
|
+
res.status(400).send(e);
|
|
1266
|
+
success = false;
|
|
1267
|
+
}
|
|
1268
|
+
const requestEndTime = new Date().getTime();
|
|
1269
|
+
analytics.track({
|
|
1270
|
+
eventName: 'Get call down list',
|
|
1271
|
+
interfaceName: 'getCallDownList',
|
|
1272
|
+
adapterName: platformName,
|
|
1273
|
+
accountId: hashedAccountId,
|
|
1274
|
+
extensionId: hashedExtensionId,
|
|
1275
|
+
success,
|
|
1276
|
+
requestDuration: (requestEndTime - requestStartTime) / 1000,
|
|
1277
|
+
userAgent,
|
|
1278
|
+
ip,
|
|
1279
|
+
author,
|
|
1280
|
+
extras: { statusCode },
|
|
1281
|
+
eventAddedVia
|
|
1282
|
+
});
|
|
1283
|
+
});
|
|
1284
|
+
|
|
1285
|
+
|
|
1286
|
+
router.delete('/calldown/:id', async function (req, res) {
|
|
1287
|
+
const requestStartTime = new Date().getTime();
|
|
1288
|
+
let platformName = null;
|
|
1289
|
+
let success = false;
|
|
1290
|
+
let statusCode = 200;
|
|
1291
|
+
const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
|
|
1292
|
+
try {
|
|
1293
|
+
const jwtToken = req.query.jwtToken;
|
|
1294
|
+
const id = req.query.id;
|
|
1295
|
+
if (!jwtToken) {
|
|
1296
|
+
res.status(400).send('Please go to Settings and authorize CRM platform');
|
|
1297
|
+
return;
|
|
1298
|
+
}
|
|
1299
|
+
const rid = req.params.id || id;
|
|
1300
|
+
if (!rid) {
|
|
1301
|
+
res.status(400).send('Missing id');
|
|
1302
|
+
return;
|
|
1303
|
+
}
|
|
1304
|
+
await calldown.remove({ jwtToken, id: rid });
|
|
1305
|
+
success = true;
|
|
1306
|
+
res.status(200).send({ successful: true });
|
|
1307
|
+
} catch (e) {
|
|
1308
|
+
console.log(`platform: ${platformName} \n${e.stack}`);
|
|
1309
|
+
statusCode = e.response?.status ?? 'unknown';
|
|
1310
|
+
res.status(400).send(e);
|
|
1311
|
+
success = false;
|
|
1312
|
+
}
|
|
1313
|
+
const requestEndTime = new Date().getTime();
|
|
1314
|
+
analytics.track({
|
|
1315
|
+
eventName: 'Delete call down item',
|
|
1316
|
+
interfaceName: 'deleteCallDownItem',
|
|
1317
|
+
adapterName: platformName,
|
|
1318
|
+
accountId: hashedAccountId,
|
|
1319
|
+
extensionId: hashedExtensionId,
|
|
1320
|
+
success,
|
|
1321
|
+
requestDuration: (requestEndTime - requestStartTime) / 1000,
|
|
1322
|
+
userAgent,
|
|
1323
|
+
ip,
|
|
1324
|
+
author,
|
|
1325
|
+
extras: { statusCode },
|
|
1326
|
+
eventAddedVia
|
|
1327
|
+
});
|
|
1328
|
+
});
|
|
1329
|
+
|
|
1330
|
+
|
|
1331
|
+
router.patch('/calldown/:id', async function (req, res) {
|
|
1332
|
+
const requestStartTime = new Date().getTime();
|
|
1333
|
+
let platformName = null;
|
|
1334
|
+
let success = false;
|
|
1335
|
+
let statusCode = 200;
|
|
1336
|
+
const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
|
|
1337
|
+
try {
|
|
1338
|
+
const jwtToken = req.query.jwtToken;
|
|
1339
|
+
if (!jwtToken) {
|
|
1340
|
+
res.status(400).send('Please go to Settings and authorize CRM platform');
|
|
1341
|
+
return;
|
|
1342
|
+
}
|
|
1343
|
+
const id = req.params.id || req.body?.id;
|
|
1344
|
+
if (!id) {
|
|
1345
|
+
res.status(400).send('Missing id');
|
|
1346
|
+
return;
|
|
1347
|
+
}
|
|
1348
|
+
await calldown.markCalled({ jwtToken, id, lastCallAt: req.body?.lastCallAt });
|
|
1349
|
+
success = true;
|
|
1350
|
+
res.status(200).send({ successful: true });
|
|
1351
|
+
} catch (e) {
|
|
1352
|
+
console.log(`platform: ${platformName} \n${e.stack}`);
|
|
1353
|
+
statusCode = e.response?.status ?? 'unknown';
|
|
1354
|
+
res.status(400).send(e);
|
|
1355
|
+
success = false;
|
|
1356
|
+
}
|
|
1357
|
+
const requestEndTime = new Date().getTime();
|
|
1358
|
+
analytics.track({
|
|
1359
|
+
eventName: 'Mark call down called',
|
|
1360
|
+
interfaceName: 'markCallDownCalled',
|
|
1361
|
+
adapterName: platformName,
|
|
1362
|
+
accountId: hashedAccountId,
|
|
1363
|
+
extensionId: hashedExtensionId,
|
|
1364
|
+
success,
|
|
1365
|
+
requestDuration: (requestEndTime - requestStartTime) / 1000,
|
|
1366
|
+
userAgent,
|
|
1367
|
+
ip,
|
|
1368
|
+
author,
|
|
1369
|
+
extras: { statusCode },
|
|
1370
|
+
eventAddedVia
|
|
1371
|
+
});
|
|
1372
|
+
});
|
|
1373
|
+
|
|
1150
1374
|
router.get('/custom/contact/search', async function (req, res) {
|
|
1151
1375
|
const requestStartTime = new Date().getTime();
|
|
1152
1376
|
let platformName = null;
|
|
@@ -1191,8 +1415,91 @@ function createCoreRouter() {
|
|
|
1191
1415
|
statusCode
|
|
1192
1416
|
}
|
|
1193
1417
|
});
|
|
1418
|
+
});
|
|
1419
|
+
|
|
1420
|
+
router.get('/ringcentral/admin/report', async function (req, res) {
|
|
1421
|
+
const requestStartTime = new Date().getTime();
|
|
1422
|
+
let platformName = null;
|
|
1423
|
+
let success = false;
|
|
1424
|
+
const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
|
|
1425
|
+
const jwtToken = req.query.jwtToken;
|
|
1426
|
+
try {
|
|
1427
|
+
if (jwtToken) {
|
|
1428
|
+
const unAuthData = jwt.decodeJwt(jwtToken);
|
|
1429
|
+
const user = await UserModel.findByPk(unAuthData?.id);
|
|
1430
|
+
if (!user) {
|
|
1431
|
+
res.status(400).send('User not found');
|
|
1432
|
+
return;
|
|
1433
|
+
}
|
|
1434
|
+
const report = await adminCore.getAdminReport({ rcAccountId: user.rcAccountId, timezone: req.query.timezone, timeFrom: req.query.timeFrom, timeTo: req.query.timeTo });
|
|
1435
|
+
res.status(200).send(report);
|
|
1436
|
+
success = true;
|
|
1437
|
+
return;
|
|
1438
|
+
}
|
|
1439
|
+
res.status(400).send('Invalid request');
|
|
1440
|
+
success = false;
|
|
1441
|
+
}
|
|
1442
|
+
catch (e) {
|
|
1443
|
+
console.log(`${e.stack}`);
|
|
1444
|
+
res.status(400).send(e);
|
|
1445
|
+
}
|
|
1446
|
+
const requestEndTime = new Date().getTime();
|
|
1447
|
+
analytics.track({
|
|
1448
|
+
eventName: 'Get admin report',
|
|
1449
|
+
interfaceName: 'getAdminReport',
|
|
1450
|
+
adapterName: platformName,
|
|
1451
|
+
accountId: hashedAccountId,
|
|
1452
|
+
extensionId: hashedExtensionId,
|
|
1453
|
+
success,
|
|
1454
|
+
requestDuration: (requestEndTime - requestStartTime) / 1000,
|
|
1455
|
+
userAgent,
|
|
1456
|
+
ip,
|
|
1457
|
+
author,
|
|
1458
|
+
eventAddedVia
|
|
1459
|
+
});
|
|
1460
|
+
});
|
|
1194
1461
|
|
|
1462
|
+
router.get('/ringcentral/admin/userReport', async function (req, res) {
|
|
1463
|
+
const requestStartTime = new Date().getTime();
|
|
1464
|
+
let platformName = null;
|
|
1465
|
+
let success = false;
|
|
1466
|
+
const { hashedExtensionId, hashedAccountId, userAgent, ip, author, eventAddedVia } = getAnalyticsVariablesInReqHeaders({ headers: req.headers })
|
|
1467
|
+
const jwtToken = req.query.jwtToken;
|
|
1468
|
+
try {
|
|
1469
|
+
if (jwtToken) {
|
|
1470
|
+
const unAuthData = jwt.decodeJwt(jwtToken);
|
|
1471
|
+
const user = await UserModel.findByPk(unAuthData?.id);
|
|
1472
|
+
if (!user) {
|
|
1473
|
+
res.status(400).send('User not found');
|
|
1474
|
+
return;
|
|
1475
|
+
}
|
|
1476
|
+
const report = await adminCore.getUserReport({ rcAccountId: user.rcAccountId, rcExtensionId: req.query.rcExtensionId, timezone: req.query.timezone, timeFrom: req.query.timeFrom, timeTo: req.query.timeTo });
|
|
1477
|
+
res.status(200).send(report);
|
|
1478
|
+
return;
|
|
1479
|
+
}
|
|
1480
|
+
res.status(400).send('Invalid request');
|
|
1481
|
+
success = false;
|
|
1482
|
+
}
|
|
1483
|
+
catch (e) {
|
|
1484
|
+
console.log(`${e.stack}`);
|
|
1485
|
+
res.status(400).send(e);
|
|
1486
|
+
}
|
|
1487
|
+
const requestEndTime = new Date().getTime();
|
|
1488
|
+
analytics.track({
|
|
1489
|
+
eventName: 'Get user report',
|
|
1490
|
+
interfaceName: 'getUserReport',
|
|
1491
|
+
adapterName: platformName,
|
|
1492
|
+
accountId: hashedAccountId,
|
|
1493
|
+
extensionId: hashedExtensionId,
|
|
1494
|
+
success,
|
|
1495
|
+
requestDuration: (requestEndTime - requestStartTime) / 1000,
|
|
1496
|
+
userAgent,
|
|
1497
|
+
ip,
|
|
1498
|
+
author,
|
|
1499
|
+
eventAddedVia
|
|
1500
|
+
});
|
|
1195
1501
|
});
|
|
1502
|
+
|
|
1196
1503
|
if (process.env.IS_PROD === 'false') {
|
|
1197
1504
|
router.post('/registerMockUser', async function (req, res) {
|
|
1198
1505
|
const secretKey = req.query.secretKey;
|
|
@@ -1254,7 +1561,7 @@ function createCoreMiddleware() {
|
|
|
1254
1561
|
return [
|
|
1255
1562
|
bodyParser.json(),
|
|
1256
1563
|
cors({
|
|
1257
|
-
methods: ['GET', 'POST', 'PATCH', 'PUT']
|
|
1564
|
+
methods: ['GET', 'POST', 'PATCH', 'PUT', 'DELETE']
|
|
1258
1565
|
})
|
|
1259
1566
|
];
|
|
1260
1567
|
}
|
package/lib/callLogComposer.js
CHANGED
|
@@ -61,10 +61,10 @@ async function composeCallLog(params) {
|
|
|
61
61
|
body = upsertCallSessionId({ body, id: callLog.sessionId, logFormat });
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
if (userSettings?.addRingCentralUserName?.value) {
|
|
65
|
+
const ringcentralUsername = (callLog.direction === 'Inbound' ? callLog?.to?.name : callLog?.from?.name) ?? '(pending...)';
|
|
66
66
|
body = upsertRingCentralUserName({ body, userName: ringcentralUsername, logFormat });
|
|
67
|
-
}
|
|
67
|
+
}
|
|
68
68
|
|
|
69
69
|
const ringcentralNumber = callLog.direction === 'Inbound' ? callLog?.to?.phoneNumber : callLog?.from?.phoneNumber;
|
|
70
70
|
if (ringcentralNumber && (userSettings?.addRingCentralNumber?.value ?? false)) {
|
|
@@ -115,6 +115,10 @@ async function composeCallLog(params) {
|
|
|
115
115
|
body = upsertTranscript({ body, transcript, logFormat });
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
+
if (callLog?.legs && (userSettings?.addCallLogLegs?.value ?? true)) {
|
|
119
|
+
body = upsertLegs({ body, legs: callLog.legs, logFormat });
|
|
120
|
+
}
|
|
121
|
+
|
|
118
122
|
return body;
|
|
119
123
|
}
|
|
120
124
|
|
|
@@ -184,22 +188,37 @@ function upsertRingCentralUserName({ body, userName, logFormat }) {
|
|
|
184
188
|
|
|
185
189
|
if (logFormat === LOG_DETAILS_FORMAT_TYPE.HTML) {
|
|
186
190
|
const userNameRegex = /(?:<li>)?<b>RingCentral user name<\/b>:\s*([^<\n]+)(?:<\/li>|(?=<|$))/i;
|
|
187
|
-
|
|
188
|
-
|
|
191
|
+
const match = body.match(userNameRegex);
|
|
192
|
+
if (match) {
|
|
193
|
+
// Only replace if existing value is (pending...)
|
|
194
|
+
if (match[1].trim() === '(pending...)') {
|
|
195
|
+
return body.replace(userNameRegex, `<li><b>RingCentral user name</b>: ${userName}</li>`);
|
|
196
|
+
}
|
|
197
|
+
return body;
|
|
189
198
|
} else {
|
|
190
199
|
return body + `<li><b>RingCentral user name</b>: ${userName}</li>`;
|
|
191
200
|
}
|
|
192
201
|
} else if (logFormat === LOG_DETAILS_FORMAT_TYPE.MARKDOWN) {
|
|
193
|
-
const userNameRegex = /\*\*RingCentral user name\*\*: [^\n]
|
|
194
|
-
|
|
195
|
-
|
|
202
|
+
const userNameRegex = /\*\*RingCentral user name\*\*: ([^\n]*)\n*/i;
|
|
203
|
+
const match = body.match(userNameRegex);
|
|
204
|
+
if (match) {
|
|
205
|
+
// Only replace if existing value is (pending...)
|
|
206
|
+
if (match[1].trim() === '(pending...)') {
|
|
207
|
+
return body.replace(userNameRegex, `**RingCentral user name**: ${userName}\n`);
|
|
208
|
+
}
|
|
209
|
+
return body;
|
|
196
210
|
} else {
|
|
197
211
|
return body + `**RingCentral user name**: ${userName}\n`;
|
|
198
212
|
}
|
|
199
213
|
} else {
|
|
200
|
-
const userNameRegex = /- RingCentral user name: [^\n]
|
|
201
|
-
|
|
202
|
-
|
|
214
|
+
const userNameRegex = /- RingCentral user name: ([^\n]*)\n*/;
|
|
215
|
+
const match = body.match(userNameRegex);
|
|
216
|
+
if (match) {
|
|
217
|
+
// Only replace if existing value is (pending...)
|
|
218
|
+
if (match[1].trim() === '(pending...)') {
|
|
219
|
+
return body.replace(userNameRegex, `- RingCentral user name: ${userName}\n`);
|
|
220
|
+
}
|
|
221
|
+
return body;
|
|
203
222
|
} else {
|
|
204
223
|
return body + `- RingCentral user name: ${userName}\n`;
|
|
205
224
|
}
|
|
@@ -327,9 +346,9 @@ function upsertCallDateTime({ body, startTime, timezoneOffset, logFormat, logDat
|
|
|
327
346
|
}
|
|
328
347
|
} else {
|
|
329
348
|
// Handle duplicated Date/Time entries and match complete date/time values
|
|
330
|
-
const dateTimeRegex =
|
|
349
|
+
const dateTimeRegex = /^(- Date\/Time:).*$/m;
|
|
331
350
|
if (dateTimeRegex.test(result)) {
|
|
332
|
-
result = result.replace(dateTimeRegex, `- Date/Time: ${formattedDateTime}
|
|
351
|
+
result = result.replace(dateTimeRegex, `- Date/Time: ${formattedDateTime}`);
|
|
333
352
|
} else {
|
|
334
353
|
result += `- Date/Time: ${formattedDateTime}\n`;
|
|
335
354
|
}
|
|
@@ -521,6 +540,81 @@ function upsertTranscript({ body, transcript, logFormat }) {
|
|
|
521
540
|
return result;
|
|
522
541
|
}
|
|
523
542
|
|
|
543
|
+
function getLegPartyInfo(info) {
|
|
544
|
+
let phoneNumber = info.phoneNumber;
|
|
545
|
+
let extensionNumber = info.extensionNumber;
|
|
546
|
+
let numberInfo = phoneNumber;
|
|
547
|
+
if (!phoneNumber && !extensionNumber) {
|
|
548
|
+
return '';
|
|
549
|
+
}
|
|
550
|
+
if (extensionNumber && phoneNumber) {
|
|
551
|
+
numberInfo = `${phoneNumber}, ext ${extensionNumber}`;
|
|
552
|
+
}
|
|
553
|
+
if (phoneNumber && !extensionNumber) {
|
|
554
|
+
numberInfo = phoneNumber;
|
|
555
|
+
}
|
|
556
|
+
if (!phoneNumber && extensionNumber) {
|
|
557
|
+
numberInfo = `ext ${extensionNumber}`;
|
|
558
|
+
}
|
|
559
|
+
if (info.name) {
|
|
560
|
+
return `${info.name}, ${numberInfo}`;
|
|
561
|
+
}
|
|
562
|
+
return numberInfo;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
function getLegsJourney(legs) {
|
|
566
|
+
return legs.map((leg, index) => {
|
|
567
|
+
if (index === 0) {
|
|
568
|
+
if (leg.direction === 'Outbound') {
|
|
569
|
+
return `Made call from ${getLegPartyInfo(leg.from)}`;
|
|
570
|
+
} else {
|
|
571
|
+
return `Received call at ${getLegPartyInfo(leg.to)}`;
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
if (leg.direction === 'Outbound') {
|
|
575
|
+
let party = leg.from;
|
|
576
|
+
if (leg.legType === 'PstnToSip') {
|
|
577
|
+
party = leg.to;
|
|
578
|
+
}
|
|
579
|
+
return `Transferred to ${getLegPartyInfo(party)}, duration: ${leg.duration} second${leg.duration > 1 ? 's' : ''}`;
|
|
580
|
+
} else {
|
|
581
|
+
return `Transferred to ${getLegPartyInfo(leg.to)}, duration: ${leg.duration} second${leg.duration > 1 ? 's' : ''}`;
|
|
582
|
+
}
|
|
583
|
+
}).join('\n');
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
function upsertLegs({ body, legs, logFormat }) {
|
|
587
|
+
if (!legs || legs.length === 0) return body;
|
|
588
|
+
|
|
589
|
+
let result = body;
|
|
590
|
+
let legsJourney = getLegsJourney(legs);
|
|
591
|
+
if (logFormat === LOG_DETAILS_FORMAT_TYPE.HTML) {
|
|
592
|
+
legsJourney = legsJourney.replace(/(?:\r\n|\r|\n)/g, '<br>');
|
|
593
|
+
const legsRegex = /<div><b>Call journey<\/b><br>(.+?)<\/div>/;
|
|
594
|
+
if (legsRegex.test(result)) {
|
|
595
|
+
result = result.replace(legsRegex, `<div><b>Call journey</b><br>${legsJourney}</div>`);
|
|
596
|
+
} else {
|
|
597
|
+
result += `<div><b>Call journey</b><br>${legsJourney}</div>`;
|
|
598
|
+
}
|
|
599
|
+
} else if (logFormat === LOG_DETAILS_FORMAT_TYPE.MARKDOWN) {
|
|
600
|
+
const legsRegex = /### Call journey\n([\s\S]*?)(?=\n### |\n$|$)/;
|
|
601
|
+
if (legsRegex.test(result)) {
|
|
602
|
+
result = result.replace(legsRegex, `### Call journey\n${legsJourney}\n`);
|
|
603
|
+
} else {
|
|
604
|
+
result += `### Call journey\n${legsJourney}\n`;
|
|
605
|
+
}
|
|
606
|
+
} else {
|
|
607
|
+
const legsRegex = /- Call journey:([\s\S]*?)--- JOURNEY END/;
|
|
608
|
+
if (legsRegex.test(result)) {
|
|
609
|
+
result = result.replace(legsRegex, `- Call journey:\n${legsJourney}\n--- JOURNEY END`);
|
|
610
|
+
} else {
|
|
611
|
+
result += `- Call journey:\n${legsJourney}\n--- JOURNEY END\n`;
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
return result;
|
|
616
|
+
}
|
|
617
|
+
|
|
524
618
|
/**
|
|
525
619
|
* Helper function to determine format type for a CRM platform
|
|
526
620
|
* @param {string} platform - CRM platform name
|
|
@@ -547,5 +641,6 @@ module.exports = {
|
|
|
547
641
|
upsertCallResult,
|
|
548
642
|
upsertCallRecording,
|
|
549
643
|
upsertAiNote,
|
|
550
|
-
upsertTranscript
|
|
551
|
-
|
|
644
|
+
upsertTranscript,
|
|
645
|
+
upsertLegs,
|
|
646
|
+
};
|