Files
call-sdk/packages/adapter-ameyo/lib/main.ts
Varnit Goyal 480f7c4f61 TP-89230 | append tags singleton (#14)
* TP-89230 | append tags singleton

* TP-88230 | fix: added console log

* Publish

 - @universal-call-sdk/adapter-ameyo@1.0.62
 - @universal-call-sdk/common@1.0.17
 - @universal-call-sdk/core@1.0.22

* TP-89230 | make append tag syncronous

* Publish

 - @universal-call-sdk/adapter-ameyo@1.0.63
 - @universal-call-sdk/common@1.0.18
 - @universal-call-sdk/core@1.0.23

* TP-89230 | make append tag syncronous

* Publish

 - @universal-call-sdk/adapter-ameyo@1.0.64
 - @universal-call-sdk/common@1.0.19
 - @universal-call-sdk/core@1.0.24

* TP-89230 | make append tag syncronous

* Publish

 - @universal-call-sdk/adapter-ameyo@1.0.65
 - @universal-call-sdk/common@1.0.20
 - @universal-call-sdk/core@1.0.25

* TP-89230 | on sip ready custom event

* Publish

 - @universal-call-sdk/adapter-ameyo@1.0.66
 - @universal-call-sdk/common@1.0.21
 - @universal-call-sdk/core@1.0.26

* TP-89230 | on sip ready custom event

* Publish

 - @universal-call-sdk/adapter-ameyo@1.0.67
 - @universal-call-sdk/common@1.0.22
 - @universal-call-sdk/core@1.0.27

* TP-89230 | on sip ready custom event

* Publish

 - @universal-call-sdk/adapter-ameyo@1.0.68
 - @universal-call-sdk/common@1.0.23
 - @universal-call-sdk/core@1.0.28

---------

Co-authored-by: varnit goyal <github.cicd@navi.com>
2024-11-28 15:35:58 +05:30

375 lines
13 KiB
TypeScript

import IAdapter from "@universal-call-sdk/common/lib/Interfaces/IAdapter.ts";
import GenericObject from "@universal-call-sdk/common/lib/types/GenericObject.ts";
import {AmeyoInitializationOptions, CALL_STATES, RequestKeys, SipAccountInfo, StateType} from "./types.ts";
import MessagingType from "../types/MessagingType.ts";
import {
ameyoHangupUser,
attachOmniqueService,
autoSelectExtension,
getSipAccountInfo,
loginInAmeyo, maintainHeartbeat,
selectCampaign,
setAgentActive, setAgentOnBreak,
setAutoStatus,
getCampaignId, ameyoDisposeCall
} from "./api.ts";
import {
acceptSipCall,
loadCallOptions,
loadCredentials,
sipHangUp,
sipMuteCall,
sipRegister, sipUnmuteCall
} from "./assets/js/sip5ml.service.ts";
import registerEventProcessor from "./eventsProcessor.ts";
class AmeyoAdapter implements IAdapter {
private callbacks: {
onCallConnected: (data: StateType) => void;
onCallDisconnected: (data: StateType) => void;
onCallIncoming: (data: StateType) => void,
onAdapterReady: () => void,
onAgentAvailabilityChange: (isAgentAvailable: boolean) => void
onForcedLogout: () => void
};
private currentCallState: string;
private eventListenerUrl: string;
private baseUrl: string;
private sessionId: string;
private campaignId: string;
private userName: string;
private password: string;
private currentCallMetadata: GenericObject;
private sipAccountInfo: GenericObject;
private isAgentAvailable: boolean;
constructor(options: AmeyoInitializationOptions) {
console.log('AmeyoAdapter constructor');
if(document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', this._appendTags);
} else {
this._appendTags();
}
this.baseUrl = options.baseUrl;
this.eventListenerUrl = options.eventListenerUrl;
this.currentCallState = CALL_STATES.IDLE;
this.callbacks = {
onCallIncoming: () => {
},
onCallConnected: () => {
},
onCallDisconnected: () => {
},
onAdapterReady: () => {
},
onAgentAvailabilityChange: () => {
},
onForcedLogout: () => {
}
};
this.sessionId = '';
this.userName = options.userName;
this.password = options.password;
this.campaignId = '';
this.sipAccountInfo = {};
this.currentCallMetadata = {};
this.isAgentAvailable = false;
window.BASE_AMEYO_URL = this.baseUrl;
window.AMEYO_LOGIN_URL = options.loginUrl
}
init() {
console.log('initializing ameyo adapter');
window.addEventListener('message', this._registerMessageListener);
this._initializeAmeyo();
}
_initializeSipStack = ({accountName, userName, domain="", password}: SipAccountInfo) => {
console.log('initializing sip stack');
const domainOnly = domain?.split?.(':')?.[0];
const port = domain?.split?.(':')?.[1];
//initialize sip stack
loadCredentials({accountName, userName, domain, password});
loadCallOptions();
sipRegister({domain: domainOnly, port});
}
_initializeAmeyo = () => {
loginInAmeyo(this.userName?.toLowerCase(), this.password);
}
_onListenForCorsBypassResponse = (payload: GenericObject) => {
console.log('universal sdk', payload);
if (payload?.data?.requestKey === RequestKeys.AMEYO_LOGIN) {
const sessionId = payload?.data?.response?.userSessionInfo?.sessionId;
this.sessionId = sessionId;
getSipAccountInfo(sessionId, this.userName?.toLowerCase());
registerEventProcessor(this.eventListenerUrl, sessionId);
maintainHeartbeat(this.sessionId, window?.listenerName || '', 0);
}
if (payload?.data?.requestKey === RequestKeys.AMEYO_HEARTBEAT) {
console.log('heartbeat response', payload?.data?.response);
}
if (payload?.data?.requestKey === RequestKeys.SIP_ACCOUNT_INFO) {
console.log('sip account info', payload?.data?.response);
const response = payload?.data?.response;
this._initializeSipStack({
accountName: response?.accountName,
userName: response?.userName,
domain: response?.domain,
password: response?.secret
});
console.log('sip account info', this.sipAccountInfo)
this.sipAccountInfo = payload?.data?.response;
getCampaignId(this.sessionId);
setAutoStatus(this.sessionId);
}
if (payload?.data?.requestKey === RequestKeys.GET_CAMPAIGN_ID) {
this.campaignId = payload?.data?.response?.campaignInfos?.[0]?.campaignId;
attachOmniqueService(this.sessionId, this.userName.toLowerCase(), this.campaignId);
}
if (payload?.data?.requestKey === RequestKeys.AMEYO_AVAILABLE) {
setAutoStatus(this.sessionId);
this.isAgentAvailable = true;
window.postMessage({type: 'onAmeyoAvailabiltyChange', data: true});
}
if (payload?.data?.requestKey === RequestKeys.OMNIQUEUE_SERVICE) {
selectCampaign(this.sessionId, this.userName.toLowerCase(), this.campaignId);
}
if (payload?.data?.requestKey === RequestKeys.SELECT_CAMPAIGN) {
console.log('campaign selected', payload?.data?.response);
autoSelectExtension(this.sessionId, this.userName.toLowerCase());
this.callbacks.onAdapterReady();
this.currentCallState = CALL_STATES.IDLE;
this.callbacks.onAgentAvailabilityChange(true);
window.postMessage({type: 'onAmeyoAvailabiltyChange', data: false},);
}
if (payload?.data?.requestKey === RequestKeys.AMEYO_ON_BREAK) {
setAutoStatus(this.sessionId);
this.isAgentAvailable = false;
this.callbacks.onAgentAvailabilityChange(false);
window.postMessage({type: 'onAmeyoAvailabiltyChange', data: false},);
}
}
_registerMessageListener = async ({data}: GenericObject) => {
if (data?.type === MessagingType.SET_RESPONSE_WITHOUT_CORS) {
this._onListenForCorsBypassResponse(data);
}
if (data?.type === MessagingType.ON_AMEYO_CALL_INCOMING) {
this.callbacks.onCallIncoming(data?.data);
this.currentCallState = CALL_STATES.CALL_INCOMING;
this.currentCallMetadata = {...this.currentCallMetadata, ...data?.data}
}
if (data?.type === MessagingType.ON_AMEYO_CALL_ACCEPTED) {
this.callbacks.onCallConnected(data?.data);
this.currentCallState = CALL_STATES.CALL_CONNECTED;
this.currentCallMetadata = {...this.currentCallMetadata, ...data?.data}
}
if (data?.type === MessagingType.ON_AMEYO_CALL_DISCONNECTED) {
this.callbacks.onCallDisconnected(data?.data);
this.currentCallState = CALL_STATES.CALL_DISCONNECTED;
ameyoHangupUser(this.sessionId, this.currentCallMetadata?.userCRTObjectId);
this.currentCallMetadata = {...this.currentCallMetadata, ...data?.data}
}
if (data?.type === MessagingType.ON_AMEYO_AGENT_ON_BREAK) {
console.log('on availability changedd')
this.isAgentAvailable = false;
this.callbacks.onAgentAvailabilityChange(false);
}
if (data?.type === MessagingType.ON_AMEYO_FORCED_LOGOUT) {
this.callbacks.onForcedLogout()
}
};
registerOnCallIncoming(callback: (callState: StateType) => void) {
console.log('registerOnCallIncoming');
this.callbacks.onCallIncoming = callback;
}
registerOnCallConnected(callback: (callState: StateType) => void) {
console.log('registerOnCallConnected');
this.callbacks.onCallConnected = callback;
}
registerOnCallDisconnected(callback: (callState: StateType) => void) {
console.log('registerOnCallDisconnected');
this.callbacks.onCallDisconnected = callback;
}
registerOnAdapterReady(callback: () => void) {
console.log('registerOnAdapterReady');
this.callbacks.onAdapterReady = callback;
}
registerOnAgentAvailabilityChange(callback: (isAgentAvailable: boolean) => void) {
console.log('registerOnAgentAvailabilityChange');
this.callbacks.onAgentAvailabilityChange = callback;
}
registerOnForcedLogoutListener(callback: () => void) {
console.log('registerOnAgentAvailabilityChange');
this.callbacks.onForcedLogout = callback;
}
acceptCall() {
console.log('acceptCall');
acceptSipCall();
}
rejectCall() {
console.log('rejectCall');
sipHangUp();
}
disposeCall() {
console.log('disposeCall');
ameyoDisposeCall(this.sessionId, this.campaignId, this.currentCallMetadata?.crtObjectId, this.currentCallMetadata?.userCRTObjectId);
}
setOnBreak() {
console.log('setAgentOnBreakk');
setAgentOnBreak(this.sessionId);
}
setAvailable() {
setAgentActive(this.sessionId);
}
muteCall() {
console.log('muteCall');
sipMuteCall();
}
unmuteCall() {
console.log('unmuteCall');
sipUnmuteCall();
}
getAgentAvailability() {
return this.isAgentAvailable;
}
getLatestCallState() {
return this.currentCallState;
}
private _appendTags: () => void = () => {
const script = document.createElement('script');
script.src = 'https://public-assets.np.navi-gi.in/jarvis/sip5ml.js'; // Assuming it's placed in the public folder
script.async=true;
document.head.appendChild(script);
const is_already_appended = document.querySelector('#audio_remote') && document.querySelector('#video_local') && document.querySelector('#video_remote') && document.querySelector('#ringtone') && document.querySelector('#ringbacktone') && document.querySelector('#dtmfTone');
if (is_already_appended) {
console.log('tags already appended skipping')
return;
}
type ElementAttributes = {
id?: string;
className?: string;
width?: string;
height?: string;
autoplay?: boolean;
muted?: boolean;
loop?: boolean;
src?: string;
style?: Partial<CSSStyleDeclaration>;
[key: string]: any;
};
function createElement(
tag: keyof HTMLElementTagNameMap,
attributes: ElementAttributes = {},
parent: HTMLElement = document.body
): HTMLElement {
const element = document.createElement(tag);
Object.keys(attributes).forEach((attr) => {
if (attr === 'style' && attributes.style) {
Object.assign(element.style, attributes.style);
} else if (attr in element) {
(element as any)[attr] = attributes[attr];
} else {
element.setAttribute(attr, attributes[attr]);
}
});
parent.appendChild(element);
return element;
}
createElement('audio', {
id: 'audio_remote',
autoplay: true,
});
createElement('video', {
className: 'video',
width: '100%',
height: '100%',
id: 'video_local',
autoplay: true,
muted: true,
style: {
opacity: '0',
display: 'none',
backgroundColor: '#000000',
webkitTransitionProperty: 'opacity',
webkitTransitionDuration: '2s',
},
});
createElement('video', {
className: 'video',
width: '100%',
height: '100%',
id: 'video_remote',
autoplay: true,
style: {
display: 'none',
opacity: '0',
backgroundColor: '#000000',
webkitTransitionProperty: 'opacity',
webkitTransitionDuration: '2s',
},
});
createElement('audio', {
id: 'ringtone',
loop: true,
src: 'https://public-assets.np.navi-gi.in/jarvis/ringtone.wav',
});
createElement('audio', {
id: 'ringbacktone',
loop: true,
src: 'https://public-assets.np.navi-gi.in/jarvis/ringbacktone.wav',
});
createElement('audio', {
id: 'dtmfTone',
src: 'https://public-assets.np.navi-gi.in/jarvis/dtmf.wav',
});
const onSipSetupReadyEvent = new CustomEvent('onSipSetupReady', {
detail: { message: 'Custom page loaded event triggered' }
});
script.onload = ()=>{
window.dispatchEvent(onSipSetupReadyEvent)
}
};
}
export default AmeyoAdapter;