UNPKG

@expertflow/sdk-for-customer-facing-channels

Version:

NPM Package to install SDK for Chat, WebRTC Audio, and Video Calls that will land on Cisco Contact Center Agents handling calls using Cisco Jabber or similar in any node-based application.

1,448 lines 207 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.sendInvite = void 0; exports.include = include; exports.widgetConfigs = widgetConfigs; exports.getPreChatForm = getPreChatForm; exports.formValidation = formValidation; exports.establishConnection = establishConnection; exports.eventListeners = eventListeners; exports.chatRequest = chatRequest; exports.voiceRequest = voiceRequest; exports.sendMessage = sendMessage; exports.chatEnd = chatEnd; exports.resumeChat = resumeChat; exports.sendJoinConversation = sendJoinConversation; exports.uploadToFileEngine = uploadToFileEngine; exports.setConversationData = setConversationData; exports.setConversationDataByCustomerIdentifier = setConversationDataByCustomerIdentifier; exports.getConversationDataByCustomerIdentifier = getConversationDataByCustomerIdentifier; exports.getConversationData = getConversationData; exports.callbackRequest = callbackRequest; exports.webhookNotifications = webhookNotifications; exports.dialCall = dialCall; exports.closeVideo = closeVideo; exports.terminateCurrentSession = terminateCurrentSession; exports.closeSession = closeSession; exports.audioControl = audioControl; exports.videoControl = videoControl; exports.screenControl = screenControl; exports.authenticateRequest = authenticateRequest; exports.postMessages = postMessages; exports.sendChatMessage = sendChatMessage; exports.getBrowserInfo = getBrowserInfo; exports.getCalendarId = getCalendarId; exports.getCalendarEvents = getCalendarEvents; const socket_io_client_1 = require("socket.io-client"); let socket; let wssServerIp; let uriServerIp; let diallingURI; let sipExtension; let extensionPassword; let enable_sip_logs; let enableLogs; let wssPort; let IP; let dialerURI; let sipPassword; let ext; let session; let mediaElement; let mediaLocal; let userAgent; let ex; var remote_stream; let remoteVideo; let register = false; let displayMediaStrea; let toggleVideo; let video; var audio; let screen; let mediaAcquire = "end"; let endCallBtn = false; var mySessionDescriptionHandlerFactory = null; let dialedNumber; let callVariableArray = []; // Initialize an object to keep track of function locks const functionLocks = {}; let canCallFunction = true; let callEndDialogId; let endCall = false; let calls = []; let consultSession; let registerer; let againRegister = false; let sessionall = null; let remoteSession = null; let loginid = null; let wrapUpEnabler = null; let agentInfo = false; let callbackFunction = null; let remoteStream; let localStream; let dialogStatedata = null; let invitedata = null; let outBoundDialingData = null; let consultCalldata = null; let sipConfigs = {}; let isConversationActive = false; const dialogStatedata1 = { event: "dialogState", response: { loginId: null, dialog: { id: null, fromAddress: null, dialedNumber: null, customerNumber: null, serviceIdentifer: null, dnis: null, callType: null, ani: null, wrapUpReason: null, callEndReason: null, queueName: null, queueType: null, associatedDialogUri: null, secondaryId: null, participants: [ { actions: { action: ["TRANSFER_SST", "HOLD", "SEND_DTMF", "DROP"], }, mediaAddress: null, mediaAddressType: "SIP.js/0.21.2-CTI/Expertflow", startTime: null, state: null, stateCause: null, stateChangeTime: null, mute: false, }, ], callVariables: { CallVariable: [], }, state: null, isCallAlreadyActive: false, callbackNumber: null, outboundClassification: null, scheduledCallbackInfo: null, isCallEnded: 0, eventType: "PUT", mediaType: null, callOriginator: "webrtc", }, }, }; const outBoundDialingData12 = { event: "outboundDialing", response: { loginid: null, dialog: { id: null, ani: null, customerNumber: null, associatedDialogUri: null, callbackNumber: null, outboundClassification: null, scheduledCallbackInfo: null, isCallEnded: 0, eventType: "PUT", callType: null, queueName: null, queueType: null, dialedNumber: null, dnis: null, secondaryId: null, state: "INITIATING", isCallAlreadyActive: false, wrapUpReason: null, wrapUpItems: null, callEndReason: null, fromAddress: null, callVariables: { CallVariable: [], }, participants: [ { actions: { action: ["TRANSFER_SST", "HOLD", "SEND_DTMF", "DROP"], }, mediaAddress: null, mediaAddressType: "SIP.js/0.21.2-CTI/Expertflow", startTime: null, state: null, stateCause: null, stateChangeTime: null, mute: false, }, ], mediaType: null, callOriginator: "webrtc", }, }, }; const consultCalldata1 = { event: "ConsultCall", response: { loginid: null, dialog: { id: null, ani: null, customerNumber: null, associatedDialogUri: null, callbackNumber: null, outboundClassification: null, scheduledCallbackInfo: null, isCallEnded: 0, eventType: "PUT", callType: null, queueName: null, queueType: null, dialedNumber: null, dnis: null, serviceIdentifier: null, secondaryId: null, state: "INITIATING", isCallAlreadyActive: false, wrapUpReason: null, wrapUpItems: null, callEndReason: null, fromAddress: null, callVariables: { CallVariable: [], }, participants: [ { actions: { action: ["TRANSFER_SST", "HOLD", "SEND_DTMF", "DROP"], }, mediaAddress: null, mediaAddressType: "SIP.js/0.21.2-CTI/Expertflow", startTime: null, state: null, stateCause: null, stateChangeTime: null, mute: false, }, ], mediaType: null, callOriginator: "webrtc", }, }, }; const invitedata1 = { event: "newInboundCall", response: { loginId: null, dialog: { id: null, ani: null, customerNumber: null, associatedDialogUri: null, callbackNumber: null, outboundClassification: null, scheduledCallbackInfo: null, isCallEnded: 0, eventType: "PUT", callType: null, queueName: null, queueType: null, dialedNumber: null, dnis: null, serviceIdentifier: null, secondaryId: null, state: "ALERTING", isCallAlreadyActive: false, wrapUpReason: null, wrapUpItems: null, callEndReason: null, fromAddress: null, callVariables: { CallVariable: [], }, participants: [ { actions: { action: ["ANSWER"], }, mediaAddress: null, mediaAddressType: "SIP.js/0.21.2-CTI/Expertflow", startTime: null, state: null, stateCause: null, stateChangeTime: null, mute: false, }, ], mediaType: null, callOriginator: "webrtc", }, }, }; var mediaConversion = { event: "mediaConversion", status: null, // error , success loginid: "", dialog: { id: null, eventRequest: null, //local , remote stream: null, // video , screenshare streamStatus: null, //on , off errorReason: null, timeStamp: null, }, }; var inviteDelegate = { onAck(ack) { console.log("onAck MESSAGE ******** ", ack); }, onBye(bye) { // need to discuss this console.log("onBye MESSAGE ******** ", bye); // event = ConsultCall, dialogState , newInboundCall if (dialogStatedata && dialogStatedata.event && dialogStatedata.event === "ConsultCall") { const match = bye.incomingByeRequest.message.data.match(/text="([^"]+)"/); if (match && match[1]) { dialogStatedata.response.dialog.callEndReason = match[1]; } } if (invitedata && invitedata.event && invitedata.event === "ConsultCall") { const match = bye.incomingByeRequest.message.data.match(/text="([^"]+)"/); if (match && match[1]) { invitedata.response.dialog.callEndReason = match[1]; } } if (dialogStatedata && dialogStatedata.event && dialogStatedata.event === "dialogState") { const match = bye.incomingByeRequest.message.data.match(/text="([^"]+)"/); if (match && match[1]) { dialogStatedata.response.dialog.callEndReason = match[1]; } } if (invitedata && invitedata.event && invitedata.event === "dialogState") { const match = bye.incomingByeRequest.message.data.match(/text="([^"]+)"/); if (match && match[1]) { invitedata.response.dialog.callEndReason = match[1]; } } }, }; function include(file) { const script = document.createElement("script"); script.src = file; script.type = "text/javascript"; script.defer = true; const head = document === null || document === void 0 ? void 0 : document.getElementsByTagName("head").item(0); if (head) { head.appendChild(script); } } /** * * @returns */ const getDynamicExt = () => new Promise((resolve, reject) => { resolve(sipExtension); }); function widgetConfigs(ccmUrl, widgetIdentifier, callback) { fetch(`${ccmUrl}/widget-configs/${widgetIdentifier}`) .then((response) => response.json()) .then((data) => { var _a, _b, _c, _d, _e, _f; callback(data); const webRtc = data.webRtc; if (webRtc) { wssServerIp = (_a = webRtc.wssFs) !== null && _a !== void 0 ? _a : "defaultWssFsValue"; // Add a fallback value if undefined uriServerIp = (_b = webRtc.uriFs) !== null && _b !== void 0 ? _b : "defaultUriFsValue"; diallingURI = (_c = webRtc.diallingUri) !== null && _c !== void 0 ? _c : "defaultDiallingUri"; sipExtension = (_d = webRtc.sipExtension) !== null && _d !== void 0 ? _d : "defaultSipExtension"; extensionPassword = (_e = webRtc.extensionPassword) !== null && _e !== void 0 ? _e : "defaultPassword"; enable_sip_logs = (_f = webRtc.enabledSipLogs) !== null && _f !== void 0 ? _f : false; enableLogs = enable_sip_logs; IP = uriServerIp; dialerURI = "sip:" + diallingURI + "@" + uriServerIp; sipPassword = extensionPassword; } else { console.error("webRtc configuration is missing in the response."); } }); } function getPreChatForm(formUrl, formId, callback) { fetch(`${formUrl}/forms/${formId}`) .then((response) => response.json()) .then((data) => { callback(data); }); } function formValidation(formUrl, callback) { fetch(`${formUrl}/formValidation`) .then((response) => response.json()) .then((data) => { callback(data); }); } /** * Function to Establish Connection * Two Parameters * 1- Customer Data * 2- Call Function of socketEventListeners() * @param {*} serviceIdentifier * @param {*} channelCustomerIdentifier * @param {*} callback */ function establishConnection(socket_url, serviceIdentifier, channelCustomerIdentifier, callback) { try { if (socket !== undefined && socket.connected) { console.log("Resuming Existing Connection"); eventListeners((data) => { callback(data); }); } else { if (socket_url !== "") { console.log("Starting New Connection"); const origin = new URL(socket_url).origin; const path = new URL(socket_url).pathname; socket = (0, socket_io_client_1.io)(origin, { path: path == "/" ? "" : path + "/socket.io", auth: { serviceIdentifier: serviceIdentifier, channelCustomerIdentifier: channelCustomerIdentifier, }, }); eventListeners((data) => { callback(data); }); } } } catch (error) { callback(error); } } /** * Socket EventListener Function * 1- Socket Connection Event * 2- Socket Discount Event * 3- Socket Connection Error Event * 4- Socket Message Arrived Event * 5- Socket End Conversation Event * 6- Socket Error * 7- Channel Session Started Event * @param {*} callback */ function eventListeners(callback) { socket === null || socket === void 0 ? void 0 : socket.on("connect", () => { if ((socket === null || socket === void 0 ? void 0 : socket.id) !== undefined) { console.log(`you are connected with socket:`, socket); const error = localStorage.getItem("widget-error"); if (error) { callback({ type: "SOCKET_RECONNECTED", data: socket }); } else { callback({ type: "SOCKET_CONNECTED", data: socket }); } } }); socket === null || socket === void 0 ? void 0 : socket.on("CHANNEL_SESSION_STARTED", (data) => { console.log(`Channel Session Started Data: `, data); const gtmObject = { type: "gtmDataLayer", data: { type: "CHAT STARTED", data: { customerIdentifier: data.header.channelData.channelCustomerIdentifier, serviceIdentifier: data.header.channelData.serviceIdentifier, }, }, }; window.parent.postMessage(gtmObject, "*"); callback({ type: "CHANNEL_SESSION_STARTED", data: data }); }); socket === null || socket === void 0 ? void 0 : socket.on("MESSAGE_RECEIVED", (message) => { console.log(`MESSAGE_RECEIVED received: `, message); callback({ type: "MESSAGE_RECEIVED", data: message }); }); socket === null || socket === void 0 ? void 0 : socket.on("disconnect", (reason) => { console.error(`Connection lost with the server: `, reason); // const gtmObject = { // type: "gtmDataLayer", // data: { // type: "CHAT ENDED", // data:reason // }, // }; // window.parent.postMessage(gtmObject, "*"); callback({ type: "SOCKET_DISCONNECTED", data: reason }); }); socket === null || socket === void 0 ? void 0 : socket.on("connect_error", (error) => { console.log(`unable to establish connection with the server: `, error.message); localStorage.setItem("widget-error", "1"); callback({ type: "CONNECT_ERROR", data: error }); }); socket === null || socket === void 0 ? void 0 : socket.on("CHAT_ENDED", (data) => { console.log(`CHAT_ENDED received: `, data); callback({ type: "CHAT_ENDED", data: data }); socket === null || socket === void 0 ? void 0 : socket.disconnect(); }); socket === null || socket === void 0 ? void 0 : socket.on("ERRORS", (data) => { console.error(`ERRORS received: `, data); callback({ type: "ERRORS", data: data }); }); } function chatRequest(data) { try { if (data) { const additionalAttributesData = []; const webChannelDataObj = { key: "WebChannelData", type: "WebChannelData", value: { browserDeviceInfo: data.data.browserDeviceInfo, queue: data.data.queue, locale: data.data.locale, formData: data.data.formData, }, }; additionalAttributesData.push(webChannelDataObj); const obj = { channelCustomerIdentifier: data.data.channelCustomerIdentifier, serviceIdentifier: data.data.serviceIdentifier, additionalAttributes: additionalAttributesData, }; if (socket) { socket.emit("CHAT_REQUESTED", obj); console.log(`SEND CHAT_REQUESTED DATA:`, obj); } } } catch (error) { throw error; } } function voiceRequest(data) { try { if (data) { const additionalAttributesData = []; const webChannelDataObj = { key: "WebChannelData", type: "WebChannelData", value: { browserDeviceInfo: data.data.browserDeviceInfo, queue: data.data.queue, locale: data.data.locale, formData: data.data.formData, }, }; additionalAttributesData.push(webChannelDataObj); const obj = { channelCustomerIdentifier: data.data.channelCustomerIdentifier, serviceIdentifier: data.data.serviceIdentifier, additionalAttributes: additionalAttributesData, }; if (socket) { socket.emit("VOICE_REQUESTED", obj); console.log(`SEND VOICE_REQUESTED DATA:`, obj); } } } catch (error) { throw error; } } function sendMessage(message, dialogId) { var destination = 0; var index = getCallIndex(dialogId); var sessionall = null; if (index !== -1) { sessionall = calls[index]; } if (!sessionall) { return; } //callType = "OUT" means its a Customer Call and we are on Customer Widget if (sessionall.response.dialog.callType == "OUT") { destination = sessionall.additionalDetail.agentExt; } else { if (typeof sessionall.session.incomingInviteRequest !== 'undefined') { destination = sessionall.session.incomingInviteRequest.message.from.uri.normal.user; } else if (typeof sessionall.session.outgoingInviteRequest !== 'undefined') { destination = sessionall.session.outgoingInviteRequest.message.to.uri.normal.user; } } const message_targetUri_value = new SIP.URI("sip", destination, sipConfigs.uriFs); message = new SIP.Messager(userAgent, message_targetUri_value, JSON.stringify(message)); message.message(); } function chatEnd(data) { // Chat Disconnection Socket Event if (socket) { socket.emit("CHAT_ENDED", data); } } /** * * @param {*} data */ function resumeChat(data, callback) { if (socket) { const gtmObject = { type: "gtmDataLayer", data: { type: "BROWSER NAVIGATED", data: { customerIdentifier: data.channelCustomerIdentifier, serviceIdentifier: data.serviceIdentifier, }, }, }; console.log(data, "Resume Chat Before Emit Console.log"); socket.emit("CHAT_RESUMED", data, (res) => { if (res) { console.log(res, "resume chat response in sdk."); callback(res); } }); } } /** * * @param {*} data */ function sendJoinConversation(data) { socket === null || socket === void 0 ? void 0 : socket.emit("joinConversation", data, (res) => { console.log("[sendJoinConversation] ", data); return res; }); } /** * File Upload to File Engine Function * @param {*} formData * @param {*} callback */ function uploadToFileEngine(fileServerUrl, formData, callback) { fetch(`${fileServerUrl}/api/uploadFileStream`, { method: "POST", body: formData, }) .then((response) => response.json()) .then((result) => { console.log("Success: ", result); callback(result); }) .catch((error) => { console.error("Error: ", error); callback(error); }); } /** * Set Conversation Data Api */ function setConversationData(url, conversationId, data) { return __awaiter(this, void 0, void 0, function* () { const response = yield fetch(`${url}/${conversationId}/conversation-data`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(data), }); return response; }); } /** * Set Conversation Data Api By Customer Channel Identifier */ function setConversationDataByCustomerIdentifier(url, channelIdentifier, data, callback) { return __awaiter(this, void 0, void 0, function* () { try { const response = yield fetch(`${url}/${channelIdentifier}/conversation-data-by-identifier`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(data), }); if (response.status === 403) { console.error("Forbidden: The server returned a 403 Forbidden response."); callback(response); } if (!response.ok) { console.error("Network response was not ok"); callback(response); } const result = yield response.json(); console.log("Success:", result); callback(result); } catch (error) { console.error("Error:", error); callback(error); // Re-throw the error for the caller to handle } }); } /** * Get Conversation Data Api By Customer Identifier */ function getConversationDataByCustomerIdentifier(url, channelIdentifier, callback) { return __awaiter(this, void 0, void 0, function* () { try { const response = yield fetch(`${url}/get/${channelIdentifier}`, { method: "GET", // Specify the HTTP method as GET headers: { "Content-Type": "application/json", // Set appropriate headers if needed }, }); if (response.status === 403) { console.error("Forbidden: The server returned a 403 Forbidden response."); callback(response); } else if (!response.ok) { console.error(`Failed to fetch data from ${url}/get/${channelIdentifier}: ${response.status} ${response.statusText}`); callback(response); } else { const data = yield response.json(); callback(data); } } catch (error) { console.error("Error:", error); callback(error); // Re-throw the error for the caller to handle } }); } /** * Get Conversation Data Api */ function getConversationData(url, conversationId) { return __awaiter(this, void 0, void 0, function* () { const response = yield fetch(`${url}/${conversationId}/conversation-data`); if (!response.ok) { throw new Error(`Failed to fetch data from ${url}/${conversationId}/conversation-data: ${response.status} ${response.statusText}`); } const data = yield response.json(); return data; }); } /** * Callback Request To ECM * @param {*} payload * @param {*} url */ function callbackRequest(url, payload, callback) { try { // Make an API Call fetch(`${url}`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(payload), }) .then((response) => response.json()) .then((data) => { // Handle the API response here console.log("API response:", data); callback(data); }) .catch((error) => { // Handle any errors that occur during the API call console.error("API Call Error", error); callback(error); }); } catch (error) { console.error("API Function Error", error); callback(error); } } /** * Webhook Notifications Functions * @param {*} data */ function webhookNotifications(webhookUrl, additionalData, data) { // Constructing the message dynamically based on the keys and values in the data object let imageUrl = modifyUrlPath(additionalData.agent_url, additionalData.icon); let formattedText = ""; for (const [key, value] of Object.entries(data)) { formattedText += `${capitalizeFirstLetter(key)}: ${value ? value : "N/A"}\n`; } let newAgentUrl = modifyUrlPath(additionalData.agent_url, "/unified-agent/"); formattedText += `To respond: <a href='${newAgentUrl}'>Click here</a>\n`; let messageObj = { cards: [ { header: { title: `${data.first_name ? data.first_name : "Customer"} started a new chat`, imageUrl: imageUrl, imageStyle: "IMAGE", }, sections: [ { widgets: [ { textParagraph: { text: formattedText, }, }, ], }, ], }, ], }; fetch(`${webhookUrl}`, { method: "POST", body: JSON.stringify(messageObj), // Formatting as a JSON object for Google Workspace webhook headers: { "Content-Type": "application/json; charset=UTF-8", }, }) .then((response) => { if (!response.ok) { return response.json().then((err) => Promise.reject(err)); } return response.json(); }) .then((result) => { console.log("Success: ", result); }) .catch((error) => { console.error("Error: ", error); }); } function modifyUrlPath(originalUrl, newPath) { try { const url = new URL(originalUrl); url.pathname = newPath; return url.toString(); } catch (error) { console.error("Invalid URL:", error); return null; } } function capitalizeFirstLetter(string) { return string.charAt(0).toUpperCase() + string.slice(1).replace(/_/g, " "); } /** * * @param {*} eventsCallback */ function dialCall(eventsCallback) { getDynamicExt() .then((extension) => { ext = extension; console.log(wssServerIp, "ip at call time"); userAgent = new SIP.UA({ uri: extension + "@" + uriServerIp, transportOptions: { wsServers: wssServerIp, traceSip: true }, authorizationUser: extension, password: extensionPassword, log: { builtinEnabled: enableLogs, level: 3, }, register: true, }); userAgent.start(); if (typeof eventsCallback === "function") { let event = { event: "get_dynamic_ext", response: extension, cause: "", }; eventsCallback(event); } userAgent.on("unregistered", function (response, cause) { register = false; if (typeof eventsCallback === "function") { let event = { event: "unregistered", response: response, cause: cause, }; eventsCallback(event); } }); userAgent.on("registered", function () { register = true; if (typeof eventsCallback === "function") { let event = { event: "registered", response: "", cause: "", }; eventsCallback(event); } }); userAgent.on("registrationFailed", function (response, cause) { if (typeof eventsCallback === "function") { let event = { event: "registrationFailed", response: response, cause: cause, }; eventsCallback(event); } }); }) .catch((rej) => { if (typeof eventsCallback === "function") { let event = { event: "get_dynamic_ext", response: "", cause: rej, }; eventsCallback(event); } }); } /** * * @param {*} mediaType * @param {*} videoName * @param {*} videoLocal * @param {*} userData * @param {*} eventsCallback * @returns */ const sendInvite = (mediaType, videoName, videoLocal, userData, eventsCallback) => { return new Promise((resolve, reject) => { let mediaConstraints = { audio: true, video: true }; toggleVideo = "web_cam"; mediaElement = document.getElementById(videoName); if (videoLocal === "") { mediaLocal = ""; } else { mediaLocal = document.getElementById(videoLocal); } audio = "true"; if (mediaType === "audio") { mediaConstraints = { audio: true, video: false }; video = "false"; } else { mediaConstraints = { audio: true, video: true }; video = "true"; } screen = "false"; console.log("invite function has been triggered"); if (userData !== null) { var extraHeaderString = []; var index = 0; for (const key in userData) { if (typeof userData[key] === "string") { var keyvalue = userData[key].trim(); extraHeaderString.push("X-variable" + index + ":" + key + "|" + keyvalue); index++; } else { console.warn(`Value for key ${key} is not a string and will be skipped.`); } } } session = userAgent.invite("sip:" + diallingURI + "@" + uriServerIp, { sessionDescriptionHandlerOptions: { constraints: mediaConstraints, }, extraHeaders: extraHeaderString, }); if (typeof eventsCallback === "function") { let event = { event: "Channel Creating", response: "", cause: "", }; eventsCallback(event); } session.on("accepted", function () { // Assumes you have a media element on the DOM const remoteStream = new MediaStream(); if (video === "false") { console.log("closing video"); } session.sessionDescriptionHandler.peerConnection .getReceivers() .forEach((receiver) => { if (receiver.track) { console.log(receiver.track); remoteStream.addTrack(receiver.track); } }); mediaElement.srcObject = remoteStream; if (mediaLocal !== "") { const localStream = new MediaStream(); session.sessionDescriptionHandler.peerConnection .getSenders() .forEach((sender) => { if (sender.track.kind === "video") { console.log(sender.track); localStream.addTrack(sender.track); } }); mediaLocal.srcObject = localStream; } if (typeof eventsCallback === "function") { let event = { event: "session-accepted", response: "", cause: "", }; eventsCallback(event); } }); session.on("progress", function (response) { if (typeof eventsCallback === "function") { let event = { event: "session-progress", response: response, cause: "", }; eventsCallback(event); } }); session.on("rejected", function (response, cause) { if (typeof eventsCallback === "function") { let event = { event: "session-rejected", response: response, cause: cause, }; eventsCallback(event); } }); session.on("failed", function (response, cause) { if (typeof eventsCallback === "function") { let event = { event: "session-failed", response: response, cause: cause, }; eventsCallback(event); } var options = { all: true, }; userAgent.unregister(options); }); session.on("terminated", function (message, cause) { closeSession(eventsCallback); if (typeof eventsCallback === "function") { let event = { event: "session-terminated", response: message, cause: cause, }; eventsCallback(event); } }); session.on("bye", function (request) { if (typeof eventsCallback === "function") { let event = { event: "session-bye", response: request, cause: "", }; eventsCallback(event); } }); session.on("iceConnectionDisconnected", function () { if (typeof eventsCallback === "function") { let event = { event: "session-iceConnectionDisconnected", response: "request", cause: "", }; eventsCallback(event); } }); session.on("SessionDescriptionHandler-created", function () { session.sessionDescriptionHandler.on("getDescription", function (sdpWrapper) { if (typeof eventsCallback === "function") { let event = { event: "session-SessionDescriptionHandler-getDescription", response: sdpWrapper, cause: "", }; eventsCallback(event); } }); session.sessionDescriptionHandler.on("Media acquire start", function () { mediaAcquire = "start"; if (typeof eventsCallback === "function") { let event = { event: "session-SessionDescriptionHandler-Media acquire start", response: "", cause: "", }; eventsCallback(event); } }); session.sessionDescriptionHandler.on("Media acquire end", function () { if (endCallBtn === true) { terminateCurrentSession(() => { eventsCallback(); }); endCallBtn = false; } mediaAcquire = "end"; if (typeof eventsCallback === "function") { let event = { event: "session-SessionDescriptionHandler-Media acquire end", response: "", cause: "", }; eventsCallback(event); } }); if (typeof eventsCallback === "function") { let event = { event: "session-SessionDescriptionHandler-created", response: "", cause: "", }; eventsCallback(event); } }); resolve("successful"); }); }; exports.sendInvite = sendInvite; /** * Close Video Function */ function closeVideo() { let pc = session.sessionDescriptionHandler.peerConnection; pc.getSenders().find(function (s) { if (s.track.readyState == "live" && s.track.kind === "video") { s.track.stop(); } }); } /** * * @param {*} eventsCallback */ /** * * @param {*} eventsCallback */ function terminateCurrentSession(eventsCallback) { promise1 .then((value) => { userAgent.stop(); }) .then(function () { return userAgent.transport.disconnect(); }) .then(function () { var options = { all: true, }; return userAgent.unregister(options); }) .then(function () { if (typeof eventsCallback === "function") { let event = { event: "session-session_ended", response: "userAgent unregistered", cause: "", }; eventsCallback(event); } }) .catch(function (error) { if (typeof eventsCallback === "function") { let event = { event: "session-termination-failed", response: "An error occurred during session termination", cause: error.message, }; eventsCallback(event); } }); } /** * Promise * @param {resolve , reject} */ const promise1 = new Promise((resolve, reject) => { resolve("Success!"); }); /** * * * @param {*} eventsCallback */ function closeSession(eventsCallback) { if (mediaAcquire === "start") { endCallBtn = true; if (typeof eventsCallback === "function") { let event = { event: "session-terminated", response: "Session terminated due to media acquire start", cause: "", }; eventsCallback(event); } } else { terminateCurrentSession(eventsCallback); } } /** * Audio Call Control */ function audioControl() { let pc = session.sessionDescriptionHandler.peerConnection; if (audio === "true") { pc.getSenders().find(function (s) { console.log(s.track.kind + "--------------" + s.track.readyState); if (s.track.readyState == "live" && s.track.kind === "audio") { s.track.stop(); } }); audio = "false"; } else { navigator.mediaDevices .getUserMedia({ audio: true, }) .then(function (stream) { let audioTrack = stream.getAudioTracks()[0]; var sender = pc.getSenders().find(function (s) { return s.track.kind == audioTrack.kind; }); console.log("found sender:", sender); sender.replaceTrack(audioTrack); }) .catch(function (err) { console.error("Error happens:", err); }); audio = "true"; } } /** * Video Call Control */ function videoControl() { let pc = session.sessionDescriptionHandler.peerConnection; if (video === "true") { pc.getSenders().find(function (s) { console.log(s.track.kind + "--------------" + s.track.readyState); if (s.track.readyState == "live" && s.track.kind === "video") { s.track.stop(); } }); video = "false"; } else { navigator.mediaDevices .getUserMedia({ video: true, }) .then(function (stream) { let videoTrack = stream.getVideoTracks()[0]; var sender = pc.getSenders().find(function (s) { return s.track.kind == videoTrack.kind; }); console.log("found sender:", sender); sender.replaceTrack(videoTrack); mediaLocal.srcObject = stream; mediaLocal.play(); }) .catch(function (err) { console.error("Error happens:", err); }); video = "true"; } } /** * ScreenControl */ function screenControl() { if (screen === "false") { screen = "true"; } else { } } /** * Webhook Notifications Functions * @param {*} data */ function authenticateRequest(authenticatorUrl, authData, callback) { console.log("authenticateRequest: in sdk function:", JSON.stringify(authData)); fetch(`${authenticatorUrl}/verifySecureLink`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(authData), }) .then((response) => __awaiter(this, void 0, void 0, function* () { const contentType = response.headers.get("content-type"); if (!response.ok) { let errorMessage = "Network response was not ok"; if (response.status === 400) { // Handle the 400 Bad Request error here const errorData = yield response.json(); errorMessage = "400 Bad Request"; // Custom handling for the error response callback({ error: true, message: errorMessage, data: errorData }); throw new Error(errorMessage); // Stop the promise chain } else if (response.status === 500) { errorMessage = "500 Internal Server Error"; } callback({ error: true, message: errorMessage }); throw new Error(errorMessage); // Stop the promise chain } if (contentType && contentType.includes("application/json")) { return response.json(); } else { return response.text(); // Handle plain text response } })) .then((result) => { // This will not be executed if an error was thrown in the previous block // console.log('Authentication Api Success: ', result); // Check for the presence of reasonCode and message fields if ("reasonCode" in result && "message" in result) { console.log("Authentication Api Error: ", result); callback({ status: 400, error: true, data: result, message: "Something went wrong!!", }); } else { console.log("Authentication Api Success: ", result); callback({ status: 200, error: false, data: result, message: "Authentication Successful!!!", }); } }) .catch((error) => { // If an error is thrown in any of the previous blocks, it will be caught here console.error("Authentication Api Error: ", error); // Optionally, call the callback with an error if not already done // callback({ error: true, message: 'Something went wrong, please try again!' }); // Since we're handling specific errors earlier, this catch might only be for unexpected errors }); } function postMessages(obj) { var _a; console.log("========> coming object", obj); let sipConfigs = {}; // Assuming sipConfigs is declared elsewhere if (Object.keys(sipConfigs).length === 0 && ((_a = obj === null || obj === void 0 ? void 0 : obj.parameter) === null || _a === void 0 ? void 0 : _a.authData)) { sipConfigs = obj.parameter.authData; } else { sipConfigs = obj.parameter.sipConfig; } console.log("=======>sip configs", sipConfigs); switch (obj.action) { case "login": if (typeof obj.parameter.clientCallbackFunction === "function") { if (sipConfigs.uriFs !== null && sipConfigs.uriFs !== undefined) { connect_useragent(obj.parameter.extension, sipConfigs.uriFs, sipConfigs.extensionPassword, sipConfigs.wssFs, sipConfigs.enabledSipLogs, obj.parameter.clientCallbackFunction); callbackFunction = obj.parameter.clientCallbackFunction; // Assuming callbackFunction is declared elsewhere } else { error("invalidState", obj.parameter.extension, "Server configurations not fetched ", obj.parameter.clientCallbackFunction); } } break; case "logout": loader3(obj.parameter.clientCallbackFunction); break; case "makeCall": initiate_call(obj.parameter.calledNumber, obj.parameter.Destination_Number, obj.parameter.callType, obj.parameter.authData, obj.parameter.clientCallbackFunction, "OUT"); break; case "SST": blind_transfer(obj.parameter.numberToTransfer, obj.parameter.clientCallbackFunction, obj.parameter.dialogId); break; case "SST_Queue": blind_transfer_queue(obj.parameter.numberToTransfer, obj.parameter.queue, obj.parameter.queueType, obj.parameter.clientCallbackFunction, obj.parameter.dialogId); break; case "makeConsult": makeConsultCall(obj.parameter.numberToConsult, obj.parameter.clientCallbackFunction); break; case "makeConsultQueue": makeConsultCall_queue(obj.parameter.numberToTransfer, obj.parameter.queue, obj.parameter.queueType, obj.parameter.clientCallbackFunction); // console.log('Freeswitch do not support makeConsult currently'); break; case "consultTransfer": makeConsultTransferCall(obj.parameter.clientCallbackFunction); break; case "silentMonitor": console.log("Freeswitch do not support silentMonitor currently"); break; case "answerCall": respond_call(obj.parameter.clientCallbackFunction, obj.parameter.dialogId, obj.parameter.answerCalltype); break; case "releaseCall": terminate_call(obj.parameter.dialogId); break; case "rejectCall": console.log("Freeswitch do not support rejectCall currently"); break; case "closeCall": console.log("Freeswitch do not support closeCall currently"); break; case "end_call": console.log(obj); break; case "holdCall": phone_hold(obj.parameter.clientCallbackFunction, obj.parameter.dialogId); break; case "retrieveCall": phone_unhold(obj.parameter.clientCallbackFunction, obj.parameter.dialogId); break; case "mute_call": phone_mute(obj.parameter.clientCallbackFunction, obj.parameter.dialogId); break; case "unmute_call": phone_unmute(obj.parameter.clientCallbackFunction, obj.parameter.dialogId); break; case "conferenceCall": console.log("Freeswitch do not support con