"use strict";
import {XMPPService} from "../XMPPService";
import {XMPPUTils} from "../../common/XMPPUtils";
//const Conversation = require("../../common/models/Conversation");
//const Call = require("../../common/models/Call");
import {Call} from "../../common/models/Call";
import {getJsonFromXML, logEntryExit} from "../../common/Utils";
//const config = require("../../config/config");
import {config} from "../../config/config";
import {GenericHandler} from "./GenericHandler";
export {};
const Utils = require("../../common/Utils");
const NameUpdatePrio = require("../../common/models/Contact").NameUpdatePrio;
const xml = require("@xmpp/xml");
const PromiseQueue = require("../../common/promiseQueue");
const prettydata = require("../pretty-data").pd;
const LOG_ID = "XMPP/HNDL/TEL - ";
/*********************************************************************/
/** PRIVATE CONSTRUCTOR **/
/*********************************************************************/
const CallFailureLabels = {
"DESTNOTOBTAINABLE": "outOfService",
"DONOTDISTURB": "dnd",
"TRUNKSBUSY": "trunksbusy"
};
@logEntryExit(LOG_ID)
class TelephonyEventHandler extends GenericHandler {
public MESSAGE: any;
public IQ_RESULT: any;
public IQ_ERROR: any;
public telephonyService: any;
public contactService: any;
public promiseQueue: any;
public _profiles: any;
public xmppUtils: XMPPUTils;
/*public onIqResultReceived: any;
public onIqGetPbxAgentStatusReceived: any;
public onMessageReceived: any;
public onInitiatedEvent: any;
public onOriginatedEvent: any;
public getCall: any;
public onDeliveredEvent: any;
public onEstablishedEvent: any;
public onRetrieveCallEvent: any;
public onClearCallEvent: any;
public onHeldEvent: any;
public onQueuedEvent: any;
public onDivertedEvent: any;
public onTransferEvent: any;
public getOrCreateCall: any;
public onConferenceEvent: any;
public onVoiceMessageEvent: any;
public onUpDateCallEvent: any;
public onFailCallEvent: any;
public onCallForwardedEvent: any;
public onNomadicStatusEvent: any;
public createConferenceCall: any;
*/
static getClassName(){ return 'TelephonyEventHandler'; }
getClassName(){ return TelephonyEventHandler.getClassName(); }
static getAccessorName(){ return 'telephonyevent'; }
getAccessorName(){ return TelephonyEventHandler.getAccessorName(); }
constructor(xmppService : XMPPService, telephonyService, contactService, profileService) {
super(xmppService);
let that = this;
this.MESSAGE = "jabber:client.message";
this.IQ_RESULT = "jabber:client.iq.result";
this.IQ_ERROR = "jabber:client.iq.error";
/*this.MESSAGE_GROUPCHAT = "jabber:client.message.groupchat";
this.MESSAGE_WEBRTC = "jabber:client.message.webrtc";
this.MESSAGE_MANAGEMENT = "jabber:client.message.management";
this.MESSAGE_ERROR = "jabber:client.message.error";
this.MESSAGE_HEADLINE = "jabber:client.message.headline";
this.MESSAGE_CLOSE = "jabber:client.message.headline";
*/
this.xmppUtils = XMPPUTils.getXMPPUtils();
this.telephonyService = telephonyService;
this.contactService = contactService;
this.promiseQueue = PromiseQueue.createPromiseQueue(that._logger);
this._profiles = profileService;
}
onIqResultReceived (msg, stanzaTab) {
let that = this;
let stanza = stanzaTab[0];
let prettyStanza = stanzaTab[1];
let jsonStanza = stanzaTab[2];
let children = stanza.children;
children.forEach((node) => {
switch (node.getName()) {
case "pbxagentstatus":
that.onIqGetPbxAgentStatusReceived(stanza, node);
break;
case "default":
//that._logger.log(that.WARN, LOG_ID + "(handleXMPPConnection, onIqResultReceived) not managed - 'stanza'", node.getName());
break;
default:
//that
// .logger
//.log("warn", LOG_ID + "(handleXMPPConnection, onIqResultReceived) child not managed for iq - 'stanza'", node.getName());
}
});
};
// Private methods
onIqGetPbxAgentStatusReceived (stanza, node) {
let that = this;
let pbxagentstatus = {
"phoneapi" : "",
"xmppagent" : "",
"version" : ""
};
let subchildren = node.children;
subchildren.forEach(function (item) {
if (typeof item === "object") {
let itemName = item.getName();
if (itemName) {
pbxagentstatus[itemName] = item.text();
}
}
});
if (pbxagentstatus.version) {
let phoneApi = pbxagentstatus.phoneapi;
let xmppAgent = pbxagentstatus.xmppagent;
let agentVersion = pbxagentstatus.version;
let agentStatus = { "phoneApi": phoneApi, "xmppAgent": xmppAgent, "agentVersion": agentVersion };
that._logger.log(that.DEBUG, LOG_ID + "(onIqGetPbxAgentStatusReceived) - send rainbow_onpbxagentstatusreceived 'agentStatus' ", agentStatus);
that.eventEmitter.emit("rainbow_onpbxagentstatusreceived", agentStatus);
}
};
onMessageReceived (msg, stanzaTab) {
let that = this;
let stanza = stanzaTab[0];
let prettyStanza = stanzaTab[1];
let jsonStanza = stanzaTab[2];
that._logger.log(that.INTERNAL, LOG_ID + "(onMessageReceived) _entering_ : ", msg, prettyStanza);
try {
let stanzaElem = stanza;
//let that = this;
// Ignore "Offline" message
let delay = stanzaElem.getChild("delay");
if (delay && delay.text() === "Offline Storage") {
return true;
}
let from = stanza.attrs.from;
let to = stanza.attrs.to;
// Treat WEBRTC Events
let actionElmPropose = stanzaElem.getChild("propose");
if (actionElmPropose !== undefined) {
this.onProposeMessageReceived(actionElmPropose, from);
return true;
}
let actionElmRetract = stanzaElem.getChild("retract");
if (actionElmRetract !== undefined) {
this.onRetractMessageReceived(actionElmRetract, from);
return true;
}
let actionElmAccept = stanzaElem.getChild("accept");
if (actionElmAccept !== undefined) {
this.onAcceptMessageReceived(actionElmAccept, from);
return true;
}
// Treat Telephony (3PCC) Events
let actionElm = stanzaElem.getChild("callservice");
if (actionElm === undefined) {
return true;
}
let actionElem = null;
let actionElemName = null;
for (let i = 0; i < actionElm.children.length; i++) {
if (!actionElemName) {
if (actionElm.children[i].name) {
actionElemName = actionElm.children[i].name.toLowerCase();
actionElem = actionElm.children[i];
}
}
}
if (actionElemName) {
that._logger.log(that.DEBUG, LOG_ID + "(onMessageReceived) ", that._logger.colors.debug("-- event -- ", actionElemName));
// Handle the event
switch (actionElemName) {
case "initiated" :
this.promiseQueue.add(function () {
return that.onInitiatedEvent(actionElem);
});
break; // */
case "originated":
this.promiseQueue.add(function () {
return that.onOriginatedEvent(actionElem);
});
break; // */
case "delivered":
this.promiseQueue.add(function () {
return that.onDeliveredEvent(actionElem);
});
break;
case "established":
this.promiseQueue.add(function () {
return that.onEstablishedEvent(actionElem);
});
break;
case "retrievecall":
this.promiseQueue.add(function () {
return that.onRetrieveCallEvent(actionElem);
});
break;
case "queued":
this.promiseQueue.add(function () {
return that.onQueuedEvent(actionElem);
});
break;
case "holdcall":
case "held":
this.promiseQueue.add(function () {
return that.onHeldEvent(actionElem);
});
break; // OLD SYNTAX TO BE REMOVED
case "diverted":
this.promiseQueue.add(function () {
return that.onDivertedEvent(actionElem);
});
break;
case "transfercall":
case "transferred":
this.promiseQueue.add(function () {
return that.onTransferEvent(actionElem);
});
break; // OLD SYNTAX TO BE REMOVED
case "conferenced":
this.promiseQueue.add(function () {
return that.onConferenceEvent(actionElem);
});
break;
case "connectioncleared":
this.promiseQueue.add(function () {
return that.onClearCallEvent(actionElem);
});
break;
case "failed":
this.promiseQueue.add(function () {
return that.onFailCallEvent(actionElem);
});
break;
case "messaging":
this.promiseQueue.add(function () {
return that.onVoiceMessageEvent(actionElem);
});
break;
case "updatecall":
this.promiseQueue.add(function () {
return that.onUpDateCallEvent(actionElem);
});
break;
case "forwarded":
this.promiseQueue.add(function () {
return that.onCallForwardedEvent(actionElem);
});
break;
case "nomadicstatus":
this.promiseQueue.add(function () {
return that.onNomadicStatusEvent(actionElem);
});
break;
case "voicemessages":
this.promiseQueue.add(function () {
return that.onVoiceMessagesEvent(actionElem);
});
break;
// */
default:
that._logger.log(that.INTERNAL, LOG_ID + "(onMessageReceived) untreated actionElemName : ", actionElemName);
}
// */
return true;
} else {
// that._logger.log(that.ERROR, LOG_ID + "(onMessageReceived) -- failure -- no name found in callservice children.");
that._logger.log(that.ERROR, LOG_ID + "(onMessageReceived) -- failure -- no name found in callservice children : ", stanzaElem);
}
}
catch (error) {
// that._logger.log(that.ERROR, LOG_ID + "(onMessageReceived) CATCH Error !!! -- failure -- ");
that._logger.log(that.ERROR, LOG_ID + "(onMessageReceived) CATCH Error !!! -- failure -- : ", error);
//return true;
}
that._logger.log(that.DEBUG, LOG_ID + "(onMessageReceived) _exiting_");
return true;
};
async onProposeMessageReceived (node, from) {
let that = this;
/*
stanza :
*/
that._logger.log(that.INTERNAL, LOG_ID + "(onProposeMessageReceived) node - ", node);
let id = ( node.attrs ) ? node.attrs.id : undefined;
let descriptionElm = node.getChild("description");
let description : { media : string, xmlns : string } = { media : undefined, xmlns : undefined };
description.media = ( descriptionElm && descriptionElm.attrs ) ? descriptionElm.attrs.media : undefined;
description.xmlns = ( descriptionElm && descriptionElm.attrs ) ? descriptionElm.attrs.xmlns : undefined;
let resource = that.xmppUtils.getResourceFromFullJID(from);
let unifiedplanElm = node.getChild("unifiedplan");
let unifiedplan : { xmlns : string } = { xmlns : undefined };
unifiedplan.xmlns = ( unifiedplanElm && unifiedplanElm.attrs ) ? unifiedplanElm.attrs.xmlns : undefined;
let xmlns = ( node && node.attrs ) ? node.attrs.xmlns : undefined;
let contact = await that.contactService.getContactByJid(from, true).catch((err)=>{ that._logger.log(that.ERROR, LOG_ID + "(onProposeMessageReceived) getContactByJid failed : ", err); return undefined;});
that.eventEmitter.emit("evt_internal_propose", {contact, resource, xmlns, description, unifiedplan, id });
};
async onRetractMessageReceived (node, from) {
/*
stanza :
*/
let that = this;
that._logger.log(that.INTERNAL, LOG_ID + "(onRetractMessageReceived) node - ", node);
let id = ( node.attrs ) ? node.attrs.id : undefined;
let resource = that.xmppUtils.getResourceFromFullJID(from);
let xmlns = ( node && node.attrs ) ? node.attrs.xmlns : undefined;
let contact = await that.contactService.getContactByJid(from, true).catch((err)=>{ that._logger.log(that.ERROR, LOG_ID + "(onRetractMessageReceived) getContactByJid failed : ", err); return undefined;});
that.eventEmitter.emit("evt_internal_retract", {contact, resource, xmlns, id });
};
async onAcceptMessageReceived (node, from) {
/*
stanza :
*/
let that = this;
that._logger.log(that.INTERNAL, LOG_ID + "(onAcceptMessageReceived) node - ", node);
let id = ( node.attrs ) ? node.attrs.id : undefined;
let resource = that.xmppUtils.getResourceFromFullJID(from);
let xmlns = ( node && node.attrs ) ? node.attrs.xmlns : undefined;
let contact = await that.contactService.getContactByJid(from, true).catch((err)=>{ that._logger.log(that.ERROR, LOG_ID + "(onAcceptMessageReceived) getContactByJid failed : ", err); return undefined;});
that.eventEmitter.emit("evt_internal_accept", {contact, resource, xmlns, id });
};
/*********************************************************************/
/** INITIATED CALL STUFF **/
/*********************************************************************/
onInitiatedEvent (initiatedElem) {
let that = this;
that._logger.log(that.INTERNAL, LOG_ID + "(onInitiatedEvent) _entering_ : ", initiatedElem);
return that.getCall(initiatedElem)
.then(function (call : Call) {
try {
/*if (call.status === Call.Status.QUEUED_INCOMING) {
return Promise.resolve(undefined);
} // */
let deviceState = initiatedElem.attr("deviceState");
//let devicetype = initiatedElem.attr("devicetype");
//let callId = initiatedElem.attr("callId");
if (deviceState && deviceState === "LCI_INITIATED") {
call.setStatus(Call.Status.DIALING );
// Update call info
//that._logger.log(that.INTERNAL, LOG_ID + "(updateCallContact) send evt_internal_callupdated ", call);
that.eventEmitter.emit("evt_internal_callupdated", call);
}
return Promise.resolve(undefined);
}
catch (error) {
let errorMessage = "onInitiatedEvent -- " + error.message;
that._logger.log(that.ERROR, LOG_ID + "(onInitiatedEvent) Catch Error !!! " );
that._logger.log(that.ERROR, LOG_ID + "(onInitiatedEvent) Catch Error !!! : ", errorMessage);
return Promise.reject(new Error(errorMessage));
}
});
// */
};
/*********************************************************************/
/** ORIGINATED CALL STUFF **/
/*********************************************************************/
onOriginatedEvent (originatedElem) {
let that = this;
that._logger.log(that.DEBUG, LOG_ID + "(onOriginatedEvent) _entering_ : ", originatedElem);
return that.getCall(originatedElem)
.then(function (call) {
try {
let jid = originatedElem.attr("endpointIm");
let phoneNumber = originatedElem.attr("endpointTel");
let currentCalled = {
contactPhoneNumber: "",
contact: call.contact,
participantsPhoneNumbers: null,
participants: null
};
// PCG has some info
if (jid || phoneNumber) {
currentCalled.contactPhoneNumber = (phoneNumber ? phoneNumber : "");
}
// Unknown user
else if (call.contact && call.contact.temp) {
currentCalled.contactPhoneNumber = call.contact._id;//that is the only current known phoneNumber
}
call.setCurrentCalled(currentCalled);
/*let deviceState = call.deviceState;
//let devicetype = initiatedElem.attr("devicetype");
//let callId = initiatedElem.attr("callId");
if (deviceState && deviceState === "LCI_CONNECTED") {
call.setStatus(Call.Status.DIALING );
// Update call info
that._logger.log(that.DEBUG, LOG_ID + "(updateCallContact) send evt_internal_callupdated ", call);
that.eventEmitter.emit("evt_internal_callupdated", call);
} */
return Promise.resolve(undefined);
}
catch (error) {
let errorMessage = "onOriginatedEvent -- " + error.message;
// that._logger.log(that.ERROR, LOG_ID + "(onOriginatedEvent) Catch Error !!! " );
that._logger.log(that.ERROR, LOG_ID + "(onOriginatedEvent) Catch Error !!! : ", errorMessage);
return Promise.reject(new Error(errorMessage));
}
});
// */
};
/*********************************************************************/
/** DELIVERED STUFF **/
/*********************************************************************/
onDeliveredEvent (deliveredElem) {
let that = this;
that._logger.log(that.INTERNAL, LOG_ID + "(onDeliveredEvent) _entering_ : ", deliveredElem);
//let that = this;
return that.getCall(deliveredElem).then(function (call) {
try {
if (call.status === Call.Status.QUEUED_INCOMING) {
return Promise.resolve(undefined);
}
let type = deliveredElem.attr("type");
let jid = deliveredElem.attr("endpointIm");
let phoneNumber = deliveredElem.attr("endpointTel");
// Update call info
call.setStatus((type === "outgoing") ? Call.Status.RINGING_OUTGOING : Call.Status.RINGING_INCOMING);
call.startDate = null;
call.vm = false;
that._logger.log(that.INTERNAL, LOG_ID + "(onDeliveredEvent) call : ", call);
// Update contact info if necessary
return that.updateCallContact(jid, phoneNumber, "delivered", call);
}
catch (error) {
let errorMessage = "onDeliveredEvent -- " + error.message;
// that._logger.log(that.ERROR, LOG_ID + "(onDeliveredEvent) Catch Error !!! " );
that._logger.log(that.ERROR, LOG_ID + "(onDeliveredEvent) Catch Error !!! : ", errorMessage);
return Promise.reject(new Error(errorMessage));
}
}); // */
};
/*********************************************************************/
/** ESTABLISHED STUFF **/
/*********************************************************************/
onEstablishedEvent (establishedElem) {
let that = this;
that._logger.log(that.INTERNAL, LOG_ID + "(onEstablishedEvent) _entering_ : ", establishedElem);
//let that = this;
return that.getCall(establishedElem).then(function (call) {
try {
let jid = establishedElem.attr("endpointIm");
let phoneNumber = establishedElem.attr("endpointTel");
// Call already exists and IS NOT a conference, update contact info if necessary
if (call.contact && call.contact._id) {
call.setStatus(Call.Status.ACTIVE);
// Update contact info as necessary
return that.updateCallContact(jid, phoneNumber, "established", call);
}
// Call already exists and IS a conference, update contact info if necessary
else if (call.participants && call.participants.length > 0) {
//recover former matching contact from participants
let contactRecovered = null;
for (let i = 0; (i < call.participants.length && !contactRecovered); i++) {
if (call.participants[i].id === jid) {
contactRecovered = call.participants[i];
}
else if (call.currentCalled.participantsPhoneNumbers &&
call.currentCalled.participantsPhoneNumbers.length > 0 &&
call.currentCalled.participantsPhoneNumbers[i] === phoneNumber) {
contactRecovered = call.participants[i];
}
}
//clean former conf struct & update contact
call.participants = [];
call.isConference = false;
let currentCalled = call.getCurrentCalled();
if (contactRecovered) {
call.setContact(contactRecovered);
call.setStatus(Call.Status.ACTIVE);
currentCalled = {contactPhoneNumber: phoneNumber, contact: contactRecovered};
call.setCurrentCalled(currentCalled);
//that._logger.log(that.INTERNAL, LOG_ID + "(onEstablishedEvent) send evt_internal_callupdated ", call);
that.eventEmitter.emit("evt_internal_callupdated", call);
//$rootScope.$broadcast("ON_CALL_UPDATED_EVENT", call);
}
else { // no matching contact strange but go ahead ...
if (!jid && !phoneNumber) {
phoneNumber = "****";
}
return that.contactService.getOrCreateContact(jid, phoneNumber)
.then(function (contact) {
call.setContact(contact);
call.setStatus(Call.Status.ACTIVE);
currentCalled = {contactPhoneNumber: phoneNumber, contact: contact};
call.setCurrentCalled(currentCalled);
// $rootScope.$broadcast("ON_CALL_UPDATED_EVENT", call);
//that._logger.log(that.INTERNAL, LOG_ID + "(onEstablishedEvent) send evt_internal_callupdated ", call);
that.eventEmitter.emit("evt_internal_callupdated", call);
return Promise.resolve(undefined);
});
}
} else {
that._logger.log(that.DEBUG, LOG_ID + "(onEstablishedEvent) Neither contact, nor participant found!" );
}
return Promise.resolve(undefined);
}
catch (error) {
let errorMessage = "onEstablishedEvent -- " + error.message;
// that._logger.log(that.ERROR, LOG_ID + "(onEstablishedEvent) Catch Error!!! " );
that._logger.log(that.ERROR, LOG_ID + "(onEstablishedEvent) Catch Error!!! : ", errorMessage);
return Promise.reject(new Error(errorMessage));
}
}); // */
};
/*********************************************************************/
/** RETRIEVE CALL STUFF **/
/*********************************************************************/
onRetrieveCallEvent (retrieveElem) {
let that = this;
that._logger.log(that.INTERNAL, LOG_ID + "(onRetrieveCallEvent) _entering_ : ", retrieveElem);
return that.getCall(retrieveElem).then(function (call) {
call.setStatus(Call.Status.ACTIVE);
//that._logger.log(that.INTERNAL, LOG_ID + "(onRetrieveCallEvent) send evt_internal_callupdated ", call);
that.eventEmitter.emit("evt_internal_callupdated", call);
// $rootScope.$broadcast("ON_CALL_UPDATED_EVENT", call);
});
// */
};
/*********************************************************************/
/** CLEAR CALL STUFF **/
/*********************************************************************/
onClearCallEvent (clearElem) {
let that = this;
that._logger.log(that.INTERNAL, LOG_ID + "(onClearCallEvent) _entering_ : ", clearElem);
//let that = this;
return that.getCall(clearElem).then(async (call) => {
if (call.status !== Call.Status.ERROR) {
call.setStatus(Call.Status.UNKNOWN);
let cause = clearElem.attr("cause");
let deviceState = clearElem.attr("deviceState");
call.cause = cause;
call.deviceState = deviceState;
//that._logger.log(that.INTERNAL, LOG_ID + "(onClearCallEvent) send evt_internal_callupdated ", call);
that.eventEmitter.emit("evt_internal_callupdated", call);
await that.telephonyService.clearCall(call);
//$rootScope.$broadcast("ON_CALL_UPDATED_EVENT", call);
}
}); // */
};
/*********************************************************************/
/** HOLD CALL STUFF **/
/*********************************************************************/
onHeldEvent (heldElem) {
let that = this;
that._logger.log(that.INTERNAL, LOG_ID + "(onHeldEvent) _entering_ : ", heldElem);
return that.getCall(heldElem).then(function (call) {
try {
let connectionId = heldElem.attr("callId");
if (!connectionId) {
connectionId = heldElem.attr("heldCallId");
} // TODO: WHY and WHEN
let callDeviceId = Call.getDeviceIdFromConnectionId(call.connectionId);
let holdDeviceId = Call.getDeviceIdFromConnectionId(connectionId);
if (callDeviceId === holdDeviceId) {
call.setStatus(Call.Status.HOLD);
}
// Same callId but different equipmentId (We receive equipment id of user who put us in held)
else {
call.setStatus(Call.Status.PUT_ON_HOLD);
}
//$rootScope.$broadcast("ON_CALL_UPDATED_EVENT", call);
//that._logger.log(that.INTERNAL, LOG_ID + "(onHeldEvent) send evt_internal_callupdated ", call);
that.eventEmitter.emit("evt_internal_callupdated", call);
return Promise.resolve(undefined);
}
catch (error) {
let errorMessage = "onHeldEvent -- " + error.message;
// that._logger.log(that.ERROR, LOG_ID + "(onHeldEvent) Catch Error!!! " );
that._logger.log(that.ERROR, LOG_ID + "(onHeldEvent) Catch Error!!! : ", errorMessage);
return Promise.reject(new Error(errorMessage));
}
}); // */
};
/*********************************************************************/
/** QUEUED STUFF **/
/*********************************************************************/
onQueuedEvent (queuedElem) {
let that = this;
that._logger.log(that.INTERNAL, LOG_ID + "(onQueuedEvent) _entering_ : ", queuedElem);
//let that = this;
let cause = queuedElem.attr("cause");
if (cause === "PARK") {
that._logger.log(that.WARN, LOG_ID + "(onQueuedEvent) - ignore PARK cause");
return Promise.resolve(undefined);
}
if (cause === "NEWCALL") {
that._logger.log(that.WARN, LOG_ID + "(onQueuedEvent) - ignore NEWCALL cause");
return Promise.resolve(undefined);
}
return that.getCall(queuedElem).then(function (call) {
try {
let type = queuedElem.attr("type");
let jid = queuedElem.attr("endpointIm");
let phoneNumber = queuedElem.attr("endpointTel");
let status = (type === "outgoing") ? Call.Status.QUEUED_OUTGOING : Call.Status.QUEUED_INCOMING;
call.setStatus(status);
call.startDate = null;
call.vm = false;
// Update contact info if necessary
return that.updateCallContact(jid, phoneNumber, "queued", call);
}
catch (error) {
let errorMessage = "onQueuedEvent -- " + error.message;
// that._logger.log(that.ERROR, LOG_ID + "(onHeldEvent) Catch Error!!! " );
that._logger.log(that.ERROR, LOG_ID + "(onHeldEvent) Catch Error!!! : ", errorMessage);
return Promise.reject(new Error(errorMessage));
}
});
// */
};
/*********************************************************************/
/** DIVERTED STUFF **/
/*********************************************************************/
async onDivertedEvent (divertedElem) {
let that = this;
that._logger.log(that.INTERNAL, LOG_ID + "(onDivertedEvent) _entering_ : ", divertedElem);
let oldConnectionId = divertedElem.attr("oldCallId");
let oldCallId = Call.getIdFromConnectionId(oldConnectionId);
let call = that.telephonyService.getCallFromCache(oldCallId);
if (!call) {
that._logger.log(that.WARN, LOG_ID + "(onDivertedEvent) - receive divertedEvent on unknown call --- ignored");
return Promise.resolve(undefined);
}
await that.telephonyService.clearCall(call);
// $rootScope.$broadcast("ON_CALL_UPDATED_EVENT", call);
//that._logger.log(that.INTERNAL, LOG_ID + "(onDivertedEvent) send evt_internal_callupdated ", call);
that.eventEmitter.emit("evt_internal_callupdated", call);
return Promise.resolve(undefined);
// */
};
/*********************************************************************/
/** TRANSFER STUFF **/
/*********************************************************************/
async onTransferEvent (transferElem) {
let that = this;
that._logger.log(that.INTERNAL, LOG_ID + "(onTransferEvent) _entering_ : ", transferElem);
// let that = this;
// Extract transfert call parameters
let activeConnectionId = transferElem.attr("activeCallId");
let heldConnectionId = transferElem.attr("heldCallId");
let newConnectionId = transferElem.attr("newCallId");
// Get active call
let activeCallId = Call.getIdFromConnectionId(activeConnectionId);
let activeCall = that.telephonyService.getCallFromCache(activeCallId);
if (heldConnectionId) {
that._logger.log(that.DEBUG, LOG_ID + "(onTransferEvent) heldconnectionId found ", heldConnectionId);
// Get the held call
let heldCallId = Call.getIdFromConnectionId(heldConnectionId);
let heldCall = that.telephonyService.getCallFromCache(heldCallId);
// Release both calls (active and held)
if (heldCall) {
heldCall.setStatus(Call.Status.UNKNOWN);
//that._logger.log(that.INTERNAL, LOG_ID + "(onTransferEvent) send evt_internal_callupdated ", heldCall);
that.eventEmitter.emit("evt_internal_callupdated", heldCall);
await that.telephonyService.clearCall(heldCall);
} else {
that._logger.log(that.DEBUG, LOG_ID + "(onTransferEvent) no heldCall found");
}
if (activeCall) {
activeCall.setStatus(Call.Status.UNKNOWN);
//that._logger.log(that.INTERNAL, LOG_ID + "(onTransferEvent) send evt_internal_callupdated ", activeCall);
that.eventEmitter.emit("evt_internal_callupdated", activeCall);
await that.telephonyService.clearCall(activeCall);
} else {
that._logger.log(that.DEBUG, LOG_ID + "(onTransferEvent) no activeCall found");
}
// $rootScope.$broadcast("ON_CALL_UPDATED_EVENT", heldCall);
// $rootScope.$broadcast("ON_CALL_UPDATED_EVENT", activeCall);
}
if (newConnectionId) {
that._logger.log(that.DEBUG, LOG_ID + "(onTransferEvent) newConnectionId found ", newConnectionId);
let jid = transferElem.attr("newEndpointIm");
let phoneNumber = transferElem.attr("newEndpointTel");
let deviceState = transferElem.attr("deviceState");
if (!deviceState) {
deviceState = transferElem.attr("deviceStatus");
} // TO BE REMOVED
if (activeCall) {
// Release current call
activeCall.setStatus(Call.Status.UNKNOWN);
//$rootScope.$broadcast("ON_CALL_UPDATED_EVENT", activeCall);
//that._logger.log(that.INTERNAL, LOG_ID + "(onTransferEvent) send evt_internal_callupdated ", activeCall);
that.eventEmitter.emit("evt_internal_callupdated", activeCall);
await that.telephonyService.clearCall(activeCall);
} else {
that._logger.log(that.DEBUG, LOG_ID + "(onTransferEvent) no activeCall found");
}
if (!jid && !phoneNumber) {//secret identity
phoneNumber = "****";
}
let deviceType = transferElem.find("deviceType");
return that.getOrCreateCall(newConnectionId, jid, deviceType, phoneNumber)
.then(function (newCall) {
let globalCallId = transferElem.attr("globalCallId");
if (globalCallId) {
newCall.setGlobalCallId(globalCallId);
}
let correlatorData = transferElem.attr("correlatorData");
if (correlatorData) {
newCall.correlatorData = correlatorData;
}
if (deviceState && deviceState === "LCI_ALERTING") {
newCall.setStatus(Call.Status.RINGING_INCOMING);
}
else {
newCall.setStatus(Call.Status.ACTIVE);
}
// Update contact info if necessary
return that.updateCallContact(jid, phoneNumber, "transfercall", newCall);
});
} else {
return Promise.resolve(undefined);
}
// */
};
/*********************************************************************/
/** CONFERENCE STUFF **/
/*********************************************************************/
onConferenceEvent (conferencedElem) {
let that = this;
that._logger.log(that.INTERNAL, LOG_ID + "(onConferenceEvent) _entering_ : ", conferencedElem);
//let that = this;
// Get connectionsIds
let primaryOldConnectionId = conferencedElem.getChild("primaryOldCallId") ? conferencedElem.getChild("primaryOldCallId").getText() : "";
let secondaryOldConnectionId = conferencedElem.getChild("secondaryOldCallId") ? conferencedElem.getChild("secondaryOldCallId").getText() : "";
let newConnectionId = conferencedElem.getChild("newCallId") ? conferencedElem.getChild("newCallId").getText() : "";
that._logger.log(that.DEBUG, LOG_ID + "(onConferenceEvent) primaryOldConnectionId - ", primaryOldConnectionId);
that._logger.log(that.DEBUG, LOG_ID + "(onConferenceEvent) secondaryOldConnectionId - ", secondaryOldConnectionId);
that._logger.log(that.DEBUG, LOG_ID + "(onConferenceEvent) newConnectionId - ", newConnectionId);
// Extract callIds
let primaryOldCallId = Call.getIdFromConnectionId(primaryOldConnectionId);
let secondaryOldCallId = Call.getIdFromConnectionId(secondaryOldConnectionId);
that._logger.log(that.DEBUG, LOG_ID + "(onConferenceEvent) primaryOldCallId - ", primaryOldCallId);
that._logger.log(that.DEBUG, LOG_ID + "(onConferenceEvent) secondaryOldCallId - ", secondaryOldCallId);
// Get current calls
let primaryOldCall = that.telephonyService.getCallFromCache(primaryOldCallId);
let secondaryOldCall = that.telephonyService.getCallFromCache(secondaryOldCallId);
// Prepare participant promises
let confParticipants = [];
let participantPromises = [];
let confParticipantsPhoneNumbers = [];
let confContactsInfos = [];
let participantsElmt = conferencedElem.getChild("participants");
that._logger.log(that.INTERNAL, LOG_ID + "(onConferenceEvent) participantsElmt - ", participantsElmt);
let participantElmts = participantsElmt.getChildren("participant");
that._logger.log(that.INTERNAL, LOG_ID + "(onConferenceEvent) participantElmts - ", participantElmts);
participantElmts.forEach(function (participantElem) {
//let participantElem = angular.element(this);
let endpointTel = participantElem.find("endpointTel").getText();
that._logger.log(that.DEBUG, LOG_ID + "(onConferenceEvent) endpointTel - ", endpointTel);
let endpointIm = participantElem.find("endpointIm").getText();
that._logger.log(that.DEBUG, LOG_ID + "(onConferenceEvent) endpointIm - ", endpointIm);
let callId = participantElem.find("callId").getText();
that._logger.log(that.DEBUG, LOG_ID + "(onConferenceEvent) callId - ", callId);
let role = participantElem.find("role").getText();
that._logger.log(that.DEBUG, LOG_ID + "(onConferenceEvent) role - ", role);
let contactInfos = {
endpointTel : endpointTel,
endpointIm : endpointIm,
callId : callId,
role : role
};
confContactsInfos.push(contactInfos);
if (!(endpointIm && that.contactService.isUserContactJid(endpointIm))) {
participantPromises.push(new Promise(function (resolve, reject) {
if (!endpointIm && !endpointTel) {
endpointTel = "****";
}
//if no endpointIm try to extract contact info from primary or secondary calls
if (!endpointIm && primaryOldCall && primaryOldCall.contact &&
primaryOldCall.currentCalled.contactPhoneNumber === endpointTel) {
confParticipants.push(primaryOldCall.contact);
confParticipantsPhoneNumbers.push(endpointTel);
resolve(undefined);
}
else if (!endpointIm && secondaryOldCall && secondaryOldCall.contact &&
secondaryOldCall.currentCalled.contactPhoneNumber === endpointTel) {
confParticipants.push(secondaryOldCall.contact);
confParticipantsPhoneNumbers.push(endpointTel);
resolve(undefined);
}
else {
that.contactService.getOrCreateContact(endpointIm, endpointTel)
.then(function (contact) {
//manage Outlook Call Party identification
/* let centralizedService = $injector.get("centralizedService");
centralizedService.outlook.updateContactFromOutlookInfos(contact, endpointTel)
.then(
function successCallback(updateStatus) {
if (updateStatus) {
that._logger.log(that.DEBUG, LOG_ID + " on conferenced, update from outlook for contact :" + contact.displayNameMD5);
//that.makeUpdateContact(call, contact, phoneNumber, actionElemName);
} else {
that._logger.log(that.DEBUG, LOG_ID + "on conferenced, no update from outlook for contact :" + contact.displayNameMD5);
}
},
function errorCallback() {
that._logger.log(that.DEBUG, LOG_ID + "on conferenced, no Outlook search available");
}
)
.finally(function () {
*/
confParticipants.push(contact);
confParticipantsPhoneNumbers.push(endpointTel);
resolve(undefined);
//});
})
.catch(function (error) {
that._logger.log(that.DEBUG, LOG_ID + "(onConferenceEvent) Impossible to get contact - " );
that._logger.log("internaldebug", LOG_ID + "(onConferenceEvent) Impossible to get contact - : ", error.message);
reject();
});
}
}));
}
});
// Get participants asynchronously
return Promise.all(participantPromises)
.then(async () => {
// Release previous calls
if (primaryOldCall) {
primaryOldCall.setStatus(Call.Status.UNKNOWN);
that._logger.log(that.INTERNAL, LOG_ID + "(onConferenceEvent) release primaryOldCall - ", primaryOldCall);
primaryOldCall.setStatus(Call.Status.UNKNOWN);
//let cause = clearElem.attr("cause");
//let deviceState = clearElem.attr("deviceState");
//call.cause = cause;
//call.deviceState = deviceState;
//that._logger.log(that.INTERNAL, LOG_ID + "(onConferenceEvent) send evt_internal_callupdated ", primaryOldCall);
that.eventEmitter.emit("evt_internal_callupdated", primaryOldCall);
await that.telephonyService.clearCall(primaryOldCall);
//$rootScope.$broadcast("ON_CALL_UPDATED_EVENT", primaryOldCall);
}
if (secondaryOldCall) {
secondaryOldCall.setStatus(Call.Status.UNKNOWN);
that._logger.log(that.INTERNAL, LOG_ID + "(onConferenceEvent) release secondaryOldCall - ", secondaryOldCall);
secondaryOldCall.setStatus(Call.Status.UNKNOWN);
//let cause = clearElem.attr("cause");
//let deviceState = clearElem.attr("deviceState");
//call.cause = cause;
//call.deviceState = deviceState;
//that._logger.log(that.INTERNAL, LOG_ID + "(onConferenceEvent) send evt_internal_callupdated ", secondaryOldCall);
that.eventEmitter.emit("evt_internal_callupdated", secondaryOldCall);
await that.telephonyService.clearCall(secondaryOldCall);
//$rootScope.$broadcast("ON_CALL_UPDATED_EVENT", secondaryOldCall);
}
// Create the new conference call
let newConferenceCall = await that.createConferenceCall(newConnectionId, confParticipants);
//update currentcalled structure
let currentCalled = newConferenceCall.getCurrentCalled();
currentCalled.participants = confParticipants;
currentCalled.participantsPhoneNumbers = confParticipantsPhoneNumbers;
newConferenceCall.setCurrentCalled(currentCalled);
newConferenceCall.setStatus(Call.Status.ACTIVE);
newConferenceCall.setDeviceType(undefined);
that._logger.log(that.INTERNAL, LOG_ID + "(onConferenceEvent) create newConferenceCall - " , newConferenceCall);
that._logger.log(that.INTERNAL, LOG_ID + "(onConferenceEvent) create newConferenceCall - stored :" , that.telephonyService.getCallFromCache(newConferenceCall.id));
//that._logger.log(that.INTERNAL, LOG_ID + "(onConferenceEvent) send evt_internal_callupdated ", newConferenceCall);
let conferenceInfos = {
primaryOldCall : primaryOldCall,
secondaryOldCall : secondaryOldCall,
newConferenceCall : newConferenceCall,
participants : confContactsInfos
};
that.eventEmitter.emit("evt_internal_conferenced", conferenceInfos);
that.eventEmitter.emit("evt_internal_callupdated", newConferenceCall);
//$rootScope.$broadcast("ON_CALL_UPDATED_EVENT", newConferenceCall);
});
// */
};
/*********************************************************************/
/** VOICE MESSAGE STUFF **/
/*********************************************************************/
onVoiceMessageEvent (messagingElem) {
let that = this;
that._logger.log(that.INTERNAL, LOG_ID + "(onVoiceMessageEvent) _entering_ : ", messagingElem);
// Ignore forbidden requests
if (!that._profiles.isFeatureEnabled(that._profiles.getFeaturesEnum().TELEPHONY_VOICE_MAIL)) {
that._logger.log(that.DEBUG, LOG_ID + "(onVoiceMessageEvent) feature not enabled => IGNORED event");
return Promise.resolve(undefined);
}
// Look for a voiceMessageCounter child
let voiceMessageCounterValue = messagingElem.getChild("voiceMessageCounter").text();
if (voiceMessageCounterValue) {
let ct = Number(voiceMessageCounterValue);
if (Number.isInteger(ct) && (ct >= 0)) {
that.telephonyService.voiceMail.setVMCounter(ct);
that.telephonyService.voiceMail.setVMFlag((ct > 0));
that.telephonyService.voiceMail.setInfoMsg("");
//$rootScope.$broadcast("ON_VOICE_MESSAGE_UPDATE_EVENT", ct);
//that._logger.log(that.INTERNAL, LOG_ID + "(onVoiceMessageEvent) send evt_internal_voicemessageupdated ", ct);
that.eventEmitter.emit("evt_internal_voicemessageupdated", ct);
}
}
// No voiceMessageCounter child look for voiceMessageWaiting child
let voiceMessageWaitingValue = "";
let voiceMessageWaiting = XMPPUTils.getXMPPUtils().findChild( messagingElem, "voiceMessageWaiting");
if (voiceMessageWaiting) {
voiceMessageWaitingValue = voiceMessageWaiting.text();
if (voiceMessageWaitingValue === "changed") {
return that.telephonyService.getVoiceMessageCounter();
}
}
return Promise.resolve(undefined);
// */
};
/*********************************************************************/
/** UPDATECALL STUFF **/
/*********************************************************************/
onUpDateCallEvent (updatecallElem) {
let that = this;
that._logger.log(that.INTERNAL, LOG_ID + "(onUpDateCallEvent) _entering_ : ", updatecallElem);
return that.getCall(updatecallElem).then(function (call) {
let jid = updatecallElem.attr("endpointIm");
let phoneNumber = updatecallElem.attr("endpointTel");
let firstName = "";
let lastName = "";
let identity = updatecallElem.getChild("identity");
let identityFirstName = identity.attr("firstName");
let identityLastName = updatecallElem.getChild("identity").attr("lastName");
let identityDisplayName = updatecallElem.getChild("identity").attr("displayName");
let contactUpdateDone = false;
if (!config.permitSearchFromPhoneBook) { // <--- allow to permit search even if not the good profile
//check if phonebook is allowed by profile else no result
if (!that._profiles.isFeatureEnabled(that._profiles.getFeaturesEnum().TELEPHONY_PHONE_BOOK)) {
that._logger.log(that.DEBUG, LOG_ID + "(onUpDateCallEvent) xnames not allowed for the user profile => IGNORED event");
return Promise.resolve(undefined);
}
}
//find Xnames from directories
if (identityLastName && identityLastName.length) {
lastName = identityLastName;
if (identityFirstName && identityFirstName.length) {
firstName = identityFirstName;
}
that._logger.log(that.DEBUG, LOG_ID + "(onUpDateCallEvent) received for call ", call.id, " for phoneNumber:", Utils.anonymizePhoneNumber(phoneNumber), " with name : ", firstName.slice(0, 1), "***");
} else {
if (identityDisplayName && identityDisplayName.length && identityDisplayName !== phoneNumber) {
lastName = identityDisplayName; //Workaround last resort, only displayName is available, hack is to use it as lastName
that._logger.log(that.DEBUG, LOG_ID + "(onUpDateCallEvent) only displayName available");
} else {
that._logger.log(that.DEBUG, LOG_ID + "(onUpDateCallEvent) xnames not available => IGNORED event");
return Promise.resolve(undefined);
}
}
//debug+
//if (!call.currentCalled.contactPhoneNumber || call.currentCalled.contactPhoneNumber === "") {
// $log.debug("[TelephonyServiceEventHandler] onUpDateCallEvent call.currentCalled.contactPhoneNumber EMPTY !!!");
// $log.debug("[TelephonyServiceEventHandler] for call " + call.id + " conf = " + call.isConference);
//}
//debug-
// update contact as necessary
return that.contactService.getOrCreateContact(jid, phoneNumber)
.then(function (contact) {
if (contact.temp) { //not a rainbow user
contact.updateName(firstName, lastName);
if (call.contact && call.contact._id) { //not a conf
let currentCalled = {contactPhoneNumber: phoneNumber, contact: contact};
if (call.contact._id !== contact._id || call.contact.displayName === phoneNumber || call.contact.getNameUpdatePrio() === NameUpdatePrio.OUTLOOK_UPDATE_PRIO) {
contact.setNameUpdatePrio(NameUpdatePrio.SERVER_UPDATE_PRIO);//flag as server prio
call.setContact(contact);
call.setCurrentCalled(currentCalled);
contactUpdateDone = true;
that._logger.log(that.INTERNAL, LOG_ID + "(onUpDateCallEvent) xnames updated for ", phoneNumber, "with contact : ", contact.displayNameMD5);
}
} else if (call.participants && call.participants.length > 0) {
let currentCalled = call.getCurrentCalled();
for (let i = 0; i < call.participants.length; i++) {
if (call.participants[i].temp) {
if (call.participants[i].phoneProCan && call.participants[i].phoneProCan === phoneNumber) {//concerned participant
that._logger.log(that.INTERNAL, LOG_ID + "(onUpDateCallEvent) temp participant ", call.participants[i].displayNameMD5, " updated with : ", contact.displayNameMD5);
call.participants[i] = contact;
call.participants[i].setNameUpdatePrio(NameUpdatePrio.SERVER_UPDATE_PRIO);//flag as server prio
currentCalled.participantsPhoneNumbers[i] = phoneNumber;
currentCalled.participants[i] = contact;
contactUpdateDone = true;
}
}
else {//former participant is a rainbow user I don't know what to do !!!???
that._logger.log(that.INTERNAL, LOG_ID + "(onUpDateCallEvent) STRANGE former participant was a rainbow: " , call.participants[i].displayNameMD5);
}
}
call.setCurrentCalled(currentCalled);
}
} else { //rainbow contact found
if (call.contact && call.contact._id) { //not a conf
let currentCalled = {contactPhoneNumber: phoneNumber, contact: contact};
if (call.contact._id !== contact._id) {//update call.contact if not the good one
//workaround+ Because of msg crossing pb udate old temp contact before to set the new one
if (call.contact.temp) {
call.contact.updateName(firstName, lastName);
call.contact.setNameUpdatePrio(NameUpdatePrio.SERVER_UPDATE_PRIO);//flag as server prio
}
//workaround-
call.setContact(contact);
call.setCurrentCalled(currentCalled);
contactUpdateDone = true;
that._logger.log(that.INTERNAL, LOG_ID + "(onUpDateCallEvent) call update with rainbow contact : ", contact.displayNameMD5);
}
} else if (call.participants && call.participants.length > 0) {
let currentCalled = call.getCurrentCalled();
for (let i = 0; i < call.participants.length; i++) {
if (call.participants[i].temp) {
if (call.participants[i].phoneProCan && call.participants[i].phoneProCan === phoneNumber) {//concerned participant
that._logger.log(that.INTERNAL, LOG_ID + "(onUpDateCallEvent) temp participant ", call.participants[i].displayNameMD5, " updated with : ", contact.displayNameMD5);
call.participants[i] = contact;
call.setParticipants(call.participants);//to force an update of the avatars
currentCalled.participantsPhoneNumbers[i] = phoneNumber;
currentCalled.participants[i] = contact;
contactUpdateDone = true;
}
}
else {//if former participant is the same rainbow user nothing to do except store phoneNumber and participant in call
if (call.participants[i].jid === jid) {//concerned participant
//call.participants[i] = contact;
currentCalled.participantsPhoneNumbers[i] = phoneNumber;
currentCalled.participants[i] = call.participants[i];
contactUpdateDone = true;//??
that._logger.log(that.INTERNAL, LOG_ID + "(onUpDateCallEvent)rainbow participant ", call.participants[i].displayNameMD5, " updated with the same : ", contact.displayNameMD5);
}
else {//not the good participant nothing to do
that._logger.log(that.INTERNAL, LOG_ID + "(onUpDateCallEvent) other participant not updated : ", call.participants[i].displayNameMD5, " vs ", contact.displayNameMD5);
}
}
}
call.setCurrentCalled(currentCalled);
}
}
if (contactUpdateDone) {
//that._logger.log(that.INTERNAL, LOG_ID + "(onUpDateCallEvent) send evt_internal_callupdated ", call);
that.eventEmitter.emit("evt_internal_callupdated", call);
/*//CR #28178 : workaround : delay event to avoid notification RBNotification mess !!
// with telescoping with incoming call popup
$interval(function () {
$rootScope.$broadcast("ON_CALL_UPDATED_EVENT", call);
}, 300, 1);
// */
}
else {
that._logger.log(that.DEBUG, LOG_ID + "(onUpDateCallEvent), no update needed for call : ", call.id);
}
});
});
// */
};
/*********************************************************************/
/** FAILURE STUFF **/
/*********************************************************************/
onFailCallEvent (failedElem) {
let that = this;
that._logger.log(that.INTERNAL, LOG_ID + "(onFailCallEvent) _entering_ : ", failedElem);
let cause = failedElem.attr("cause");
//let that = this;
return that.getCall(failedElem).then(async function (call) {
call.setStatus(Call.Status.ERROR);
call.errorMessage = CallFailureLabels[cause];
//call.autoClear = $interval(function () {
await that.telephonyService.clearCall(call);
//}, 5000, 1);
if (!call.errorMessage) {
call.errorMessage = cause;
}
//that._logger.log(that.INTERNAL, LOG_ID + "(onFailCallEvent) send evt_internal_callupdated ", call);
that.eventEmitter.emit("evt_internal_callupdated", call);
//$rootScope.$broadcast("ON_CALL_UPDATED_EVENT", call);
});
// */
};
/*********************************************************************/
/** FORWARD CALL STUFF **/
/*********************************************************************/
onCallForwardedEvent (forwardElem) {
let that = this;
that._logger.log(that.INTERNAL, LOG_ID + "(onCallForwardedEvent) _entering_ : ", forwardElem);
let call = {
"forwardType": forwardElem.attr("forwardType"),
"forwardTo": forwardElem.attr("forwardTo")
};
//that._logger.log(that.INTERNAL, LOG_ID + "(onCallForwardedEvent) send evt_internal_callforwarded ", call);
that.eventEmitter.emit("evt_internal_callforwarded", call);
return Promise.resolve(undefined);
/* $rootScope.$broadcast("ON_CALL_FORWARDED_EVENT", {
"forwardType": forwardElem.attr("forwardType"),
"forwardTo": forwardElem.attr("forwardTo")
});
return $q.when();
// */
};
/*
*/
/*********************************************************************/
/** NOMADIC STATUS STUFF **/
/*********************************************************************/
onNomadicStatusEvent (eventElem) {
let that = this;
that._logger.log(that.INTERNAL, LOG_ID + "(onNomadicStatusEvent) _entering_ : ", eventElem);
let nomadicstate = {
"featureActivated": eventElem.attr("featureActivated"),
"modeActivated": eventElem.attr("modeActivated"),
"destination": eventElem.attr("destination"),
"makeCallInitiatorIsMain": eventElem.attr("makeCallInitiatorIsMain")
};
that.telephonyService.updateNomadicData(nomadicstate);
//that._logger.log(that.DEBUG, LOG_ID + "(onFailCallEvent) send onNomadicStatusEvent ", call);
//that.eventEmitter.emit("onNomadicStatusEvent", call);
return Promise.resolve(undefined);
/* $rootScope.$broadcast("ON_CALL_FORWARDED_EVENT", {
"forwardType": forwardElem.attr("forwardType"),
"forwardTo": forwardElem.attr("forwardTo")
});
return $q.when();
// */
};
/*********************************************************************/
/** VOICE MESSAGES
/*********************************************************************/
async onVoiceMessagesEvent(eventElem) {
let that = this;
/*
*/
//that._logger.log(that.INTERNAL, LOG_ID + "(onVoiceMessagesEvent) _entering_ : ", eventElem);
let infos : any = {};
that._logger.log(that.INTERNAL, LOG_ID + "(onRoomsContainerManagementMessageReceived) _entering_ : ", "\n", eventElem.root ? prettydata.xml(eventElem.root().toString()):eventElem);
let xmlNodeStr = eventElem ? eventElem.toString():"";
let jsonNode = await getJsonFromXML(xmlNodeStr);
that._logger.log(that.DEBUG, LOG_ID + "(onVoiceMessagesEvent) JSON : ", jsonNode);
infos.voiceMessagesCounters = jsonNode["voiceMessages"]?jsonNode["voiceMessages"]["voiceMessagesCounters"]?jsonNode["voiceMessages"]["voiceMessagesCounters"]['$attrs']:undefined:undefined;
/* let nomadicstate = {
"featureActivated": eventElem.attr("featureActivated"),
"modeActivated": eventElem.attr("modeActivated"),
"destination": eventElem.attr("destination"),
"makeCallInitiatorIsMain": eventElem.attr("makeCallInitiatorIsMain")
}; // */
// that.telephonyService.updateNomadicData(nomadicstate);
//that._logger.log(that.DEBUG, LOG_ID + "(onFailCallEvent) send onNomadicStatusEvent ", call);
that.eventEmitter.emit("evt_internal_voicemessagesinfo", infos);
};
/*********************************************************************/
/** PRIVATE UTILITY METHODS **/
/*********************************************************************/
async getCall (elem) {
let that = this;
let jid = elem.getAttr("endpointIm");
let phoneNumber = elem.getAttr("endpointTel");
let connectionId = elem.getAttr("callId");
let deviceType = elem.getAttr("deviceType");
let cause = elem.attr("cause");
let deviceState = elem.attr("deviceState");
let type = elem.attr("type");
let globalCallId = elem.attr("globalCallId");
let correlatorData = elem.attr("correlatorData");
if (!connectionId) {
connectionId = elem.getAttr("heldCallId");
} // TODO: WHY and WHEN
that._logger.log(that.DEBUG, LOG_ID + "(getCall) - ", jid, " - ", Utils.anonymizePhoneNumber(phoneNumber), " - ", connectionId);
that._logger.log(that.INTERNAL, LOG_ID + "(getCall) jid : ", jid, ", phoneNumber : ", phoneNumber, ", connectionId : ", connectionId, ", deviceType : ", deviceType);
let callObj : Call = await that.getOrCreateCall(connectionId, jid, deviceType, phoneNumber);
let updatedinformations: { connectionId?: string,
jid?: string,
deviceType?: string,
phoneNumber?: string,
cause? : string,
deviceState? : string,
type? : string,
globalCallId?: string,
correlatorData?: string
} = {};
if (connectionId != null) {
updatedinformations.connectionId = connectionId;
}
if (jid != null) {
updatedinformations.jid = jid;
}
if (deviceType != null) {
updatedinformations.deviceType = deviceType;
}
if (phoneNumber != null) {
updatedinformations.phoneNumber = phoneNumber;
}
if (cause != null) {
updatedinformations.cause = cause;
}
if (deviceState != null) {
updatedinformations.deviceState = deviceState;
}
if (type != null) {
updatedinformations.cause = type;
}
if (globalCallId != null) {
updatedinformations.globalCallId = globalCallId;
}
if (correlatorData != null) {
updatedinformations.correlatorData = correlatorData;
}
callObj.updateCall(updatedinformations);
// */
return callObj;
};
getOrCreateCall (connectionId, jid, deviceType, phoneNumber ) : Promise {
let that = this;
// let that = this;
let callId = Call.getIdFromConnectionId(connectionId);
let call = that.telephonyService.getCallFromCache(callId);
if (call) {
return Promise.resolve(call);
}
return new Promise(function (resolve) {
if (jid || phoneNumber) {
that.contactService.getOrCreateContact(jid, phoneNumber).then(function (contact) {
resolve(that.telephonyService.getOrCreateCall(Call.Status.UNKNOWN, connectionId, deviceType, contact));
});
}
else {
resolve(that.telephonyService.getOrCreateCall(Call.Status.UNKNOWN, connectionId, deviceType, null));
}
});
// */
};
async createConferenceCall (connectionId, participants) {
let that = this;
let conferenceCall = await that.getOrCreateCall(connectionId, undefined, undefined, undefined);
that._logger.log(that.INTERNAL, LOG_ID + "(createConferenceCall) conferenceCall : ", conferenceCall);
conferenceCall.isConference = true;
conferenceCall.setParticipants(participants);
//that.telephonyService.addOrUpdateCallToCache(conferenceCall)
that._logger.log(that.DEBUG, LOG_ID + "(createConferenceCall) conferenceCall stored : ", that.telephonyService.getCallFromCache(conferenceCall.id));
return conferenceCall;
/*
// Create and configure the conference call
let conferenceCall = Call.create(Call.Status.UNKNOWN, null, Call.Type.PHONE);
conferenceCall.setConnectionId(connectionId);
conferenceCall.isConference = true;
conferenceCall.setParticipants(participants);
this.telephonyService._calls[conferenceCall.id] = conferenceCall;
return conferenceCall;
// */
};
/*********************************************************************/
/** CALL UPDATE STUFF **/
/*********************************************************************/
/**
* Method analyzeContactChange
* Analyse if a setContact has to be done following situation
* @public
* @param jid [required] jid from PCG
* @param phoneNumber [required] phone number from PCG
* @param call [required] the call to update
* @returns object:{ updateContactToBeDone : boolean, searchOutlookToBeDone :boolean}
* updateContactToBeDone true if the contact has to be updated in the call (by setContact)
* searchOutlookToBeDone true if an outlook search has to be performed to resolve call identity
* @memberof TelephonyServiceEventHandler
*/
analyzeContactChange (jid, phoneNumber, call) {
let updateContact = false;
if (!jid && !phoneNumber) { //nothing could be analysed then updated
return null;
}
// One2One Call (not a conference) only call.contact is impacted
if (!call.isConference) {
// No contact... Whatever situation set contact
if (!call.contact) {
return {updateContactToBeDone: true};
//return { updateContactToBeDone: true, searchOutlookToBeDone: false }; //OUTLOOK NOT YET DELIVERED
}
// PCG known the distant as a rainbow user (no outlook search is necessary)
if (jid !== "") {
// Only change if not the same from previous call setting
if (call.contact._id !== jid) {
updateContact = true;
}
}
// No jid available
else {
// call.contact not known as rainbow user, contact._id contain former phoneNumber
if (call.contact.temp) {
if ((call.contact._id !== phoneNumber) //called change
) {
updateContact = true;
}
else if (call.contact.displayName === phoneNumber) {//no change but name not known
updateContact = false;
//searchOutlook = false; //OUTLOOK NOT YET DELIVERED
}
}
// call.contact known as rainbow user update only if phoneNumber change (except ringing empty case)
else if (call.getCurrentCalled().contactPhoneNumber !== "" && phoneNumber !== "") {
if (call.getCurrentCalled().contactPhoneNumber !== phoneNumber) {
updateContact = true;
}
}
}
return (updateContact ) ? {
updateContactToBeDone: updateContact,
} : null;
}
}
/**
* Method updateCallContact
* @public
* @param jid [required] jid from PCG
* @param phoneNumber [required] phone number from PCG
* @param actionElemName [required] name of the action event
* @param call [required] the call to update
* @returns {ng.IPromise<{}>} status promise
* @memberof TelephonyServiceEventHandler
*/
updateCallContact (jid, phoneNumber, actionElemName, call) {
let that = this;
try {
// Determine if the contact has to be updated from event information
let updateAnalyse = that.analyzeContactChange(jid, phoneNumber, call);
// Whatever the contact change, for simple call, after analyse, update at least the call current phoneNumber
if (!call.isConference && phoneNumber !== "") {
call.setCurrentCalledContactNumber(phoneNumber);
}
if (updateAnalyse) {
return that.contactService.getOrCreateContact(jid, phoneNumber)
.then(function (contact) {
that._logger.log(that.INTERNAL, LOG_ID + "(updateCallContact) on ", actionElemName, ", update contact :", contact.displayNameMD5);
that.makeUpdateContact(call, contact, phoneNumber, actionElemName);
return Promise.resolve(undefined);
});
} else {
//that._logger.log(that.INTERNAL, LOG_ID + "(updateCallContact) send evt_internal_callupdated ", call);
that.eventEmitter.emit("evt_internal_callupdated", call);
//$rootScope.$broadcast("ON_CALL_UPDATED_EVENT", call);
return Promise.resolve(undefined);
}
}
catch (error) {
let errorMessage = "updateCallContact -- " + error.message;
// that._logger.log(that.ERROR, LOG_ID + "(updateCallContact) Catch Error !!! ");
that._logger.log(that.ERROR, LOG_ID + "(updateCallContact) Catch Error !!! : ", errorMessage);
return Promise.reject(new Error(errorMessage));
}
}
makeUpdateContact (call, contact, phoneNumber, actionElemName) {
let that = this;
call.setContact(contact);
let currentCalled = {contactPhoneNumber: phoneNumber, contact: contact};
call.setCurrentCalled(currentCalled);
//that._logger.log(that.INTERNAL, LOG_ID + "(makeUpdateContact) send evt_internal_callupdated ", call);
that.eventEmitter.emit("evt_internal_callupdated", call);
/* if (actionElemName === "delivered" && call.status === Call.Status.RINGING_INCOMING) {
//CR #28178 : workaround : delay event to avoid notification RBNotification mess !!
// with telescoping with incoming call popup
$interval(function () {
$rootScope.$broadcast("ON_CALL_UPDATED_EVENT", call);
}, 300, 1);
}
else {
//$interval(function() { $rootScope.$broadcast("ON_CALL_UPDATED_EVENT", call); }, 300, 1);
$rootScope.$broadcast("ON_CALL_UPDATED_EVENT", call);
}
// */
}
}
module.exports.TelephonyEventHandler = TelephonyEventHandler;
export {TelephonyEventHandler};