@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.
Files changed (59) hide show
  1. package/connector/developerPortal.js +43 -0
  2. package/connector/proxy/index.js +10 -3
  3. package/connector/registry.js +8 -6
  4. package/handlers/admin.js +135 -22
  5. package/handlers/auth.js +89 -67
  6. package/handlers/calldown.js +10 -4
  7. package/handlers/contact.js +4 -104
  8. package/handlers/disposition.js +7 -145
  9. package/handlers/log.js +174 -258
  10. package/handlers/user.js +19 -6
  11. package/index.js +280 -47
  12. package/lib/analytics.js +3 -1
  13. package/lib/authSession.js +68 -0
  14. package/lib/callLogComposer.js +498 -420
  15. package/lib/errorHandler.js +206 -0
  16. package/lib/jwt.js +2 -0
  17. package/lib/logger.js +190 -0
  18. package/lib/oauth.js +21 -10
  19. package/lib/ringcentral.js +2 -10
  20. package/lib/sharedSMSComposer.js +471 -0
  21. package/mcp/SupportedPlatforms.md +12 -0
  22. package/mcp/lib/validator.js +91 -0
  23. package/mcp/mcpHandler.js +166 -0
  24. package/mcp/tools/checkAuthStatus.js +110 -0
  25. package/mcp/tools/collectAuthInfo.js +91 -0
  26. package/mcp/tools/createCallLog.js +308 -0
  27. package/mcp/tools/createContact.js +117 -0
  28. package/mcp/tools/createMessageLog.js +283 -0
  29. package/mcp/tools/doAuth.js +190 -0
  30. package/mcp/tools/findContactByName.js +92 -0
  31. package/mcp/tools/findContactByPhone.js +101 -0
  32. package/mcp/tools/getCallLog.js +98 -0
  33. package/mcp/tools/getGoogleFilePicker.js +103 -0
  34. package/mcp/tools/getHelp.js +44 -0
  35. package/mcp/tools/getPublicConnectors.js +53 -0
  36. package/mcp/tools/index.js +64 -0
  37. package/mcp/tools/logout.js +68 -0
  38. package/mcp/tools/rcGetCallLogs.js +78 -0
  39. package/mcp/tools/setConnector.js +69 -0
  40. package/mcp/tools/updateCallLog.js +122 -0
  41. package/models/cacheModel.js +3 -0
  42. package/package.json +71 -70
  43. package/releaseNotes.json +24 -0
  44. package/test/handlers/log.test.js +11 -4
  45. package/test/lib/logger.test.js +206 -0
  46. package/test/lib/ringcentral.test.js +0 -6
  47. package/test/lib/sharedSMSComposer.test.js +1084 -0
  48. package/test/mcp/tools/collectAuthInfo.test.js +234 -0
  49. package/test/mcp/tools/createCallLog.test.js +425 -0
  50. package/test/mcp/tools/createMessageLog.test.js +580 -0
  51. package/test/mcp/tools/doAuth.test.js +376 -0
  52. package/test/mcp/tools/findContactByName.test.js +263 -0
  53. package/test/mcp/tools/findContactByPhone.test.js +284 -0
  54. package/test/mcp/tools/getCallLog.test.js +286 -0
  55. package/test/mcp/tools/getGoogleFilePicker.test.js +281 -0
  56. package/test/mcp/tools/getPublicConnectors.test.js +128 -0
  57. package/test/mcp/tools/logout.test.js +169 -0
  58. package/test/mcp/tools/setConnector.test.js +177 -0
  59. package/test/mcp/tools/updateCallLog.test.js +346 -0
package/handlers/log.js CHANGED
@@ -3,22 +3,30 @@ const { CallLogModel } = require('../models/callLogModel');
3
3
  const { MessageLogModel } = require('../models/messageLogModel');
4
4
  const { UserModel } = require('../models/userModel');
5
5
  const oauth = require('../lib/oauth');
