Skip to content

Commit

Permalink
Merge pull request #69 from ringcentral/CallMetadataUpdate
Browse files Browse the repository at this point in the history
feat: support to save ai note, transcript
  • Loading branch information
DaKingKong authored Dec 31, 2024
2 parents e6bd586 + 30dbd36 commit e17ef67
Show file tree
Hide file tree
Showing 7 changed files with 284 additions and 46 deletions.
49 changes: 43 additions & 6 deletions src/adapters/bullhorn/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ async function createContact({ user, authHeader, phoneNumber, newContactName, ne
}
}

async function createCallLog({ user, contactInfo, authHeader, callLog, note, additionalSubmission }) {
async function createCallLog({ user, contactInfo, authHeader, callLog, note, additionalSubmission, aiNote, transcript }) {
const noteActions = additionalSubmission.noteActions ?? '';
const subject = callLog.customSubject ?? `${callLog.direction} Call ${callLog.direction === 'Outbound' ? `to ${contactInfo.name}` : `from ${contactInfo.name}`}`;
let comments = '<b>Agent notes</b>';;
Expand All @@ -294,6 +294,8 @@ async function createCallLog({ user, contactInfo, authHeader, callLog, note, add
if (user.userSettings?.addCallLogResult?.value ?? true) { comments = upsertCallResult({ body: comments, result: callLog.result }); }
if (!!callLog.recording?.link && (user.userSettings?.addCallLogRecording?.value ?? true)) { comments = upsertCallRecording({ body: comments, recordingLink: callLog.recording.link }); }
comments += '</ul>';
if (!!aiNote && (user.userSettings?.addCallLogAiNote?.value ?? true)) { comments = upsertAiNote({ body: comments, aiNote }); }
if (!!transcript && (user.userSettings?.addCallLogTranscript?.value ?? true)) { comments = upsertTranscript({ body: comments, transcript }); }
const putBody = {
comments,
action: noteActions,
Expand Down Expand Up @@ -347,7 +349,7 @@ async function createCallLog({ user, contactInfo, authHeader, callLog, note, add
};
}

async function updateCallLog({ user, existingCallLog, authHeader, recordingLink, subject, note, startTime, duration, result }) {
async function updateCallLog({ user, existingCallLog, authHeader, recordingLink, subject, note, startTime, duration, result, aiNote, transcript }) {
const existingBullhornLogId = existingCallLog.thirdPartyLogId;
let getLogRes
let extraDataTracking;
Expand Down Expand Up @@ -380,6 +382,8 @@ async function updateCallLog({ user, existingCallLog, authHeader, recordingLink,
if (!!duration && (user.userSettings?.addCallLogDuration?.value ?? true)) { comments = upsertCallDuration({ body: comments, duration }); }
if (!!result && (user.userSettings?.addCallLogResult?.value ?? true)) { comments = upsertCallResult({ body: comments, result }); }
if (!!recordingLink && (user.userSettings?.addCallLogRecording?.value ?? true)) { comments = upsertCallRecording({ body: comments, recordingLink }); }
if (!!aiNote && (user.userSettings?.addCallLogAiNote?.value ?? true)) { comments = upsertAiNote({ body: comments, aiNote }); }
if (!!transcript && (user.userSettings?.addCallLogTranscript?.value ?? true)) { comments = upsertTranscript({ body: comments, transcript }); }

// I dunno, Bullhorn just uses POST as PATCH
const postBody = {
Expand Down Expand Up @@ -707,19 +711,52 @@ function upsertCallRecording({ body, recordingLink }) {
body = body.replace(recordingLinkRegex, (match, p1) => `<li><b>Call recording link</b>: <a target="_blank" href=${recordingLink}>open</a>${p1.endsWith('</ul>') ? '</ul>' : '<li>'}`);
}
else {
let text = '';
// a real link
if (recordingLink.startsWith('http')) {
body += `<li><b>Call recording link</b>: <a target="_blank" href=${recordingLink}>open</a><li>`;
text = `<li><b>Call recording link</b>: <a target="_blank" href=${recordingLink}>open</a><li>`;
} else {
// placeholder
text = '<li><b>Call recording link</b>: (pending...)<li>';
}
// placeholder
else {
body += '<li><b>Call recording link</b>: (pending...)<li>';
if (body.indexOf('</ul>') === -1) {
body += text;
} else {
body = body.replace('</ul>', `${text}</ul>`);
}
}
}
return body;
}

function upsertAiNote({ body, aiNote }) {
if (!!!aiNote) {
return body;
}
const formattedAiNote = aiNote.replace(/\n+$/, '').replace(/(?:\r\n|\r|\n)/g, '<br>');
const aiNoteRegex = RegExp('<div><b>AI Note</b><br>(.+?)</div>');
if (aiNoteRegex.test(body)) {
body = body.replace(aiNoteRegex, `<div><b>AI Note</b><br>${formattedAiNote}</div>`);
} else {
body += `<div><b>AI Note</b><br>${formattedAiNote}</div><br>`;
}
return body;
}

function upsertTranscript({ body, transcript }) {
if (!!!transcript) {
return body;
}
const formattedTranscript = transcript.replace(/(?:\r\n|\r|\n)/g, '<br>');
const transcriptRegex = RegExp('<div><b>Transcript</b><br>(.+?)</div>');
if (transcriptRegex.test(body)) {
body = body.replace(transcriptRegex, `<div><b>Transcript</b><br>${formattedTranscript}</div>`);
} else {
body += `<div><b>Transcript</b><br>${formattedTranscript}</div><br>`;
}
return body;
}

exports.getAuthType = getAuthType;
exports.getOauthInfo = getOauthInfo;
exports.getOverridingOAuthOption = getOverridingOAuthOption;
Expand Down
63 changes: 45 additions & 18 deletions src/adapters/clio/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ async function createContact({ user, authHeader, phoneNumber, newContactName })
}
}

async function createCallLog({ user, contactInfo, authHeader, callLog, note, additionalSubmission }) {
async function createCallLog({ user, contactInfo, authHeader, callLog, note, additionalSubmission, aiNote, transcript }) {
const sender = callLog.direction === 'Outbound' ?
{
id: user.id,
Expand All @@ -197,6 +197,9 @@ async function createCallLog({ user, contactInfo, authHeader, callLog, note, add
if (user.userSettings?.addCallLogNote?.value ?? true) { body = upsertCallAgentNote({ body, note }); }
if (user.userSettings?.addCallLogDuration?.value ?? true) { body = upsertCallDuration({ body, duration: callLog.duration }); }
if (!!callLog.recording?.link && (user.userSettings?.addCallLogRecording?.value ?? true)) { body = upsertCallRecording({ body, recordingLink: callLog.recording.link }); }
if (!!aiNote && (user.userSettings?.addCallLogAiNote?.value ?? true)) { body = upsertAiNote({ body, aiNote }); }
if (!!transcript && (user.userSettings?.addCallLogTranscript?.value ?? true)) { body = upsertTranscript({ body, transcript }); }

const postBody = {
data: {
subject: callLog.customSubject ?? `[Call] ${callLog.direction} Call ${callLog.direction === 'Outbound' ? 'to' : 'from'} ${contactInfo.name} [${contactInfo.phone}]`,
Expand Down Expand Up @@ -250,7 +253,7 @@ async function createCallLog({ user, contactInfo, authHeader, callLog, note, add
};
}

async function updateCallLog({ user, existingCallLog, authHeader, recordingLink, subject, note, startTime, duration, result }) {
async function updateCallLog({ user, existingCallLog, authHeader, recordingLink, subject, note, startTime, duration, result, aiNote, transcript }) {
const existingClioLogId = existingCallLog.thirdPartyLogId.split('.')[0];
const getLogRes = await axios.get(
`https://${user.hostname}/api/v4/communications/${existingClioLogId}.json?fields=body,id`,
Expand All @@ -264,6 +267,8 @@ async function updateCallLog({ user, existingCallLog, authHeader, recordingLink,
if (!!duration && (user.userSettings?.addCallLogDuration?.value ?? true)) { logBody = upsertCallDuration({ body: logBody, duration }); }
if (!!result && (user.userSettings?.addCallLogResult?.value ?? true)) { logBody = upsertCallResult({ body: logBody, result }); }
if (!!recordingLink && (user.userSettings?.addCallLogRecording?.value ?? true)) { logBody = upsertCallRecording({ body: logBody, recordingLink: decodeURIComponent(recordingLink) }); }
if (!!aiNote && (user.userSettings?.addCallLogAiNote?.value ?? true)) { logBody = upsertAiNote({ body: logBody, aiNote }); }
if (!!transcript && (user.userSettings?.addCallLogTranscript?.value ?? true)) { logBody = upsertTranscript({ body: logBody, transcript }); }
patchBody = {
data: {
body: logBody
Expand All @@ -272,24 +277,26 @@ async function updateCallLog({ user, existingCallLog, authHeader, recordingLink,
if (!!subject) { patchBody.data.subject = subject; }
if (!!startTime) { patchBody.data.received_at = moment(startTime).toISOString(); }
// duration - update Timer
const getTimerRes = await axios.get(
`https://${user.hostname}/api/v4/activities?communication_id=${getLogRes.data.data.id}&fields=quantity,id`,
{
headers: { 'Authorization': authHeader }
}
)
if (!!getTimerRes.data.data[0]) {
const patchTimerBody = {
data: {
quantity: duration
}
}
const patchTimerRes = await axios.patch(
`https://${user.hostname}/api/v4/activities/${getTimerRes.data.data[0].id}.json`,
patchTimerBody,
if (!!duration) {
const getTimerRes = await axios.get(
`https://${user.hostname}/api/v4/activities?communication_id=${getLogRes.data.data.id}&fields=quantity,id`,
{
headers: { 'Authorization': authHeader }
});
}
)
if (!!getTimerRes.data.data[0]) {
const patchTimerBody = {
data: {
quantity: duration
}
}
const patchTimerRes = await axios.patch(
`https://${user.hostname}/api/v4/activities/${getTimerRes.data.data[0].id}.json`,
patchTimerBody,
{
headers: { 'Authorization': authHeader }
});
}
}
const patchLogRes = await axios.patch(
`https://${user.hostname}/api/v4/communications/${existingClioLogId}.json`,
Expand Down Expand Up @@ -505,6 +512,26 @@ function upsertCallRecording({ body, recordingLink }) {
return body;
}

function upsertAiNote({ body, aiNote }) {
const aiNoteRegex = RegExp('- AI Note:([\\s\\S]*?)--- END');
const clearedAiNote = aiNote.replace(/\n+$/, '');
if (aiNoteRegex.test(body)) {
body = body.replace(aiNoteRegex, `- AI Note:\n${clearedAiNote}\n--- END`);
} else {
body += `- AI Note:\n${clearedAiNote}\n--- END\n`;
}
return body;
}

function upsertTranscript({ body, transcript }) {
const transcriptRegex = RegExp('- Transcript:([\\s\\S]*?)--- END');
if (transcriptRegex.test(body)) {
body = body.replace(transcriptRegex, `- Transcript:\n${transcript}\n--- END`);
} else {
body += `- Transcript:\n${transcript}\n--- END\n`;
}
return body;
}

exports.getAuthType = getAuthType;
exports.getOauthInfo = getOauthInfo;
Expand Down
33 changes: 29 additions & 4 deletions src/adapters/insightly/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -259,13 +259,16 @@ async function createContact({ user, authHeader, phoneNumber, newContactName, ne
}
}

async function createCallLog({ user, contactInfo, authHeader, callLog, note, additionalSubmission }) {
async function createCallLog({ user, contactInfo, authHeader, callLog, note, additionalSubmission, aiNote, transcript }) {
let body = '';
if (user.userSettings?.addCallLogNote?.value ?? true) { body = upsertCallAgentNote({ body, note }); }
if (user.userSettings?.addCallLogContactNumber?.value ?? true) { body = upsertContactPhoneNumber({ body, phoneNumber: contactInfo.phoneNumber, direction: callLog.direction }); }
if (user.userSettings?.addCallLogResult?.value ?? true) { body = upsertCallResult({ body, result: callLog.result }); }
if (user.userSettings?.addCallLogDuration?.value ?? true) { body = upsertCallDuration({ body, duration: callLog.duration }); }
if (!!callLog.recording?.link && (user.userSettings?.addCallLogRecording?.value ?? true)) { body = upsertCallRecording({ body, recordingLink: callLog.recording.link }); }
if (!!aiNote && (user.userSettings?.addCallLogAiNote?.value ?? true)) { body = upsertAiNote({ body, aiNote }); }
if (!!transcript && (user.userSettings?.addCallLogTranscript?.value ?? true)) { body = upsertTranscript({ body, transcript }); }

const postBody = {
TITLE: callLog.customSubject ?? `${callLog.direction} Call ${callLog.direction === 'Outbound' ? 'to' : 'from'} ${contactInfo.name}`,
DETAILS: body,
Expand Down Expand Up @@ -349,7 +352,7 @@ async function createCallLog({ user, contactInfo, authHeader, callLog, note, add
};
}

async function updateCallLog({ user, existingCallLog, authHeader, recordingLink, subject, note, startTime, duration, result }) {
async function updateCallLog({ user, existingCallLog, authHeader, recordingLink, subject, note, startTime, duration, result, aiNote, transcript }) {
const existingInsightlyLogId = existingCallLog.thirdPartyLogId;
const getLogRes = await axios.get(
`${user.platformAdditionalInfo.apiUrl}/${process.env.INSIGHTLY_API_VERSION}/events/${existingInsightlyLogId}`,
Expand All @@ -362,12 +365,13 @@ async function updateCallLog({ user, existingCallLog, authHeader, recordingLink,
if (!!duration && (user.userSettings?.addCallLogDuration?.value ?? true)) { logBody = upsertCallDuration({ body: logBody, duration }); }
if (!!result && (user.userSettings?.addCallLogResult?.value ?? true)) { logBody = upsertCallResult({ body: logBody, result }); }
if (!!recordingLink && (user.userSettings?.addCallLogRecording?.value ?? true)) { logBody = upsertCallRecording({ body: logBody, recordingLink: decodeURIComponent(recordingLink) }); }
if (!!aiNote && (user.userSettings?.addCallLogAiNote?.value ?? true)) { logBody = upsertAiNote({ body: logBody, aiNote }); }
if (!!transcript && (user.userSettings?.addCallLogTranscript?.value ?? true)) { logBody = upsertTranscript({ body: logBody, transcript }); }

let logSubject = !!subject ?? getLogRes.data.TITLE;
const putBody = {
EVENT_ID: existingInsightlyLogId,
DETAILS: logBody,
TITLE: logSubject,
TITLE: subject ? subject : getLogRes.data.TITLE,
START_DATE_UTC: moment(startTime).utc(),
END_DATE_UTC: moment(startTime).utc().add(duration, 'seconds')
}
Expand Down Expand Up @@ -586,6 +590,27 @@ function upsertCallRecording({ body, recordingLink }) {
return body;
}

function upsertAiNote({ body, aiNote }) {
const aiNoteRegex = RegExp('- AI Note:([\\s\\S]*?)--- END');
const clearedAiNote = aiNote.replace(/\n+$/, '');
if (aiNoteRegex.test(body)) {
body = body.replace(aiNoteRegex, `- AI Note:\n${clearedAiNote}\n--- END`);
} else {
body += `- AI Note:\n${clearedAiNote}\n--- END\n`;
}
return body;
}

function upsertTranscript({ body, transcript }) {
const transcriptRegex = RegExp('- Transcript:([\\s\\S]*?)--- END');
if (transcriptRegex.test(body)) {
body = body.replace(transcriptRegex, `- Transcript:\n${transcript}\n--- END`);
} else {
body += `- Transcript:\n${transcript}\n--- END\n`;
}
return body;
}

exports.getAuthType = getAuthType;
exports.getBasicAuth = getBasicAuth;
exports.getUserInfo = getUserInfo;
Expand Down
70 changes: 70 additions & 0 deletions src/adapters/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,20 @@
"type": "boolean",
"name": "Add recording link to call log",
"defaultValue": true
},
{
"id": "addCallLogAiNote",
"type": "boolean",
"name": "Add AI note to call log (if available) - Beta",
"defaultValue": false,
"requiredPermission": "aiNote"
},
{
"id": "addCallLogTranscript",
"type": "boolean",
"name": "Add transcript to call log (if available) - Beta",
"defaultValue": false,
"requiredPermission": "aiNote"
}
]
}
Expand Down Expand Up @@ -268,6 +282,20 @@
"type": "boolean",
"name": "Add recording link to call log",
"defaultValue": true
},
{
"id": "addCallLogAiNote",
"type": "boolean",
"name": "Add AI note to call log (if available) - Beta",
"defaultValue": false,
"requiredPermission": "aiNote"
},
{
"id": "addCallLogTranscript",
"type": "boolean",
"name": "Add transcript to call log (if available) - Beta",
"defaultValue": false,
"requiredPermission": "aiNote"
}
]
}
Expand Down Expand Up @@ -451,6 +479,20 @@
"type": "boolean",
"name": "Add recording link to call log",
"defaultValue": true
},
{
"id": "addCallLogAiNote",
"type": "boolean",
"name": "Add AI note to call log (if available) - Beta",
"defaultValue": false,
"requiredPermission": "aiNote"
},
{
"id": "addCallLogTranscript",
"type": "boolean",
"name": "Add transcript to call log (if available) - Beta",
"defaultValue": false,
"requiredPermission": "aiNote"
}
]
}
Expand Down Expand Up @@ -653,6 +695,20 @@
"type": "boolean",
"name": "Add recording link to call log",
"defaultValue": true
},
{
"id": "addCallLogAiNote",
"type": "boolean",
"name": "Add AI note to call log (if available) - Beta",
"defaultValue": false,
"requiredPermission": "aiNote"
},
{
"id": "addCallLogTranscript",
"type": "boolean",
"name": "Add transcript to call log (if available) - Beta",
"defaultValue": false,
"requiredPermission": "aiNote"
}
]
}
Expand Down Expand Up @@ -867,6 +923,20 @@
"type": "boolean",
"name": "Add recording link to call log",
"defaultValue": true
},
{
"id": "addCallLogAiNote",
"type": "boolean",
"name": "Add AI note to call log (if available) - Beta",
"defaultValue": false,
"requiredPermission": "aiNote"
},
{
"id": "addCallLogTranscript",
"type": "boolean",
"name": "Add transcript to call log (if available) - Beta",
"defaultValue": false,
"requiredPermission": "aiNote"
}
]
}
Expand Down
Loading

0 comments on commit e17ef67

Please sign in to comment.