@app-connect/core 1.7.10 → 1.7.11
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 +44 -21
- package/handlers/auth.js +89 -67
- package/handlers/calldown.js +10 -4
- package/handlers/contact.js +4 -104
- package/handlers/disposition.js +4 -142
- package/handlers/log.js +172 -257
- package/handlers/user.js +19 -6
- package/index.js +213 -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 +90 -0
- package/mcp/tools/collectAuthInfo.js +86 -0
- package/mcp/tools/createCallLog.js +299 -0
- package/mcp/tools/createMessageLog.js +283 -0
- package/mcp/tools/doAuth.js +185 -0
- package/mcp/tools/findContactByName.js +87 -0
- package/mcp/tools/findContactByPhone.js +96 -0
- package/mcp/tools/getCallLog.js +98 -0
- package/mcp/tools/getHelp.js +39 -0
- package/mcp/tools/getPublicConnectors.js +46 -0
- package/mcp/tools/index.js +58 -0
- package/mcp/tools/logout.js +63 -0
- package/mcp/tools/rcGetCallLogs.js +73 -0
- package/mcp/tools/setConnector.js +64 -0
- package/mcp/tools/updateCallLog.js +122 -0
- package/models/cacheModel.js +3 -0
- package/package.json +71 -70
- package/releaseNotes.json +12 -0
- package/test/handlers/log.test.js +6 -2
- package/test/lib/logger.test.js +206 -0
- package/test/lib/sharedSMSComposer.test.js +1084 -0
- package/test/mcp/tools/collectAuthInfo.test.js +192 -0
- package/test/mcp/tools/createCallLog.test.js +412 -0
- package/test/mcp/tools/createMessageLog.test.js +580 -0
- package/test/mcp/tools/doAuth.test.js +363 -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/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/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
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
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
|
-
|
|
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
|
}
|
|
@@ -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
|
-
|
|
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
|
-
|
|
323
|
-
|
|
324
|
-
|
|
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);
|
|
@@ -371,9 +317,9 @@ async function updateCallLog({ platform, userId, incomingData, hashedAccountId,
|
|
|
371
317
|
existingBody = getLogResult.callLogInfo.note;
|
|
372
318
|
}
|
|
373
319
|
} catch (error) {
|
|
374
|
-
|
|
320
|
+
logger.error('Error getting existing log details, proceeding with empty body', { stack: error.stack });
|
|
375
321
|
}
|
|
376
|
-
composedLogDetails =
|
|
322
|
+
composedLogDetails = composeCallLog({
|
|
377
323
|
logFormat,
|
|
378
324
|
existingBody,
|
|
379
325
|
callLog: {
|
|
@@ -434,49 +380,7 @@ async function updateCallLog({ platform, userId, incomingData, hashedAccountId,
|
|
|
434
380
|
}
|
|
435
381
|
return { successful: false };
|
|
436
382
|
} catch (e) {
|
|
437
|
-
|
|
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
|
-
};
|
|
383
|
+
return handleApiError(e, platform, 'updateCallLog', { userId });
|
|
480
384
|
}
|
|
481
385
|
}
|
|
482
386
|
|
|
@@ -498,7 +402,13 @@ async function createMessageLog({ platform, userId, incomingData }) {
|
|
|
498
402
|
const platformModule = connectorRegistry.getConnector(platform);
|
|
499
403
|
const contactNumber = incomingData.logInfo.correspondents[0].phoneNumber;
|
|
500
404
|
const additionalSubmission = incomingData.additionalSubmission;
|
|
501
|
-
let user =
|
|
405
|
+
let user = null;
|
|
406
|
+
try {
|
|
407
|
+
user = await UserModel.findByPk(userId);
|
|
408
|
+
}
|
|
409
|
+
catch (error) {
|
|
410
|
+
return handleDatabaseError(error, 'Error finding user');
|
|
411
|
+
}
|
|
502
412
|
if (!user || !user.accessToken) {
|
|
503
413
|
return {
|
|
504
414
|
successful: false,
|
|
@@ -546,139 +456,144 @@ async function createMessageLog({ platform, userId, incomingData }) {
|
|
|
546
456
|
type: incomingData.contactType ?? "",
|
|
547
457
|
name: incomingData.contactName ?? ""
|
|
548
458
|
};
|
|
459
|
+
// For shared SMS
|
|
460
|
+
const assigneeName = incomingData.logInfo.assignee?.name;
|
|
461
|
+
const ownerName = incomingData.logInfo.owner?.name;
|
|
462
|
+
const isSharedSMS = !!ownerName;
|
|
463
|
+
|
|
549
464
|
const messageIds = incomingData.logInfo.messages.map(m => { return { id: m.id.toString() }; });
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
465
|
+
let existingMessages = null;
|
|
466
|
+
try {
|
|
467
|
+
existingMessages = await MessageLogModel.findAll({
|
|
468
|
+
where: {
|
|
469
|
+
[Op.or]: messageIds
|
|
470
|
+
}
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
catch (error) {
|
|
474
|
+
return handleDatabaseError(error, 'Error finding existing messages');
|
|
475
|
+
}
|
|
555
476
|
const existingIds = existingMessages.map(m => m.id);
|
|
556
477
|
const logIds = [];
|
|
557
|
-
//
|
|
558
|
-
|
|
559
|
-
|
|
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({
|
|
478
|
+
// Case: Shared SMS
|
|
479
|
+
if (isSharedSMS) {
|
|
480
|
+
const existingMessageLog = await MessageLogModel.findOne({
|
|
596
481
|
where: {
|
|
597
482
|
conversationLogId: incomingData.logInfo.conversationLogId
|
|
598
483
|
}
|
|
599
484
|
});
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
485
|
+
const entities = incomingData.logInfo.entities;
|
|
486
|
+
const sharedSMSLogContent = composeSharedSMSLog({ logFormat: platformModule.getLogFormatType(platform, proxyConfig), conversation: incomingData.logInfo, contactName: contactInfo.name, timezoneOffset: user.timezoneOffset });
|
|
487
|
+
if (existingMessageLog) {
|
|
488
|
+
const updateMessageResult = await platformModule.updateMessageLog({ user, contactInfo, sharedSMSLogContent, existingMessageLog: existingMessageLog, authHeader, additionalSubmission, proxyConfig });
|
|
604
489
|
returnMessage = updateMessageResult?.returnMessage;
|
|
605
490
|
}
|
|
606
491
|
else {
|
|
607
|
-
const createMessageLogResult = await platformModule.createMessageLog({ user, contactInfo,
|
|
608
|
-
crmLogId = createMessageLogResult.logId;
|
|
492
|
+
const createMessageLogResult = await platformModule.createMessageLog({ user, contactInfo, sharedSMSLogContent, authHeader, additionalSubmission, proxyConfig });
|
|
493
|
+
const crmLogId = createMessageLogResult.logId;
|
|
609
494
|
returnMessage = createMessageLogResult?.returnMessage;
|
|
610
495
|
extraDataTracking = createMessageLogResult.extraDataTracking;
|
|
496
|
+
if (createMessageLogResult.logId) {
|
|
497
|
+
const createdMessageLog =
|
|
498
|
+
await MessageLogModel.create({
|
|
499
|
+
id: incomingData.logInfo.conversationLogId,
|
|
500
|
+
platform,
|
|
501
|
+
conversationId: incomingData.logInfo.conversationId,
|
|
502
|
+
thirdPartyLogId: createMessageLogResult.logId,
|
|
503
|
+
userId,
|
|
504
|
+
conversationLogId: incomingData.logInfo.conversationLogId
|
|
505
|
+
});
|
|
506
|
+
logIds.push(createdMessageLog.id);
|
|
507
|
+
}
|
|
611
508
|
}
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
509
|
+
}
|
|
510
|
+
// Case: normal SMS
|
|
511
|
+
else {
|
|
512
|
+
// reverse the order of messages to log the oldest message first
|
|
513
|
+
const reversedMessages = incomingData.logInfo.messages.reverse();
|
|
514
|
+
for (const message of reversedMessages) {
|
|
515
|
+
if (existingIds.includes(message.id.toString())) {
|
|
516
|
+
continue;
|
|
517
|
+
}
|
|
518
|
+
let recordingLink = null;
|
|
519
|
+
if (message.attachments && message.attachments.some(a => a.type === 'AudioRecording')) {
|
|
520
|
+
recordingLink = message.attachments.find(a => a.type === 'AudioRecording').link;
|
|
521
|
+
}
|
|
522
|
+
let faxDocLink = null;
|
|
523
|
+
let faxDownloadLink = null;
|
|
524
|
+
if (message.attachments && message.attachments.some(a => a.type === 'RenderedDocument')) {
|
|
525
|
+
faxDocLink = message.attachments.find(a => a.type === 'RenderedDocument').link;
|
|
526
|
+
faxDownloadLink = message.attachments.find(a => a.type === 'RenderedDocument').uri + `?access_token=${incomingData.logInfo.rcAccessToken}`
|
|
527
|
+
}
|
|
528
|
+
let imageLink = null;
|
|
529
|
+
let imageDownloadLink = null;
|
|
530
|
+
let imageContentType = null;
|
|
531
|
+
if (message.attachments && message.attachments.some(a => a.type === 'MmsAttachment' && a.contentType.startsWith('image/'))) {
|
|
532
|
+
const imageAttachment = message.attachments.find(a => a.type === 'MmsAttachment' && a.contentType.startsWith('image/'));
|
|
533
|
+
if (imageAttachment) {
|
|
534
|
+
imageLink = getMediaReaderLinkByPlatformMediaLink(imageAttachment?.uri);
|
|
535
|
+
imageDownloadLink = imageAttachment?.uri + `?access_token=${incomingData.logInfo.rcAccessToken}`;
|
|
536
|
+
imageContentType = imageAttachment?.contentType;
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
let videoLink = null;
|
|
540
|
+
if (message.attachments && message.attachments.some(a => a.type === 'MmsAttachment')) {
|
|
541
|
+
const imageAttachment = message.attachments.find(a => a.type === 'MmsAttachment' && a.contentType.startsWith('image/'));
|
|
542
|
+
if (imageAttachment) {
|
|
543
|
+
imageLink = getMediaReaderLinkByPlatformMediaLink(imageAttachment?.uri);
|
|
544
|
+
}
|
|
545
|
+
const videoAttachment = message.attachments.find(a => a.type === 'MmsAttachment' && a.contentType.startsWith('video/'));
|
|
546
|
+
if (videoAttachment) {
|
|
547
|
+
videoLink = getMediaReaderLinkByPlatformMediaLink(videoAttachment?.uri);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
const existingSameDateMessageLog = await MessageLogModel.findOne({
|
|
551
|
+
where: {
|
|
620
552
|
conversationLogId: incomingData.logInfo.conversationLogId
|
|
621
|
-
}
|
|
622
|
-
|
|
553
|
+
}
|
|
554
|
+
});
|
|
555
|
+
if (existingSameDateMessageLog) {
|
|
556
|
+
const updateMessageResult = await platformModule.updateMessageLog({ user, contactInfo, assigneeName, ownerName, existingMessageLog: existingSameDateMessageLog, message, authHeader, additionalSubmission, imageLink, videoLink, proxyConfig });
|
|
557
|
+
returnMessage = updateMessageResult?.returnMessage;
|
|
558
|
+
}
|
|
559
|
+
else {
|
|
560
|
+
const createMessageLogResult = await platformModule.createMessageLog({ user, contactInfo, assigneeName, ownerName, authHeader, message, additionalSubmission, recordingLink, faxDocLink, faxDownloadLink, imageLink, imageDownloadLink, imageContentType, videoLink, proxyConfig });
|
|
561
|
+
const crmLogId = createMessageLogResult.logId;
|
|
562
|
+
if (crmLogId) {
|
|
563
|
+
try {
|
|
564
|
+
const createdMessageLog =
|
|
565
|
+
await MessageLogModel.create({
|
|
566
|
+
id: message.id.toString(),
|
|
567
|
+
platform,
|
|
568
|
+
conversationId: incomingData.logInfo.conversationId,
|
|
569
|
+
thirdPartyLogId: crmLogId,
|
|
570
|
+
userId,
|
|
571
|
+
conversationLogId: incomingData.logInfo.conversationLogId
|
|
572
|
+
});
|
|
573
|
+
logIds.push(createdMessageLog.id);
|
|
574
|
+
} catch (error) {
|
|
575
|
+
return handleDatabaseError(error, 'Error creating message log');
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
returnMessage = createMessageLogResult?.returnMessage;
|
|
579
|
+
extraDataTracking = createMessageLogResult.extraDataTracking;
|
|
580
|
+
}
|
|
623
581
|
}
|
|
624
582
|
}
|
|
625
583
|
return { successful: true, logIds, returnMessage, extraDataTracking };
|
|
626
584
|
}
|
|
627
585
|
catch (e) {
|
|
628
|
-
|
|
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
|
-
};
|
|
586
|
+
return handleApiError(e, platform, 'createMessageLog', { userId });
|
|
671
587
|
}
|
|
672
588
|
}
|
|
673
589
|
|
|
674
|
-
async function saveNoteCache({ sessionId, note }) {
|
|
590
|
+
async function saveNoteCache({ platform, userId, sessionId, note }) {
|
|
675
591
|
try {
|
|
676
592
|
const now = moment();
|
|
677
|
-
|
|
593
|
+
await NoteCache.create({ sessionId, note, ttl: now.unix() + 3600 });
|
|
678
594
|
return { successful: true, returnMessage: 'Note cache saved' };
|
|
679
595
|
} catch (e) {
|
|
680
|
-
|
|
681
|
-
return { successful: false, returnMessage: 'Error saving note cache' };
|
|
596
|
+
return handleApiError(e, platform, 'saveNoteCache', { userId, sessionId, note });
|
|
682
597
|
}
|
|
683
598
|
}
|
|
684
599
|
|
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
|
-
|
|
81
|
-
|
|
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
|
-
|
|
91
|
-
|
|
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
|