6
- const errorMessage = require('../lib/generalErrorMessage');
7
6
  const { composeCallLog } = require('../lib/callLogComposer');
7
+ const { composeSharedSMSLog } = require('../lib/sharedSMSComposer');
8
8
  const connectorRegistry = require('../connector/registry');
9
9
  const { LOG_DETAILS_FORMAT_TYPE } = require('../lib/constants');
10
10
  const { NoteCache } = require('../models/dynamo/noteCacheSchema');
11
11
  const { Connector } = require('../models/dynamo/connectorSchema');
12
12
  const moment = require('moment');
13
13
  const { getMediaReaderLinkByPlatformMediaLink } = require('../lib/util');
14
+ const logger = require('../lib/logger');
15
+ const { handleApiError, handleDatabaseError } = require('../lib/errorHandler');
14
16
 
15
17
  async function createCallLog({ platform, userId, incomingData, hashedAccountId, isFromSSCL }) {
16
18
  try {
17
- const existingCallLog = await CallLogModel.findOne({
18
- where: {
19
- sessionId: incomingData.logInfo.sessionId
20
- }
21
- });
19
+ let existingCallLog = null;
20
+ try {
21
+ existingCallLog = await CallLogModel.findOne({
22
+ where: {
23
+ sessionId: incomingData.logInfo.sessionId
24
+ }
25
+ });
26
+ }
27
+ catch (error) {
28
+ return handleDatabaseError(error, 'Error finding existing call log');
29
+ }
22
30
  if (existingCallLog) {
23
31
  return {
24
32
  successful: false,
@@ -29,7 +37,13 @@ async function createCallLog({ platform, userId, incomingData, hashedAccountId,
29
37
  }
30
38
  }
31
39
  }
32
- let user = await UserModel.findByPk(userId);
40
+ let user = null;
41
+ try {
42
+ user = await UserModel.findByPk(userId);
43
+ }
44
+ catch (error) {
45
+ return handleDatabaseError(error, 'Error finding user');
46
+ }
33
47
  if (!user || !user.accessToken) {
34
48
  return {
35
49
  successful: false,
@@ -88,12 +102,12 @@ async function createCallLog({ platform, userId, incomingData, hashedAccountId,
88
102
  type: incomingData.contactType ?? "",
89
103
  name: incomingData.contactName ?? ""
90
104
  };
91
-
105
+
92
106
  // Compose call log details centrally
93
107
  const logFormat = platformModule.getLogFormatType ? platformModule.getLogFormatType(platform, proxyConfig) : LOG_DETAILS_FORMAT_TYPE.PLAIN_TEXT;
94
108
  let composedLogDetails = '';
95
109
  if (logFormat === LOG_DETAILS_FORMAT_TYPE.PLAIN_TEXT || logFormat === LOG_DETAILS_FORMAT_TYPE.HTML || logFormat === LOG_DETAILS_FORMAT_TYPE.MARKDOWN) {
96
- composedLogDetails = await composeCallLog({
110
+ composedLogDetails = composeCallLog({
97
111
  logFormat,
98
112
  callLog,
99
113
  contactInfo,
@@ -135,54 +149,23 @@ async function createCallLog({ platform, userId, incomingData, hashedAccountId,
135
149
  proxyConfig,
136
150
  });
137
151
  if (logId) {
138
- await CallLogModel.create({
139
- id: incomingData.logInfo.telephonySessionId || incomingData.logInfo.id,
140
- sessionId: incomingData.logInfo.sessionId,
141
- platform,
142
- thirdPartyLogId: logId,
143
- userId,
144
- contactId
145
- });
152
+ try {
153
+ await CallLogModel.create({
154
+ id: incomingData.logInfo.telephonySessionId || incomingData.logInfo.id,
155
+ sessionId: incomingData.logInfo.sessionId,
156
+ platform,
157
+ thirdPartyLogId: logId,
158
+ userId,
159
+ contactId
160
+ });
161
+ }
162
+ catch (error) {
163
+ return handleDatabaseError(error, 'Error creating call log');
164
+ }
146
165
  }
147
166
  return { successful: !!logId, logId, returnMessage, extraDataTracking };
148
167
  } catch (e) {
149
- console.error(`platform: ${platform} \n${e.stack} \n${JSON.stringify(e.response?.data)}`);
150
- if (e.response?.status === 429) {
151
- return {
152
- successful: false,
153
- returnMessage: errorMessage.rateLimitErrorMessage({ platform })
154
- };
155
- }
156
- else if (e.response?.status >= 400 && e.response?.status < 410) {
157
- return {
158
- successful: false,
159
- returnMessage: errorMessage.authorizationErrorMessage({ platform }),
160
- extraDataTracking: {
161
- statusCode: e.response?.status,
162
- }
163
- };
164
- }
165
- return {
166
- successful: false,
167
- returnMessage:
168
- {
169
- message: `Error creating call log`,
170
- messageType: 'warning',
171
- details: [
172
- {
173
- title: 'Details',
174
- items: [
175
- {
176
- id: '1',
177
- type: 'text',
178
- text: `Please check if your account has permission to CREATE logs.`
179
- }
180
- ]
181
- }
182
- ],
183
- ttl: 5000
184
- }
185
- };
168
+ return handleApiError(e, platform, 'createCallLog', { userId });
186
169
  }
187
170
  }
188
171
 
@@ -233,8 +216,7 @@ async function getCallLog({ userId, sessionIds, platform, requireDetails }) {
233
216
  }
234
217
  });
235
218
  for (const sId of sessionIdsArray) {
236
- if(sId == 0)
237
- {
219
+ if (sId == 0) {
238
220
  logs.push({ sessionId: sId, matched: false });
239
221
  continue;
240
222
  }
@@ -243,7 +225,7 @@ async function getCallLog({ userId, sessionIds, platform, requireDetails }) {
243
225
  logs.push({ sessionId: sId, matched: false });
244
226
  }
245
227
  else {
246
- const getCallLogResult = await platformModule.getCallLog({ user, callLogId: callLog.thirdPartyLogId, contactId: callLog.contactId, authHeader, proxyConfig });
228
+ const getCallLogResult = await platformModule.getCallLog({ user, telephonySessionId: callLog.id, callLogId: callLog.thirdPartyLogId, contactId: callLog.contactId, authHeader, proxyConfig });
247
229
  returnMessage = getCallLogResult.returnMessage;
248
230
  extraDataTracking = getCallLogResult.extraDataTracking;
249
231
  logs.push({ sessionId: callLog.sessionId, matched: true, logId: callLog.thirdPartyLogId, logData: getCallLogResult.callLogInfo });
@@ -271,59 +253,23 @@ async function getCallLog({ userId, sessionIds, platform, requireDetails }) {
271
253
  return { successful: true, logs, returnMessage, extraDataTracking };
272
254
  }
273
255
  catch (e) {
274
- console.error(`platform: ${platform} \n${e.stack} \n${JSON.stringify(e.response?.data)}`);
275
- if (e.response?.status === 429) {
276
- return {
277
- successful: false,
278
- returnMessage: errorMessage.rateLimitErrorMessage({ platform }),
279
- extraDataTracking: {
280
- statusCode: e.response?.status,
281
- }
282
- };
283
- }
284
- else if (e.response?.status >= 400 && e.response?.status < 410) {
285
- return {
286
- successful: false,
287
- returnMessage: errorMessage.authorizationErrorMessage({ platform }),
288
- extraDataTracking: {
289
- statusCode: e.response?.status,
290
- }
291
- };
292
- }
293
- return {
294
- successful: false,
295
- returnMessage:
296
- {
297
- message: `Error getting call log`,
298
- messageType: 'warning',
299
- details: [
300
- {
301
- title: 'Details',
302
- items: [
303
- {
304
- id: '1',
305
- type: 'text',
306
- text: `Please check if your account has permission to READ logs.`
307
- }
308
- ]
309
- }
310
- ],
311
- ttl: 5000
312
- },
313
- extraDataTracking: {
314
- statusCode: e.response?.status,
315
- }
316
- };
256
+ return handleApiError(e, platform, 'getCallLog', { userId, sessionIds, requireDetails });
317
257
  }
318
258
  }
319
259
 
320
260
  async function updateCallLog({ platform, userId, incomingData, hashedAccountId, isFromSSCL }) {
321
261
  try {
322
- const existingCallLog = await CallLogModel.findOne({
323
- where: {
324
- sessionId: incomingData.sessionId
325
- }
326
- });
262
+ let existingCallLog = null;
263
+ try {
264
+ existingCallLog = await CallLogModel.findOne({
265
+ where: {
266
+ sessionId: incomingData.sessionId
267
+ }
268
+ });
269
+ }
270
+ catch (error) {
271
+ return handleDatabaseError(error, 'Error finding existing call log');
272
+ }
327
273
  if (existingCallLog) {
328
274
  const platformModule = connectorRegistry.getConnector(platform);
329
275
  let user = await UserModel.findByPk(userId);
@@ -358,6 +304,7 @@ async function updateCallLog({ platform, userId, incomingData, hashedAccountId,
358
304
  try {
359
305
  const getLogResult = await platformModule.getCallLog({
360
306
  user,
307
+ telephonySessionId: existingCallLog.id,
361
308
  callLogId: existingCallLog.thirdPartyLogId,
362
309
  contactId: existingCallLog.contactId,
363
310
  authHeader,
@@ -371,9 +318,9 @@ async function updateCallLog({ platform, userId, incomingData, hashedAccountId,
371
318
  existingBody = getLogResult.callLogInfo.note;
372
319
  }
373
320
  } catch (error) {
374
- console.log('Error getting existing log details, proceeding with empty body', error);
321
+ logger.error('Error getting existing log details, proceeding with empty body', { stack: error.stack });
375
322
  }
376
- composedLogDetails = await composeCallLog({
323
+ composedLogDetails = composeCallLog({
377
324
  logFormat,
378
325
  existingBody,
379
326
  callLog: {
@@ -434,49 +381,7 @@ async function updateCallLog({ platform, userId, incomingData, hashedAccountId,
434
381
  }
435
382
  return { successful: false };
436
383
  } catch (e) {
437
- console.error(`platform: ${platform} \n${e.stack} \n${JSON.stringify(e.response?.data)}`);
438
- if (e.response?.status === 429) {
439
- return {
440
- successful: false,
441
- returnMessage: errorMessage.rateLimitErrorMessage({ platform }),
442
- extraDataTracking: {
443
- statusCode: e.response?.status,
444
- }
445
- };
446
- }
447
- else if (e.response?.status >= 400 && e.response?.status < 410) {
448
- return {
449
- successful: false,
450
- returnMessage: errorMessage.authorizationErrorMessage({ platform }),
451
- extraDataTracking: {
452
- statusCode: e.response?.status,
453
- }
454
- };
455
- }
456
- return {
457
- successful: false,
458
- returnMessage:
459
- {
460
- message: `Error updating call log`,
461
- messageType: 'warning',
462
- details: [
463
- {
464
- title: 'Details',
465
- items: [
466
- {
467
- id: '1',
468
- type: 'text',
469
- text: `Please check if the log entity still exist on ${platform} and your account has permission to EDIT logs.`
470
- }
471
- ]
472
- }
473
- ],
474
- ttl: 5000
475
- },
476
- extraDataTracking: {
477
- statusCode: e.response?.status,
478
- }
479
- };
384
+ return handleApiError(e, platform, 'updateCallLog', { userId });
480
385
  }
481
386
  }
482
387
 
@@ -498,7 +403,13 @@ async function createMessageLog({ platform, userId, incomingData }) {
498
403
  const platformModule = connectorRegistry.getConnector(platform);
499
404
  const contactNumber = incomingData.logInfo.correspondents[0].phoneNumber;
500
405
  const additionalSubmission = incomingData.additionalSubmission;
501
- let user = await UserModel.findByPk(userId);
406
+ let user = null;
407
+ try {
408
+ user = await UserModel.findByPk(userId);
409
+ }
410
+ catch (error) {
411
+ return handleDatabaseError(error, 'Error finding user');
412
+ }
502
413
  if (!user || !user.accessToken) {
503
414
  return {
504
415
  successful: false,
@@ -546,139 +457,144 @@ async function createMessageLog({ platform, userId, incomingData }) {
546
457
  type: incomingData.contactType ?? "",
547
458
  name: incomingData.contactName ?? ""
548
459
  };
460
+ // For shared SMS
461
+ const assigneeName = incomingData.logInfo.assignee?.name;
462
+ const ownerName = incomingData.logInfo.owner?.name;
463
+ const isSharedSMS = !!ownerName;
464
+
549
465
  const messageIds = incomingData.logInfo.messages.map(m => { return { id: m.id.toString() }; });
550
- const existingMessages = await MessageLogModel.findAll({
551
- where: {
552
- [Op.or]: messageIds
553
- }
554
- });
466
+ let existingMessages = null;
467
+ try {
468
+ existingMessages = await MessageLogModel.findAll({
469
+ where: {
470
+ [Op.or]: messageIds
471
+ }
472
+ });
473
+ }
474
+ catch (error) {
475
+ return handleDatabaseError(error, 'Error finding existing messages');
476
+ }
555
477
  const existingIds = existingMessages.map(m => m.id);
556
478
  const logIds = [];
557
- // reverse the order of messages to log the oldest message first
558
- const reversedMessages = incomingData.logInfo.messages.reverse();
559
- for (const message of reversedMessages) {
560
- if (existingIds.includes(message.id.toString())) {
561
- continue;
562
- }
563
- let recordingLink = null;
564
- if (message.attachments && message.attachments.some(a => a.type === 'AudioRecording')) {
565
- recordingLink = message.attachments.find(a => a.type === 'AudioRecording').link;
566
- }
567
- let faxDocLink = null;
568
- let faxDownloadLink = null;
569
- if (message.attachments && message.attachments.some(a => a.type === 'RenderedDocument')) {
570
- faxDocLink = message.attachments.find(a => a.type === 'RenderedDocument').link;
571
- faxDownloadLink = message.attachments.find(a => a.type === 'RenderedDocument').uri + `?access_token=${incomingData.logInfo.rcAccessToken}`
572
- }
573
- let imageLink = null;
574
- let imageDownloadLink = null;
575
- let imageContentType = null;
576
- if (message.attachments && message.attachments.some(a => a.type === 'MmsAttachment' && a.contentType.startsWith('image/'))) {
577
- const imageAttachment = message.attachments.find(a => a.type === 'MmsAttachment' && a.contentType.startsWith('image/'));
578
- if (imageAttachment) {
579
- imageLink = getMediaReaderLinkByPlatformMediaLink(imageAttachment?.uri);
580
- imageDownloadLink = imageAttachment?.uri + `?access_token=${incomingData.logInfo.rcAccessToken}`;
581
- imageContentType = imageAttachment?.contentType;
582
- }
583
- }
584
- let videoLink = null;
585
- if (message.attachments && message.attachments.some(a => a.type === 'MmsAttachment')) {
586
- const imageAttachment = message.attachments.find(a => a.type === 'MmsAttachment' && a.contentType.startsWith('image/'));
587
- if (imageAttachment) {
588
- imageLink = getMediaReaderLinkByPlatformMediaLink(imageAttachment?.uri);
589
- }
590
- const videoAttachment = message.attachments.find(a => a.type === 'MmsAttachment' && a.contentType.startsWith('video/'));
591
- if (videoAttachment) {
592
- videoLink = getMediaReaderLinkByPlatformMediaLink(videoAttachment?.uri);
593
- }
594
- }
595
- const existingSameDateMessageLog = await MessageLogModel.findOne({
479
+ // Case: Shared SMS
480
+ if (isSharedSMS) {
481
+ const existingMessageLog = await MessageLogModel.findOne({
596
482
  where: {
597
483
  conversationLogId: incomingData.logInfo.conversationLogId
598
484
  }
599
485
  });
600
- let crmLogId = ''
601
- if (existingSameDateMessageLog) {
602
- const updateMessageResult = await platformModule.updateMessageLog({ user, contactInfo, existingMessageLog: existingSameDateMessageLog, message, authHeader, additionalSubmission, imageLink, videoLink, proxyConfig });
603
- crmLogId = existingSameDateMessageLog.thirdPartyLogId;
486
+ const entities = incomingData.logInfo.entities;
487
+ const sharedSMSLogContent = composeSharedSMSLog({ logFormat: platformModule.getLogFormatType(platform, proxyConfig), conversation: incomingData.logInfo, contactName: contactInfo.name, timezoneOffset: user.timezoneOffset });
488
+ if (existingMessageLog) {
489
+ const updateMessageResult = await platformModule.updateMessageLog({ user, contactInfo, sharedSMSLogContent, existingMessageLog: existingMessageLog, authHeader, additionalSubmission, proxyConfig });
604
490
  returnMessage = updateMessageResult?.returnMessage;
605
491
  }
606
492
  else {
607
- const createMessageLogResult = await platformModule.createMessageLog({ user, contactInfo, authHeader, message, additionalSubmission, recordingLink, faxDocLink, faxDownloadLink, imageLink, imageDownloadLink, imageContentType, videoLink, proxyConfig });
608
- crmLogId = createMessageLogResult.logId;
493
+ const createMessageLogResult = await platformModule.createMessageLog({ user, contactInfo, sharedSMSLogContent, authHeader, additionalSubmission, proxyConfig });
494
+ const crmLogId = createMessageLogResult.logId;
609
495
  returnMessage = createMessageLogResult?.returnMessage;
610
496
  extraDataTracking = createMessageLogResult.extraDataTracking;
497
+ if (createMessageLogResult.logId) {
498
+ const createdMessageLog =
499
+ await MessageLogModel.create({
500
+ id: incomingData.logInfo.conversationLogId,
501
+ platform,
502
+ conversationId: incomingData.logInfo.conversationId,
503
+ thirdPartyLogId: createMessageLogResult.logId,
504
+ userId,
505
+ conversationLogId: incomingData.logInfo.conversationLogId
506
+ });
507
+ logIds.push(createdMessageLog.id);
508
+ }
611
509
  }
612
- if (crmLogId) {
613
- const createdMessageLog =
614
- await MessageLogModel.create({
615
- id: message.id.toString(),
616
- platform,
617
- conversationId: incomingData.logInfo.conversationId,
618
- thirdPartyLogId: crmLogId,
619
- userId,
510
+ }
511
+ // Case: normal SMS
512
+ else {
513
+ // reverse the order of messages to log the oldest message first
514
+ const reversedMessages = incomingData.logInfo.messages.reverse();
515
+ for (const message of reversedMessages) {
516
+ if (existingIds.includes(message.id.toString())) {
517
+ continue;
518
+ }
519
+ let recordingLink = null;
520
+ if (message.attachments && message.attachments.some(a => a.type === 'AudioRecording')) {
521
+ recordingLink = message.attachments.find(a => a.type === 'AudioRecording').link;
522
+ }
523
+ let faxDocLink = null;
524
+ let faxDownloadLink = null;
525
+ if (message.attachments && message.attachments.some(a => a.type === 'RenderedDocument')) {
526
+ faxDocLink = message.attachments.find(a => a.type === 'RenderedDocument').link;
527
+ faxDownloadLink = message.attachments.find(a => a.type === 'RenderedDocument').uri + `?access_token=${incomingData.logInfo.rcAccessToken}`
528
+ }
529
+ let imageLink = null;
530
+ let imageDownloadLink = null;
531
+ let imageContentType = null;
532
+ if (message.attachments && message.attachments.some(a => a.type === 'MmsAttachment' && a.contentType.startsWith('image/'))) {
533
+ const imageAttachment = message.attachments.find(a => a.type === 'MmsAttachment' && a.contentType.startsWith('image/'));
534
+ if (imageAttachment) {
535
+ imageLink = getMediaReaderLinkByPlatformMediaLink(imageAttachment?.uri);
536
+ imageDownloadLink = imageAttachment?.uri + `?access_token=${incomingData.logInfo.rcAccessToken}`;
537
+ imageContentType = imageAttachment?.contentType;
538
+ }
539
+ }
540
+ let videoLink = null;
541
+ if (message.attachments && message.attachments.some(a => a.type === 'MmsAttachment')) {
542
+ const imageAttachment = message.attachments.find(a => a.type === 'MmsAttachment' && a.contentType.startsWith('image/'));
543
+ if (imageAttachment) {
544
+ imageLink = getMediaReaderLinkByPlatformMediaLink(imageAttachment?.uri);
545
+ }
546
+ const videoAttachment = message.attachments.find(a => a.type === 'MmsAttachment' && a.contentType.startsWith('video/'));
547
+ if (videoAttachment) {
548
+ videoLink = getMediaReaderLinkByPlatformMediaLink(videoAttachment?.uri);
549
+ }
550
+ }
551
+ const existingSameDateMessageLog = await MessageLogModel.findOne({
552
+ where: {
620
553
  conversationLogId: incomingData.logInfo.conversationLogId
621
- });
622
- logIds.push(createdMessageLog.id);
554
+ }
555
+ });
556
+ if (existingSameDateMessageLog) {
557
+ const updateMessageResult = await platformModule.updateMessageLog({ user, contactInfo, assigneeName, ownerName, existingMessageLog: existingSameDateMessageLog, message, authHeader, additionalSubmission, imageLink, videoLink, proxyConfig });
558
+ returnMessage = updateMessageResult?.returnMessage;
559
+ }
560
+ else {
561
+ const createMessageLogResult = await platformModule.createMessageLog({ user, contactInfo, assigneeName, ownerName, authHeader, message, additionalSubmission, recordingLink, faxDocLink, faxDownloadLink, imageLink, imageDownloadLink, imageContentType, videoLink, proxyConfig });
562
+ const crmLogId = createMessageLogResult.logId;
563
+ if (crmLogId) {
564
+ try {
565
+ const createdMessageLog =
566
+ await MessageLogModel.create({
567
+ id: message.id.toString(),
568
+ platform,
569
+ conversationId: incomingData.logInfo.conversationId,
570
+ thirdPartyLogId: crmLogId,
571
+ userId,
572
+ conversationLogId: incomingData.logInfo.conversationLogId
573
+ });
574
+ logIds.push(createdMessageLog.id);
575
+ } catch (error) {
576
+ return handleDatabaseError(error, 'Error creating message log');
577
+ }
578
+ }
579
+ returnMessage = createMessageLogResult?.returnMessage;
580
+ extraDataTracking = createMessageLogResult.extraDataTracking;
581
+ }
623
582
  }
624
583
  }
625
584
  return { successful: true, logIds, returnMessage, extraDataTracking };
626
585
  }
627
586
  catch (e) {
628
- console.error(`platform: ${platform} \n${e.stack}`);
629
- if (e.response?.status === 429) {
630
- return {
631
- successful: false,
632
- returnMessage: errorMessage.rateLimitErrorMessage({ platform }),
633
- extraDataTracking: {
634
- statusCode: e.response?.status,
635
- }
636
- };
637
- }
638
- else if (e.response?.status >= 400 && e.response?.status < 410) {
639
- return {
640
- successful: false,
641
- returnMessage: errorMessage.authorizationErrorMessage({ platform }),
642
- extraDataTracking: {
643
- statusCode: e.response?.status,
644
- }
645
- };
646
- }
647
- return {
648
- successful: false,
649
- returnMessage:
650
- {
651
- message: `Error creating message log`,
652
- messageType: 'warning',
653
- details: [
654
- {
655
- title: 'Details',
656
- items: [
657
- {
658
- id: '1',
659
- type: 'text',
660
- text: `Please check if your account has permission to CREATE logs.`
661
- }
662
- ]
663
- }
664
- ],
665
- ttl: 5000
666
- },
667
- extraDataTracking: {
668
- statusCode: e.response?.status,
669
- }
670
- };
587
+ return handleApiError(e, platform, 'createMessageLog', { userId });
671
588
  }
672
589
  }
673
590
 
674
- async function saveNoteCache({ sessionId, note }) {
591
+ async function saveNoteCache({ platform, userId, sessionId, note }) {
675
592
  try {
676
593
  const now = moment();
677
- const noteCache = await NoteCache.create({ sessionId, note, ttl: now.unix() + 3600 });
594
+ await NoteCache.create({ sessionId, note, ttl: now.unix() + 3600 });
678
595
  return { successful: true, returnMessage: 'Note cache saved' };
679
596
  } catch (e) {
680
- console.error(`Error saving note cache: ${e.stack}`);
681
- return { successful: false, returnMessage: 'Error saving note cache' };
597
+ return handleApiError(e, platform, 'saveNoteCache', { userId, sessionId, note });
682
598
  }
683
599
  }
684
600
 
package/handlers/user.js CHANGED
@@ -2,6 +2,8 @@ const axios = require('axios');
2
2
  const { AdminConfigModel } = require('../models/adminConfigModel');
3
3
  const { getHashValue } = require('../lib/util');
4
4
  const connectorRegistry = require('../connector/registry');
5
+ const logger = require('../lib/logger');
6
+ const { handleDatabaseError } = require('../lib/errorHandler');
5
7
 
6
8
  async function getUserSettingsByAdmin({ rcAccessToken, rcAccountId }) {
7
9
  let hashedRcAccountId = null;
@@ -31,6 +33,7 @@ async function getUserSettings({ user, rcAccessToken, rcAccountId }) {
31
33
  userSettingsByAdmin = await getUserSettingsByAdmin({ rcAccessToken, rcAccountId });
32
34
  }
33
35
  catch (e) {
36
+ logger.error('Error getting user settings by admin', { stack: e.stack });
34
37
  userSettingsByAdmin = [];
35
38
  }
36
39
  }
@@ -77,9 +80,14 @@ async function updateUserSettings({ user, userSettings, platformName }) {
77
80
  if (platformModule.onUpdateUserSettings) {
78
81
  const { successful, returnMessage } = await platformModule.onUpdateUserSettings({ user, userSettings, updatedSettings });
79
82
  if (successful) {
80
- await user.update({
81
- userSettings: updatedSettings
82
- });
83
+ try {
84
+ await user.update({
85
+ userSettings: updatedSettings
86
+ });
87
+ }
88
+ catch (error) {
89
+ return handleDatabaseError(error, 'Error updating user settings');
90
+ }
83
91
  }
84
92
  return {
85
93
  successful,
@@ -87,9 +95,14 @@ async function updateUserSettings({ user, userSettings, platformName }) {
87
95
  };
88
96
  }
89
97
  else {
90
- await user.update({
91
- userSettings: updatedSettings
92
- });
98
+ try {
99
+ await user.update({
100
+ userSettings: updatedSettings
101
+ });
102
+ }
103
+ catch (error) {
104
+ return handleDatabaseError(error, 'Error updating user settings');
105
+ }
93
106
  }
94
107
  return {
95
108
  userSettings: user.userSettings