scv-connector-base
Version:
Salesforce Service Cloud Connector Base
1,475 lines (1,385 loc) • 60.8 kB
JavaScript
/*
* Copyright (c) 2021, salesforce.com, inc.
* All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
/* eslint-disable no-unused-vars */
import constants from './constants.js';
import { downloadLogs } from './logger.js';
export const Constants = {
/**
* @enum {string}
*/
SHARED_EVENT_TYPE: {
LOGIN_RESULT: constants.SHARED_EVENT_TYPE.LOGIN_RESULT,
LOGOUT_RESULT: constants.SHARED_EVENT_TYPE.LOGOUT_RESULT,
MESSAGE: constants.SHARED_EVENT_TYPE.MESSAGE,
SET_AGENT_STATUS: constants.SHARED_EVENT_TYPE.SET_AGENT_STATUS,
GET_AGENT_STATUS: constants.SHARED_EVENT_TYPE.GET_AGENT_STATUS,
STATE_CHANGE: constants.SHARED_EVENT_TYPE.STATE_CHANGE,
STORAGE_ACCESS_RESULT: constants.SHARED_EVENT_TYPE.STORAGE_ACCESS_RESULT,
GET_CONTACTS_RESULT: constants.SHARED_EVENT_TYPE.GET_CONTACTS_RESULT,
AFTER_CONVERSATION_WORK_STARTED: constants.SHARED_EVENT_TYPE.AFTER_CONVERSATION_WORK_STARTED,
AFTER_CONVERSATION_WORK_ENDED: constants.SHARED_EVENT_TYPE.AFTER_CONVERSATION_WORK_ENDED
},
/**
* @enum {string}
*/
VOICE_EVENT_TYPE: {
CALL_STARTED: constants.VOICE_EVENT_TYPE.CALL_STARTED,
QUEUED_CALL_STARTED: constants.VOICE_EVENT_TYPE.QUEUED_CALL_STARTED,
CALL_CONNECTED: constants.VOICE_EVENT_TYPE.CALL_CONNECTED,
HANGUP: constants.VOICE_EVENT_TYPE.HANGUP,
MUTE_TOGGLE: constants.VOICE_EVENT_TYPE.MUTE_TOGGLE,
HOLD_TOGGLE: constants.VOICE_EVENT_TYPE.HOLD_TOGGLE,
RECORDING_TOGGLE: constants.VOICE_EVENT_TYPE.RECORDING_TOGGLE,
PARTICIPANTS_SWAPPED: constants.VOICE_EVENT_TYPE.PARTICIPANTS_SWAPPED,
PARTICIPANTS_CONFERENCED: constants.VOICE_EVENT_TYPE.PARTICIPANTS_CONFERENCED,
PARTICIPANT_ADDED: constants.VOICE_EVENT_TYPE.PARTICIPANT_ADDED,
PARTICIPANT_CONNECTED: constants.VOICE_EVENT_TYPE.PARTICIPANT_CONNECTED,
PARTICIPANT_REMOVED: constants.VOICE_EVENT_TYPE.PARTICIPANT_REMOVED,
AFTER_CALL_WORK_STARTED: constants.VOICE_EVENT_TYPE.AFTER_CALL_WORK_STARTED,
WRAP_UP_ENDED: constants.VOICE_EVENT_TYPE.WRAP_UP_ENDED,
AGENT_ERROR: constants.VOICE_EVENT_TYPE.AGENT_ERROR,
SOFTPHONE_ERROR: constants.VOICE_EVENT_TYPE.SOFTPHONE_ERROR,
UPDATE_AUDIO_STATS: constants.VOICE_EVENT_TYPE.UPDATE_AUDIO_STATS,
CALL_BARGED_IN: constants.VOICE_EVENT_TYPE.CALL_BARGED_IN,
SUPERVISOR_BARGED_IN: constants.VOICE_EVENT_TYPE.SUPERVISOR_BARGED_IN,
SUPERVISOR_CALL_STARTED : constants.VOICE_EVENT_TYPE.SUPERVISOR_CALL_STARTED,
SUPERVISOR_CALL_CONNECTED: constants.VOICE_EVENT_TYPE.SUPERVISOR_CALL_CONNECTED,
SUPERVISOR_HANGUP : constants.VOICE_EVENT_TYPE.SUPERVISOR_HANGUP,
SHOW_TRANSFER_VIEW: constants.VOICE_EVENT_TYPE.SHOW_TRANSFER_VIEW,
AUDIO_STATS: constants.VOICE_EVENT_TYPE.AUDIO_STATS,
CALL_UPDATED: constants.VOICE_EVENT_TYPE.CALL_UPDATED
},
/**
* @enum {string}
*/
SHARED_ERROR_TYPE: {
GENERIC_ERROR: constants.SHARED_ERROR_TYPE.GENERIC_ERROR,
INVALID_AGENT_STATUS: constants.SHARED_ERROR_TYPE.INVALID_AGENT_STATUS
},
/**
* @enum {string}
*/
VOICE_ERROR_TYPE: {
INVALID_PARTICIPANT: constants.VOICE_ERROR_TYPE.INVALID_PARTICIPANT,
INVALID_DESTINATION: constants.VOICE_ERROR_TYPE.INVALID_DESTINATION,
CAN_NOT_UPDATE_PHONE_NUMBER: constants.VOICE_ERROR_TYPE.CAN_NOT_UPDATE_PHONE_NUMBER,
INVALID_PARAMS: constants.VOICE_ERROR_TYPE.INVALID_PARAMS
},
/**
* @enum {string}
*/
AGENT_STATUS: { ...constants.AGENT_STATUS },
/**
* @enum {string}
*/
PARTICIPANT_TYPE: { ...constants.PARTICIPANT_TYPE },
/**
* @enum {string}
*/
CALL_TYPE: { ...constants.CALL_TYPE },
/**
* @enum {string}
*/
CALL_SUBTYPE: { ...constants.CALL_SUBTYPE },
/**
* @enum {string}
*/
DIALER_TYPE: { ...constants.DIALER_TYPE },
/**
* @enum {string}
*/
CONTACT_TYPE: { ...constants.CONTACT_TYPE },
/**
* @enum {string}
*/
CONTACT_LIST_TYPE: { ...constants.CONTACT_LIST_TYPE },
/**
* @enum {string}
*/
CALL_STATE: { ...constants.CALL_STATE },
/**
* @enum {string}
*/
HANGUP_REASON: { ...constants.HANGUP_REASON },
/**
* @enum {string}
*/
PHONE_TYPE: { ...constants.PHONE_TYPE },
/**
* @enum {String}
*/
AGENT_AVAILABILITY: { ...constants.AGENT_AVAILABILITY },
/**
* @enum (String)
*/
REMOVE_PARTICIPANT_VARIANT: { ...constants.REMOVE_PARTICIPANT_VARIANT },
/**
* @enum {String}
*/
LOG_LEVEL: { ...constants.LOG_LEVEL },
/**
* @enum {String}
*/
CONTACTS_FILTER_TYPES: { ...constants.CONTACTS_FILTER_TYPES },
/**
* @enum {String}
*/
WORK_EVENT: { ...constants.WORK_EVENT },
/**
* @enum {String}
*/
HANGUP_STATUS: { ...constants.HANGUP_STATUS }
};
/**
* Class representing a Custom Error
*/
export class CustomError extends Error {
/**
* Custom error
* @param {object} param
* @param {String} param.labelName
* @param {String} param.namespace
* @param {String} [param.message]
*/
constructor({ labelName, namespace, message }) {
super(message);
Validator.validateString(labelName);
Validator.validateString(namespace);
if (message) {
Validator.validateString(message);
}
this.labelName = labelName;
this.namespace = namespace;
this.message = message;
}
}
/**
* Class representing a Phone type
*/
export class Phone {
/**
* Create Phone
* @param {object} param
* @param {PHONE_TYPE} param.type
* @param {string} [param.number]
*/
constructor({ type, number}) {
Validator.validateEnum(type, Object.values(constants.PHONE_TYPE));
if(number) {
Validator.validateString(number);
}
this.type = type;
this.number = number;
}
}
/**
* Class representing a Hid Device
*/
export class HidDevice {
/**
* Create Hid Device
* @param productId
* @param vendorId
*/
constructor({ productId, vendorId }) {
if (productId) {
Validator.validateNumber(productId);
}
if (vendorId) {
Validator.validateNumber(vendorId);
}
this.productId = productId;
this.vendorId = vendorId;
}
}
/**
* Class representing result type for mute() & unmute()
*/
export class MuteToggleResult {
/**
* Create MuteToggleResult
* @param {object} param
* @param {boolean} param.isMuted
* @param {PhoneCall} param.call
* @param {boolean} param.isGlobal
*/
constructor({ isMuted, call, isGlobal }) {
this.isMuted = isMuted;
this.call = call;
this.isGlobal = isGlobal;
}
}
/**
* Class representing result type for getActiveCalls()
*/
export class ActiveCallsResult {
/**
* Create ActiveCallsResult
* @param {object} param
* @param {PhoneCall[]} [param.activeCalls]
*/
constructor({ activeCalls = [] }) {
if (activeCalls.length > 0) {
activeCalls.forEach(activeCall => {
Validator.validateClassObject(activeCall, PhoneCall);
});
}
this.activeCalls = activeCalls;
}
}
/**
* Class representing result type for getAudioDevices()
*/
export class AudioDevicesResult {
/**
* Create AudioDevicesResult
* @param {object} param
* @param {AudioDevice[]} param.audioDevices
*/
constructor({ audioDevices = [] }) {
this.audioDevices = audioDevices;
}
}
/**
* Class representing result type for getSharedCapabilities()
*/
export class SharedCapabilitiesResult {
/**
* Create SharedCapabilitiesResult
* @param {object} param
* @param {boolean} [param.debugEnabled]
* @param {boolean} [param.hasContactSearch] True if getPhoneContacts uses the 'contain' filter
* @param {boolean} [param.hasAgentAvailability] True if getPhoneContacts also provides agent availability, false if Salesforce provides it.
* @param {boolean} [param.hasQueueWaitTime] True if getPhoneContacts also provides estimated queue wait time, false if Salesforce provides it.
* @param {boolean} [param.hasTransferToOmniFlow] True if vendor supports transfer to omni flows
* @param {boolean} [param.hasPendingStatusChange] True if vendor supports Pending Status Change
* @param {boolean} [param.hasSFDCPendingState] True if amazon connect has sfdc_pending state
* @param {boolean} [param.hasAutoAcceptEnabled] True if agent has enabled auto accept
*/
constructor({
debugEnabled = true,
hasContactSearch = false,
hasAgentAvailability = false,
hasQueueWaitTime = false,
hasTransferToOmniFlow = false,
hasPendingStatusChange = false,
hasSFDCPendingState = false,
hasAutoAcceptEnabled = false
}){
Validator.validateBoolean(debugEnabled);
Validator.validateBoolean(hasContactSearch);
Validator.validateBoolean(hasAgentAvailability);
Validator.validateBoolean(hasQueueWaitTime);
Validator.validateBoolean(hasTransferToOmniFlow);
Validator.validateBoolean(hasPendingStatusChange);
Validator.validateBoolean(hasSFDCPendingState);
Validator.validateBoolean(hasAutoAcceptEnabled);
this.debugEnabled = debugEnabled;
this.hasContactSearch = hasContactSearch;
this.hasAgentAvailability = hasAgentAvailability;
this.hasQueueWaitTime = hasQueueWaitTime;
this.hasTransferToOmniFlow = hasTransferToOmniFlow;
this.hasPendingStatusChange = hasPendingStatusChange;
this.hasSFDCPendingState = hasSFDCPendingState;
this.hasAutoAcceptEnabled = hasAutoAcceptEnabled;
}
}
/**
* Class representing result type for getVoiceCapabilities()
*/
export class VoiceCapabilitiesResult {
/**
* Create VoiceCapabilitiesResult
* @param {object} param
* @param {boolean} [param.hasMute]
* @param {boolean} [param.hasRecord]
* @param {boolean} [param.hasMerge]
* @param {boolean} [param.hasSwap]
* @param {boolean} [param.hasBlindTransfer] True if vendor supports blind transfers
* @param {boolean} [param.hasSignedRecordingUrl]
* @param {boolean} [param.supportsMos] True if vendor support MOS
* @param {boolean} [param.hasSupervisorListenIn] True if vendor supports supervisor listening to a ongoing call
* @param {boolean} [param.hasSupervisorBargeIn] True if vendor supports Supervisor barging into a ongoing call
* @param {boolean} [param.hasPhoneBook] True if vendor supports the phoneBook UI
* @param {boolean} [param.hasGetExternalSpeakerDeviceSetting] True if vendor supports retrieving the speaker device ID
* @param {boolean} [param.hasSetExternalSpeakerDeviceSetting] True if vendor supports setting the speaker device ID
* @param {boolean} [param.hasGetExternalMicrophoneDeviceSetting] True if vendor supports retrieving the microphone device ID
* @param {boolean} [param.hasSetExternalMicrophoneDeviceSetting] True if vendor supports setting the microphone device ID
* @param {boolean} [param.canConsult] True if can consult
* @param {boolean} [param.isDialPadDisabled] True if dial pad is disabled
* @param {boolean} [param.isHidSupported] True if vendor supports hid or headset controllers
* @param {boolean} [param.isPhoneBookDisabled] True if phone book is disabled
*/
constructor({
hasMute = true,
hasRecord = true,
hasMerge = true,
hasSwap = true,
hasBlindTransfer = false,
hasSignedRecordingUrl = false,
supportsMos = false,
hasSupervisorListenIn = false,
hasSupervisorBargeIn = false,
hasPhoneBook = false,
hasGetExternalSpeakerDeviceSetting = false,
hasSetExternalSpeakerDeviceSetting = false,
hasGetExternalMicrophoneDeviceSetting = false,
hasSetExternalMicrophoneDeviceSetting = false,
canConsult= false,
isDialPadDisabled = false,
isHidSupported = false,
isPhoneBookDisabled = false
}) {
Validator.validateBoolean(hasMute);
Validator.validateBoolean(hasRecord);
Validator.validateBoolean(hasMerge);
Validator.validateBoolean(hasSwap);
Validator.validateBoolean(hasBlindTransfer);
Validator.validateBoolean(hasSignedRecordingUrl);
Validator.validateBoolean(supportsMos);
Validator.validateBoolean(hasSupervisorListenIn);
Validator.validateBoolean(hasSupervisorBargeIn);
Validator.validateBoolean(hasPhoneBook);
Validator.validateBoolean(hasGetExternalSpeakerDeviceSetting);
Validator.validateBoolean(hasSetExternalSpeakerDeviceSetting);
Validator.validateBoolean(hasGetExternalMicrophoneDeviceSetting);
Validator.validateBoolean(hasSetExternalMicrophoneDeviceSetting);
Validator.validateBoolean(canConsult);
Validator.validateBoolean(isDialPadDisabled);
Validator.validateBoolean(isHidSupported);
Validator.validateBoolean(isPhoneBookDisabled);
this.hasMute = hasMute;
this.hasRecord = hasRecord;
this.hasMerge = hasMerge;
this.hasSwap = hasSwap;
this.hasBlindTransfer = hasBlindTransfer;
this.hasSignedRecordingUrl = hasSignedRecordingUrl;
this.supportsMos = supportsMos;
this.hasSupervisorListenIn = hasSupervisorListenIn;
this.hasSupervisorBargeIn = hasSupervisorBargeIn;
this.hasPhoneBook = hasPhoneBook;
this.hasGetExternalSpeakerDeviceSetting = hasGetExternalSpeakerDeviceSetting;
this.hasSetExternalSpeakerDeviceSetting = hasSetExternalSpeakerDeviceSetting;
this.hasGetExternalMicrophoneDeviceSetting = hasGetExternalMicrophoneDeviceSetting;
this.hasSetExternalMicrophoneDeviceSetting = hasSetExternalMicrophoneDeviceSetting;
this.canConsult = canConsult;
this.isDialPadDisabled = isDialPadDisabled;
this.isHidSupported = isHidSupported;
this.isPhoneBookDisabled = isPhoneBookDisabled;
}
}
/**
* Class representing result type for getAgentConfig()
*/
export class AgentConfigResult {
/**
* Create AgentConfigResult
* @param {object} param
* @param {Phone[]} param.phones
* @param {Phone} param.selectedPhone
* @param {string} param.speakerDeviceId
* @param {string} param.microphoneDeviceId
*/
constructor({ phones = [constants.PHONE_TYPE.SOFT_PHONE], selectedPhone = new Phone({type: constants.PHONE_TYPE.SOFT_PHONE}),
speakerDeviceId = '', microphoneDeviceId = ''}) {
Validator.validateClassObject(phones, Array);
Validator.validateClassObject(selectedPhone, Phone);
Validator.validateString(speakerDeviceId);
Validator.validateString(microphoneDeviceId);
this.phones = phones;
this.selectedPhone = selectedPhone;
this.speakerDeviceId = speakerDeviceId;
this.microphoneDeviceId = microphoneDeviceId;
}
}
/**
* Class representing AgentConfig type for setAgentConfig()
*/
export class AgentConfig {
/**
* Create AgentConfig
* @param {object} param
* @param {Phone} param.selectedPhone
* @param {string} param.speakerDeviceId
* @param {string} param.microphoneDeviceId
* @param {HidDevice} param.hidDeviceInfo
*/
constructor({ selectedPhone,speakerDeviceId, microphoneDeviceId, hidDeviceInfo }) {
Validator.validateClassObject(selectedPhone, Phone);
//Hid device info is optional
if (hidDeviceInfo !== undefined) {
Validator.validateClassObject(hidDeviceInfo, HidDevice);
}
this.selectedPhone = selectedPhone;
this.speakerDeviceId = speakerDeviceId;
this.microphoneDeviceId = microphoneDeviceId;
this.hidDeviceInfo = hidDeviceInfo;
}
}
/**
* Class representing result type for pauseRecording() & resumeRecording
*/
export class RecordingToggleResult {
/**
* Create RecordingToggleResult
* @param {object} param
* @param {boolean} param.isRecordingPaused
* @param {string} [param.contactId]
* @param {string} [param.initialContactId]
* @param {string} [param.instanceId]
* @param {string} [param.region]
*/
constructor({ isRecordingPaused, contactId = null, initialContactId = null, instanceId = null, region = null }) {
this.isRecordingPaused = isRecordingPaused;
this.contactId = contactId;
this.initialContactId = initialContactId;
this.instanceId = instanceId;
this.region = region;
}
}
/**
* Class representing result type for addParticipant()
*/
export class ParticipantResult {
/**
* Create ParticipantResult
* @param {object} param
* @param {boolean} param.initialCallHasEnded
* @param {CallInfo} param.callInfo
* @param {PhoneCallAttributes} [param.callAttributes] - Any additional call attributes
* @param {string} param.phoneNumber
* @param {string} param.callId
* @param {Contact} param.contact
* @param {string} param.connectionId - optional connectionID representing a call leg.
*/
constructor({ initialCallHasEnded, callInfo, callAttributes, phoneNumber, callId, contact = null , connectionId}) {
Validator.validateClassObject(callInfo, CallInfo);
this.initialCallHasEnded = initialCallHasEnded;
this.callInfo = callInfo;
this.callAttributes = callAttributes;
this.phoneNumber = phoneNumber;
this.callId = callId;
this.contact = contact
if (connectionId) {
this.connectionId = connectionId;
} else {
this.connectionId = callId;
}
}
}
/**
* Class representing result type for getContacts()
*/
export class ContactsResult {
/**
* Create ContactsResult
* @param {object} param
* @param {Contact[]} [param.contacts]
* @param {Array} [param.contactTypes]
*/
constructor({ contacts = [], contactTypes = [] }) {
if (contacts.length > 0) {
contacts.forEach(contact => {
Validator.validateClassObject(contact, Contact);
});
}
if (contactTypes.length > 0) {
contactTypes.forEach(filterType => {
Validator.validateEnum(filterType, Object.values(constants.CONTACT_TYPE));
});
}
this.contacts = contacts;
this.contactTypes = contactTypes;
}
}
/**
* Class representing result type for getPhoneContacts()
* NOTE: TO BE DEPRECATED, Use ContactsResult instead
*/
export class PhoneContactsResult extends ContactsResult {
/**
* Create PhoneContactsResult
* @param {object} param
* @param {Contact[]} [param.contacts]
* @param {Array} [param.contactTypes]
*/
constructor({ contacts = [], contactTypes = [] }) {
super({ contacts, contactTypes });
}
}
/**
* Class representing result type for accept(), decline(), dial()
*/
export class CallResult {
/**
* Create CallResult
* @param {object} param
* @param {PhoneCall} [param.call]
*/
constructor({ call }) {
if (call !== undefined) {
Validator.validateClassObject(call, PhoneCall);
}
this.call = call;
}
}
/**
* Class representing result type for endCall(), hangup()
*/
export class HangupResult {
/**
* Create CallResult
* @param {object} param
* @param {PhoneCall[]|PhoneCall} param.calls - one or more calls (can be multiple calls in case of agent endcall/hangup)
*/
constructor({ calls }) {
if (calls instanceof Array) {
calls.forEach(call => Validator.validateClassObject(call, PhoneCall));
this.calls = calls;
} else {
Validator.validateClassObject(calls, PhoneCall);
this.calls = [calls];
}
}
}
/**
* Class representing result type for hold() & resume()
*/
export class HoldToggleResult {
/**
* Create HoldToggleResult
* @param {object} param
* @param {boolean} param.isThirdPartyOnHold
* @param {boolean} param.isCustomerOnHold
* @param {PhoneCall[]} [param.calls]
* @param {boolean} param.isCallMerged
*/
constructor({ isThirdPartyOnHold, isCustomerOnHold, calls , isCallMerged}) {
if (calls) {
Object.values(calls).forEach(call => {
Validator.validateClassObject(call, PhoneCall);
});
this.calls = calls;
}
this.isThirdPartyOnHold = isThirdPartyOnHold;
this.isCustomerOnHold = isCustomerOnHold;
this.isCallMerged = isCallMerged;
}
}
/**
* Class representing result type for getRecordingUrl
*/
export class SignedRecordingUrlResult {
/**
* Create SignedRecordingUrlResult
* @param {object} param
* @param {boolean} param.success
* @param {string} [param.url]
* @param {number} [param.duration] in seconds
* @param {string} [param.callId] Salesforce callId of the voice call
*/
constructor({ success, url, duration, callId }) {
if (success) {
// For a successfull result, url is required
Validator.validateString(url);
Validator.validateString(callId);
if (duration) {
Validator.validateNumber(duration);
}
}
this.success = success;
this.url = url;
this.duration = duration;
this.callId = callId;
}
}
/**
* Class representing result type for init()
*/
export class InitResult {
/**
* Create InitResult
* @param {object} param
* @param {boolean} [param.showLogin]
* @param {number} [param.loginFrameHeight]
* @param {boolean} [param.isSilentLogin]
* @param {boolean} [param.showStorageAccess]
*/
constructor({ showLogin = false, loginFrameHeight = 350, isSilentLogin = false, showStorageAccess = false }) {
this.showLogin = showLogin;
this.loginFrameHeight = loginFrameHeight;
this.isSilentLogin = this.showLogin ? false : isSilentLogin;
this.showStorageAccess = showStorageAccess;
}
}
/**
* Class representing dial options for outbound dialing
*/
export class DialOptions {
/**
* Create DialOptions
* @param {boolean} [param.isCallback]
* @param {boolean} [param.isConsultCall]
*/
constructor({ isCallback = false, isConsultCall = false }) {
this.isCallback = isCallback;
this.isConsultCall = isConsultCall;
}
}
/**
* Class representing generic result type
*/
export class GenericResult {
/**
* Create GenericResult
* @param {object} param
* @param {boolean} param.success
*/
constructor({ success }) {
this.success = success;
}
}
/**
* Class representing result type for setAgentStatus()
*/
export class SetAgentStateResult extends GenericResult {
/**
* Create AgentState
* @param {object} param
*/
constructor({ success, isStatusSyncNeeded = true }) {
super({ success });
this.isStatusSyncNeeded = isStatusSyncNeeded;
}
}
/**
* Class representing result type for setAgentConfig()
*/
export class SetAgentConfigResult extends GenericResult {
/**
* Create AgentConfig
* @param {object} param
*/
constructor({ success, isSystemEvent = false }) {
super({ success });
this.isSystemEvent = isSystemEvent;
}
setIsSystemEvent(isSystemEvent) {
this.isSystemEvent = isSystemEvent;
}
}
/**
* Class representing logout result type
*/
export class LogoutResult {
/**
* Create LogoutResult
* @param {object} param
* @param {boolean} param.success
* @param {number} [param.loginFrameHeight]
*/
constructor({ success, loginFrameHeight = 350 }) {
this.success = success;
this.loginFrameHeight = loginFrameHeight;
}
}
/**
* Class representing callInfo class (call metadata)
*/
export class CallInfo {
/**
* Create CallInfo
* @param {object} param
* @param {boolean} param.isOnHold
* @param {boolean} param.isRecordingPaused
* @param {boolean} param.isMuted
* @param {string} [param.initialCallId]
* @param {Date} [param.callStateTimestamp]
* @param {string} [param.queueName]
* @param {string} [param.queueId]
* @param {Date} [param.queueTimestamp]
* @param {boolean} [param.isSoftphoneCall] - is it a softphone call
* @param {boolean} [param.acceptEnabled]
* @param {boolean} [param.declineEnabled]
* @param {boolean} [param.muteEnabled]
* @param {boolean} [param.swapEnabled]
* @param {boolean} [param.conferenceEnabled]
* @param {boolean} [param.holdEnabled]
* @param {boolean} [param.recordEnabled]
* @param {boolean} [param.addCallerEnabled]
* @param {boolean} [param.extensionEnabled]
* @param {boolean} [param.isReplayable]
* @param {boolean} [param.isBargeable]
* @param {boolean} [param.isExternalTransfer]
* @param {boolean} [param.showMuteButton]
* @param {boolean} [param.showRecordButton]
* @param {boolean} [param.showAddCallerButton]
* @param {boolean} [param.showAddBlindTransferButton]
* @param {boolean} [param.showMergeButton]
* @param {boolean} [param.showSwapButton]
* @param {("ALWAYS"|"NEVER"|"ALWAYS_EXCEPT_ON_HOLD")} [param.removeParticipantVariant] - The type of remove participant variant when in a transfer call.
* @param {String} [param.additionalFields] - Represents additional standard and custom fields in the voice call record, where each key-value pair value corresponds to a standard or custom field and its values.
* @param {boolean} [param.isMultiParty]
* @param {boolean} [param.isHIDCall]
* @param {boolean} [param.endCallDisabled]
* @param {string} [param.renderContactId]
*/
constructor({ callStateTimestamp = null, isOnHold, isMuted = false, isRecordingPaused = false, initialCallId, queueId = null, queueName = null, queueTimestamp = null, isSoftphoneCall = true,
acceptEnabled = true, declineEnabled = true, muteEnabled = true, swapEnabled = true, conferenceEnabled = true, holdEnabled = true,
recordEnabled = true, addCallerEnabled = true, extensionEnabled = true, isReplayable = true, isBargeable = false, isExternalTransfer,
showMuteButton = true, showRecordButton = true, showAddCallerButton = true, showAddBlindTransferButton = true, showMergeButton = true,
showSwapButton = true, removeParticipantVariant = Constants.REMOVE_PARTICIPANT_VARIANT.ALWAYS, additionalFields = null, isMultiParty = false, isHIDCall = false, endCallDisabled = false, renderContactId = null }) {
if (callStateTimestamp) {
Validator.validateDate(callStateTimestamp);
}
if (queueTimestamp) {
Validator.validateDate(queueTimestamp);
}
if (queueId) {
Validator.validateString(queueId);
}
if (queueName) {
Validator.validateString(queueName);
}
Validator.validateBoolean(isRecordingPaused);
Validator.validateBoolean(isMuted);
Validator.validateBoolean(isSoftphoneCall);
Validator.validateBoolean(acceptEnabled);
Validator.validateBoolean(declineEnabled);
Validator.validateBoolean(muteEnabled);
Validator.validateBoolean(swapEnabled);
Validator.validateBoolean(conferenceEnabled);
Validator.validateBoolean(holdEnabled);
Validator.validateBoolean(recordEnabled);
Validator.validateBoolean(addCallerEnabled);
Validator.validateBoolean(extensionEnabled);
Validator.validateBoolean(isBargeable);
Validator.validateBoolean(showMuteButton);
Validator.validateBoolean(showRecordButton);
Validator.validateBoolean(showAddCallerButton);
Validator.validateBoolean(showAddBlindTransferButton);
Validator.validateBoolean(showMergeButton);
Validator.validateBoolean(showSwapButton);
Validator.validateBoolean(isHIDCall);
Validator.validateBoolean(endCallDisabled);
if (isExternalTransfer !== undefined) {
Validator.validateBoolean(isExternalTransfer);
}
Validator.validateEnum(removeParticipantVariant, Object.values(constants.REMOVE_PARTICIPANT_VARIANT));
if (additionalFields) {
Validator.validateString(additionalFields);
}
Validator.validateBoolean(isMultiParty);
if (renderContactId) {
Validator.validateString(renderContactId);
}
this.callStateTimestamp = callStateTimestamp;
this.isRecordingPaused = isRecordingPaused;
this.isMuted = isMuted;
this.isOnHold = isOnHold;
this.initialCallId = initialCallId;
this.queueName = queueName;
this.queueId = queueId;
this.queueTimestamp = queueTimestamp;
this.isSoftphoneCall = isSoftphoneCall;
this.acceptEnabled = acceptEnabled;
this.declineEnabled = declineEnabled;
this.muteEnabled = muteEnabled;
this.swapEnabled = swapEnabled;
this.conferenceEnabled = conferenceEnabled;
this.holdEnabled = holdEnabled;
this.recordEnabled = recordEnabled;
this.addCallerEnabled = addCallerEnabled;
this.extensionEnabled = extensionEnabled;
this.isReplayable = isReplayable;
this.isBargeable = isBargeable;
this.isExternalTransfer = isExternalTransfer;
this.removeParticipantVariant = removeParticipantVariant;
this.showMuteButton = showMuteButton;
this.showRecordButton = showRecordButton;
this.showAddCallerButton = showAddCallerButton;
this.showAddBlindTransferButton = showAddBlindTransferButton;
this.showMergeButton = showMergeButton;
this.showSwapButton = showSwapButton;
this.additionalFields = additionalFields;
this.isMultiParty = isMultiParty;
this.isHIDCall = isHIDCall;
this.endCallDisabled = endCallDisabled;
this.renderContactId = renderContactId;
}
}
/**
* Class representing a Contact. This object is used to represent
* phone system contact or any call target
*/
export class Contact {
/**
* Create a Contact.
* @param {object} param
* @param {string} [param.id] - The unique contactId
* @param {("PhoneBook"|"Queue"|"PhoneNumber"|"Agent")} [param.type] - The type of the contact, one of the CONTACT_TYPE values
* @param {string} [param.name] - The label for this contact to be displayed in the UI
* @param {("Transfer"|"Conference"|"All")} [param.listType] - The type of contact List, one of the CONTACT_LIST_TYPE values. Messaging Only
* @param {string} [param.phoneNumber] - The phone number associcated with this contact
* @param {string} [param.prefix] - Any prefix to be dialed before dialing the number (i.e. +1)
* @param {string} [param.extension] - Any extension to be dialed after dialing the number
* @param {string} [param.endpointARN]
* @param {string} [param.queue]
* @param {string} [param.availability]
* @param {string} [param.recordId] - Salesforce RecordId
* @param {string} [param.description] - Contact Description
* @param {string} [param.queueWaitTime] - Estimated Queue Wait Time
*/
constructor({phoneNumber, id, type, name, listType, prefix, extension, endpointARN, queue, availability, recordId, description, queueWaitTime}) {
if (phoneNumber) {
Validator.validateString(phoneNumber);
}
if (type) {
Validator.validateEnum(type, Object.values(constants.CONTACT_TYPE));
}
if (id) {
Validator.validateString(id);
}
if (name) {
Validator.validateString(name);
}
if (listType) {
Validator.validateEnum(listType, Object.values(Constants.CONTACT_LIST_TYPE));
}
if (prefix) {
Validator.validateString(prefix);
}
if (extension) {
Validator.validateString(extension);
}
if (availability) {
Validator.validateEnum(availability, Object.values(constants.AGENT_AVAILABILITY));
}
if (recordId) {
Validator.validateString(recordId);
}
if (description) {
Validator.validateString(description);
}
if (queueWaitTime) {
Validator.validateString(queueWaitTime);
}
this.phoneNumber = phoneNumber;
this.id = id;
this.type = type;
this.name = name;
this.listType = listType;
this.prefix = prefix;
this.extension = extension;
this.endpointARN = endpointARN;
this.queue = queue;
if (constants.CONTACT_TYPE.AGENT === this.type) {
this.availability = availability;
} else {
this.availability = null;
}
this.queueWaitTime = queueWaitTime;
this.recordId = recordId;
this.description = description;
}
}
/**
* Class representing PhoneCallAttributes
*/
export class PhoneCallAttributes {
/**
* Create PhoneCallAttributes.
* @param {object} param
* @param {string} [param.voiceCallId] - The voice call id
* @param {PARTICIPANT_TYPE} [param.participantType] - The participant type of the call
* @param {DIALER_TYPE} [param.dialerType] - The dialer type of the call
* @param {string} [param.parentId] - The parent call id of the call
* @param {boolean} [param.isOnHold]
* @param {boolean} [param.hasSupervisorBargedIn]
* @param {boolean} [param.isAutoMergeOn] - for multiparty conference, the call cannot be put on hold, and is being auto-merged
* @param {boolean} [param.isConsultCall] - true if the call is a Consult call
*/
constructor({ voiceCallId, participantType, dialerType = Constants.DIALER_TYPE.NONE, parentId, isOnHold, hasSupervisorBargedIn = false, isAutoMergeOn = false, isConsultCall = false }) {
if (voiceCallId) {
Validator.validateString(voiceCallId);
}
if (participantType) {
Validator.validateEnum(participantType, Object.values(constants.PARTICIPANT_TYPE));
}
if (parentId) {
Validator.validateString(parentId);
}
if (isOnHold !== undefined) {
Validator.validateBoolean(isOnHold);
}
Validator.validateBoolean(hasSupervisorBargedIn);
Validator.validateEnum(dialerType, Object.values(constants.DIALER_TYPE));
Validator.validateBoolean(isAutoMergeOn);
Validator.validateBoolean(isConsultCall);
this.voiceCallId = voiceCallId;
this.participantType = participantType;
this.parentId = parentId;
this.isOnHold = isOnHold;
this.dialerType = dialerType;
this.hasSupervisorBargedIn = hasSupervisorBargedIn;
this.isAutoMergeOn = isAutoMergeOn;
this.isConsultCall = isConsultCall;
}
}
/**
* Class representing a PhoneCall (PSTN or WebRTC).
*/
export class PhoneCall {
/**
* Create a PhoneCall.
* @param {object} param
* @param {string} [param.callId] - The unique callId. This is a required parameter
* @param {string} [param.connectionId] - optional connectionID representing a call leg.
* @param {CALL_TYPE} [param.callType] - The type of the call, one of the CALL_TYPE values
* @param {CALL_SUBTYPE} [param.callSubtype] - The subtype of the call, one of the CALL_SUBTYPE values
* @param {Contact} [param.contact] - The Call Target / Contact . TODO: to be deprecated, replace with toContact
* @param {string} [param.state] - The state of the call, i.e. ringing, connected, declined, failed
* @param {PhoneCallAttributes} [param.callAttributes] - Any additional call attributes
* @param {string} [param.phoneNumber] - The phone number associated with this call (usually external number)
* @param {CallInfo} [param.callInfo]
* @param {string} [param.reason]
* @param {boolean} [param.closeCallOnError]
* @param {string} [param.agentStatus]
* @param {string} [param.agentARN]
* @param {Contact} [param.fromContact] - This is optional, and being populated when dialing/consulting a contact or adding a participant
* @param {Contact} [param.toContact] - This is currently the same as param.contact (just rename)
*/
constructor({callId, callType, callSubtype, contact, state, callAttributes, phoneNumber, callInfo, reason, closeCallOnError, agentStatus, agentARN, fromContact, toContact, connectionId }) {
// TODO: Revisit the required fields
if (callId) {
Validator.validateString(callId);
this.callId = callId;
}
// Salesforce uses connectionId to represent a call leg as provided or assumed to be same as callId
// if provided, connectionId can be used in the connector API instead of the callId
// if not provided, it will be a copy of the callId
if (connectionId) {
Validator.validateString(connectionId);
this.connectionId = connectionId;
} else if (callId) {
this.connectionId = callId;
}
if (callType) {
Validator.validateEnum(callType, Object.values(constants.CALL_TYPE));
this.callType = callType;
}
if (callSubtype) {
Validator.validateEnum(callSubtype, Object.values(constants.CALL_SUBTYPE));
this.callSubtype = callSubtype;
}
if (phoneNumber) {
Validator.validateString(phoneNumber);
this.phoneNumber = phoneNumber;
}
if (callInfo) {
Validator.validateClassObject(callInfo, CallInfo);
this.callInfo = callInfo;
}
if (contact) {
Validator.validateClassObject(contact, Contact);
this.contact = contact;
}
if (fromContact) {
Validator.validateClassObject(fromContact, Contact);
this.fromContact = fromContact;
}
if (toContact) {
Validator.validateClassObject(toContact, Contact);
this.toContact = toContact;
} else if (contact) {
this.toContact = contact;
}
if (reason) {
this.reason = reason;
}
if (closeCallOnError) {
this.closeCallOnError = closeCallOnError;
}
if (agentStatus) {
this.agentStatus = agentStatus;
}
if (agentARN) {
this.agentARN = agentARN;
}
this.state = state;
this.callAttributes = callAttributes;
}
}
/**
* Class representing a TelephonyConnector
*/
export class TelephonyConnector {
/**
* Get the currently active calls
* @returns {Promise<ActiveCallsResult>}
*
*/
getActiveCalls() {
throw new Error('Not implemented');
}
/**
* Accept call
* @param {PhoneCall} call - The call to be accepted
* @returns {Promise<CallResult>}
*
*/
acceptCall(call) {
throw new Error('Not implemented');
}
/**
* Decline call
* @param {PhoneCall} call - The call to be declined
* @returns {Promise<CallResult>}
*
*/
declineCall(call) {
throw new Error('Not implemented');
}
/**
* End call
* @param {PhoneCall} call - The call to be ended
* @param {AGENT_STATUS} agentStatus
* @returns {Promise<HangupResult>}
*
*/
endCall(call, agentStatus) {
throw new Error('Not implemented');
}
/**
* Mute call
* @param {PhoneCall} call (an optional participant call to mute)
* @returns {Promise<MuteToggleResult>}
*
*/
mute(call) {
throw new Error('Not implemented');
}
/**
* Unmute call
* @param {PhoneCall} call (an optional participant call to unmute)
* @returns {Promise<MuteToggleResult>}
*
*/
unmute(call) {
throw new Error('Not implemented');
}
/**
* Hold call
* @param {PhoneCall} call - The call to be held
* @returns {Promise<HoldToggleResult>}
*
*/
hold(call) {
throw new Error('Not implemented');
}
/**
* Resume call
* @param {PhoneCall} call - The call to be resumed
* @returns {Promise<HoldToggleResult>}
*
*/
resume(call) {
throw new Error('Not implemented');
}
/**
* Dial out Number
* @param {Contact} contact
* @param {DialOptions} dialOptions
* @returns {Promise<CallResult>}
*
*/
dial(contact, dialOptions) {
throw new Error('Not implemented');
}
/**
* Send digits
* @param {string} digits
*/
sendDigits(digits) {
throw new Error('Not implemented');
}
/**
* Get phone contacts
* @param {ContactsFilter} filterType
* @returns {Promise<PhoneContactsResult>}
*/
getPhoneContacts(filter) {
throw new Error('Not implemented');
}
/**
* Swap calls
* @param {PhoneCall} call1
* @param {PhoneCall} call2
* @returns {Promise<HoldToggleResult>}
*/
swap(call1, call2) {
throw new Error('Not implemented');
}
/**
* Conference calls
* @param {PhoneCall[]} calls
* @returns {Promise<HoldToggleResult>}
*/
conference(calls) {
throw new Error('Not implemented');
}
/**
* Add participant to call
* @param {Contact} contact: The transfer target
* @param {PhoneCall} parentCall: The call to which a participant will be added
* @param {Boolean} isBlindTransfer: True if blind transfering a call and hanging up upon transfer
* @returns {Promise<ParticipantResult>}
*/
addParticipant(contact, parentCall, isBlindTransfer) {
throw new Error('Not implemented');
}
/**
* Pause recording
* @returns {Promise<RecordingToggleResult>}
*/
pauseRecording() {
throw new Error('Not implemented');
}
/**
* Resume recording
* @returns {Promise<RecordingToggleResult>}
*/
resumeRecording() {
throw new Error('Not implemented');
}
/**
* Get agentConfig
* @returns {Promise<AgentConfigResult>}
*/
getAgentConfig() {
throw new Error('Not implemented');
}
/**
* Set Agent Config
* @param {AgentConfig} config
* @returns {Promise<GenericResult>}
*/
setAgentConfig(config) {
throw new Error('Not implemented');
}
/**
* Get voice capabilities
* @returns {Promise<VoiceCapabilitiesResult>}
*/
getVoiceCapabilities() {
throw new Error('Not implemented');
}
/**
* Wrap up call
* @param {PhoneCall} call
*/
wrapUpCall(call) {
throw new Error('Not implemented');
}
/**
* Get the signed recording url
* @param {String} recordingUrl
* @param {String} vendorCallKey
* @param {String} callId
* @returns {Promise<SignedRecordingUrlResult>}
*/
getSignedRecordingUrl(recordingUrl, vendorCallKey, callId) {
throw new Error('Not implemented');
}
/**
* Supervise a call
* @param {SupervisedCallInfo} supervisedCallInfo CallInfo of the call to be supervised
* @returns {Promise <SuperviseCallResult>}
*/
superviseCall(supervisedCallInfo) {
throw new Error('Not implemented');
}
/**
* Supervisor disconnects from a call
* @param {SupervisedCallInfo} supervisedCallInfo CallInfo of the supervised call to be disconnected
* @returns {Promise <SupervisorHangupResult>}
*/
supervisorDisconnect(supervisedCallInfo) {
throw new Error('Not implemented');
}
/**
* Supervisor Barges into a ongoing call
* @param {SupervisedCallInfo} supervisedCallInfo CallInfo of the supervised call which supervisor barges in
* @returns {Promise <SuperviseCallResult>}
*/
supervisorBargeIn(supervisedCallInfo) {
throw new Error('Not implemented');
}
}
/**
* Class representing a VendorConnector
*/
export class VendorConnector {
/**
* Initialize the connector
* @param {object} connectorConfig
* @returns {Promise<InitResult>}
*
*/
init(config) {
throw new Error('Not implemented');
}
/**
* Gets the telephonyConnector
* @returns {Promise<TelephonyConnector>}
*
*/
getTelephonyConnector() {
throw new Error('Not implemented');
}
/**
* Sends non-voice agent work events to vendor such as work accepted, declined, etc
* @param {AgentWork} agentWork
*
*/
onAgentWorkEvent(agentWork) {
throw new Error('Not implemented');
}
/**
* Set agent status
* @param {Constants.AGENT_STATUS} agentStatus
* @param {StatusInfo} statusInfo
* @param {Boolean} enqueueNextState - flag to determine if this status change request should be enqueued if neccessary
* @returns {Promise<GenericResult>}
*
*/
setAgentStatus(agentStatus, statusInfo, enqueueNextState) {
throw new Error('Not implemented');
}
/**
* Get agent status
* @returns {Promise<AgentStatusInfo>}
*
*/
getAgentStatus() {
this.logMessageToVendor(constants.LOG_LEVEL.INFO, 'getAgentStatus API is NOT Implemented' );
}
/**
* Logout from Omni
* @returns {Promise<LogoutResult>}
*/
logout() {
throw new Error('Not implemented');
}
/**
* Handle message from LWC/Aura component
* @param {object} message
*/
handleMessage(message) {
throw new Error('Not implemented');
}
/**
* Triggers a browser download for Vendor Logs
* @param {String[]} logs Array of log messages.
*/
downloadLogs(logs) {
downloadLogs();
}
/**
* Sends the logs with a logLevel and payload to the vendor connector.
* Does a no-op, if not implemented.
* @param {String} logLevel Log Level (INFO, WARN, ERROR)
* @param {String} message Message to be logged
* @param {Object} payload An optional payload to be logged
*/
logMessageToVendor(logLevel, message, payload) {}
/**
* To get the Contacts for this workItem's transfer/other channel operation
* @param {ContactsFilter} filter It has fields like the search term and contact Type
* @param {String} workItemId
* @returns {Promise<PhoneContactsResult>}
*/
getContacts(filter, workItemId) {
throw new Error('Not implemented');
}
/**
* Returns a list of valid device IDs that can be used for the speaker and microphone devices.
*/
getAudioDevices() {
throw new Error('Not implemented');
}
/**
* Get shared capabilities
* @returns {Promise<SharedCapabilitiesResult>}
*/
getSharedCapabilities() {
throw new Error('Not implemented');
}
}
export class Validator {
static validateString(value) {
if (typeof value !== 'string') {
throw new Error(`Invalid argument. Expecting a string but got ${typeof value}`);
}
return this;
}
static validateNumber(value) {
if (typeof value !== 'number') {
throw new Error(`Invalid argument. Expecting a number but got ${typeof value}`);
}
return this;
}
static validateBoolean(value) {
if (typeof value !== 'boolean') {
throw new Error(`Invalid argument. Expecting a boolean but got ${typeof value}`);
}
return this;
}
static validateEnum(value, enumValues) {
const regex = new RegExp(enumValues.join( "|" ), "i");
if (!regex.test(value)) {
throw new Error(`Invalid argument. Expecting a value from ${JSON.stringify(enumValues)} but got ${value}`);
}
return this;
}
static validateDate(value) {
if (!(value instanceof Date)) {
throw new Error(`Invalid argument. Expecting a Date object but got ${typeof value}`);
}
return this;
}
static validateClassObject(object, className) {
if (!(object instanceof className)) {
throw new Error(`Invalid className. Expecting object of class ${className} but got ${typeof object}`);
}
return this;
}
static validateClassObjects(object, ...classNames) {
let isValid = false;
for (let i = 0; i < classNames.length; i++) {
try {
this.validateClassObject(object, classNames[i]);
isValid = true;
break;
} catch(e) {
// continue on
}
}
if (!isValid) {
throw new Error(`Invalid className. Expecting object matching a class name in ${classNames} but got ${typeof object}`);
}
return this;
}
}
/**
* Class representing an AgentWork
*/
export class AgentWork {
/**
* Create an AgentWork.
* @param {object} param
* @param {string} [param.workItemId] - Salesforce agent work it