"use strict";
import {InvitationsService} from "./InvitationsService";
import {XMPPUTils} from "../common/XMPPUtils";
import {ErrorManager} from "../common/ErrorManager";
import {Contact, NameUpdatePrio} from "../common/models/Contact";
import * as util from 'util';
import * as md5 from 'md5';
import * as path from 'path';
import {getRandomInt, isStarted, logEntryExit} from "../common/Utils";
import {PresenceService} from "./PresenceService";
import {EventEmitter} from "events";
import {Logger} from "../common/Logger";
import {Core} from "../Core";
import {PresenceLevel, PresenceRainbow, PresenceShow, PresenceStatus} from "../common/models/PresenceRainbow";
import {Invitation} from "../common/models/Invitation";
import {GenericService} from "./GenericService";
import {PEERTYPE} from "../common/models/Conversation.js";
import {isObject, isString} from "../common/Utils";
let AsyncLock = require('async-lock');
export {};
const LOG_ID = "CONTACTS/SVCE - ";
const API_ID = "API_CALL - ";
class RosterPresenceQueue {
private _logger : Logger;
private _rosterPresenceQueue: any;
private _contactsService : ContactsService;
constructor(_logger : Logger, _contacts: ContactsService) {
let that = this;
that._logger = _logger;
that._contactsService = _contacts;
that._rosterPresenceQueue = [];
// timeout: 5000, Specify timeout - max amount of time an item can remain in the queue before acquiring the lock
// maxPending: 1000, Set max pending tasks - max number of tasks allowed in the queue at a time
// maxOccupationTime : 3000 Specify max occupation time - max amount of time allowed between entering the queue and completing execution
that.lockEngine = new AsyncLock({timeout: 3 * 60 * 1000, maxPending: 1000, maxOccupationTime : 5 * 60 * 1000});
}
//region Lock
async lock(fn, id) {
let that = this;
let resultLock = "Lock failed.";
try {
that._logger.log(that._contactsService.INTERNAL, LOG_ID + "(lock) - id : ", id, " - will acquire lock the ", that.lockKey);
await that.lockEngine.acquire(that.lockKey, async () => {
// that._logger.log(that._contacts.DEBUG, LOG_ID + "(lock) lock the ", that.lockKey);
that._logger.log(that._contactsService.INTERNAL, LOG_ID + "(lock) - id : ", id, " - lock the ", that.lockKey);
let result = undefined;
try {
result = await fn(); // async work
return result;
} catch (err3) {
that._logger.log(that._contactsService.ERROR, LOG_ID + "(lock) - id : ", id, " - CATCH Error !!! error at run : ", that.lockKey, ", error : ", err3);
}
}).then((result) => {
// that._logger.log(that.DEBUG, LOG_ID + "(lock) release the ", that.lockKey);
that._logger.log(that._contactsService.INTERNAL, LOG_ID + "(lock) - id : ", id, " - release the ", that.lockKey, ", result : ", result);
resultLock = result;
}).catch((err2) => {
that._logger.log(that._contactsService.WARN, LOG_ID + "(lock) - id : ", id, " - catch at acquire : ", that.lockKey, ", error : ", err2);
throw resultLock = err2;
}
);
} catch (err) {
that._logger.log(that._contactsService.ERROR, LOG_ID + "(lock) - id : ", id, " - CATCH Error !!! error at acquire : ", that.lockKey, ", error : ", err);
throw resultLock = err;
}
that._logger.log(that._contactsService.INTERNAL, LOG_ID + "(lock) - id : ", id, " - __ exiting __ ", that.lockKey, ", resultLock : ", resultLock);
return resultLock;
}
//endregion Lock
add( presenceToSave : {presence : any, date: any }){
let that = this;
let id = (new Date()).getTime();
that._logger.log(that._contactsService.INTERNAL, LOG_ID + "(add) - id : ", id, " - will lock.");
that.lock(() => {
that._logger.log(that._contactsService.INTERNAL, LOG_ID + "(add) - id : ", id, " - will call fn for presence.jid : ", presenceToSave.presence.jid);
this._rosterPresenceQueue.push(presenceToSave);
}, id).then(() => {
that._logger.log(that._contactsService.DEBUG, LOG_ID + "(add) - id : ", id, " - lock succeed.");
}).catch((error) => {
that._logger.log(that._contactsService.ERROR, LOG_ID + "(add) - id : ", id, " - Catch Error, error : ", error);
});
}
treatPresenceForContact(contact: any, fn) {
let that = this;
let id = (new Date()).getTime();
that._logger.log(that._contactsService.INTERNAL, LOG_ID + "(treatPresenceForContact) - id : ", id, " - will lock.");
that.lock(() => {
that._rosterPresenceQueue.filter(presenceItem => presenceItem.presence.jid===contact.jid).forEach(item => {
that._logger.log(that._contactsService.INTERNAL, LOG_ID + "(treatPresenceForContact) - id : ", id, " - will call treat presence : ", item.presence, " for contact.jid : ", contact.jid);
fn(item.presence);
});
let currentDate = Date.now();
that._rosterPresenceQueue = that._rosterPresenceQueue.filter(presenceItem => presenceItem.presence.jid!==contact.jid || (presenceItem.date + 10000) < currentDate);
}, id).then(() => {
that._logger.log(that._contactsService.DEBUG, LOG_ID + "(treatPresenceForContact) - id : ", id, " - lock succeed.");
}).catch((error) => {
that._logger.log(that._contactsService.ERROR, LOG_ID + "(treatPresenceForContact) - id : ", id, " - Catch Error, error : ", error);
});
}
treatPresenceForAllContacts(fn) {
let that = this;
let id = (new Date()).getTime();
that._logger.log(that._contactsService.INTERNAL, LOG_ID + "(treatPresenceForAllContacts) - id : ", id, " - will lock.");
that.lock(() => {
that._rosterPresenceQueue.forEach(item => {
that._logger.log(that._contactsService.INTERNAL, LOG_ID + "(treatPresenceForAllContacts) - id : ", id, " - will call fn for presence.jid : ", item.presence.jid);
fn(item.presence);
});
let currentDate = Date.now();
that._rosterPresenceQueue = [];
}, id).then(() => {
that._logger.log(that._contactsService.DEBUG, LOG_ID + "(treatPresenceForAllContacts) - id : ", id, " - lock succeed.");
}).catch((error) => {
that._logger.log(that._contactsService.ERROR, LOG_ID + "(treatPresenceForAllContacts) - id : ", id, " - Catch Error, error : ", error);
});
}
remove(contact) {
let that = this;
let id = (new Date()).getTime();
that.lock(() => {
let currentDate = Date.now();
that._rosterPresenceQueue = that._rosterPresenceQueue.filter(presenceItem => presenceItem.presence.jid!==contact.jid || (presenceItem.date + 10000) < currentDate);
}, id).then(() => {
that._logger.log(that._contactsService.DEBUG, LOG_ID + "(remove) - id : ", id, " - lock succeed.");
}).catch((error) => {
that._logger.log(that._contactsService.ERROR, LOG_ID + "(remove) - id : ", id, " - Catch Error, error : ", error);
});
}
private lockEngine: any;
private lockKey = "LOCK_ROSTER_QUEUE";
}
@logEntryExit(LOG_ID)
@isStarted([])
/**
* @module
* @name ContactsService
* @version SDKVERSION
* @public
* @description
* This module manages _contacts. A contact is defined by a set of public information (name, firstname, avatar...) and a set of private information.
* Using this module, you can get access to your network _contacts or search for Rainbow _contacts.
*
* The main methods proposed in that module allow to:
* - Get the network _contacts (roster)
* - Get and search _contacts by Id, JID or loginEmail
*/
class ContactsService extends GenericService {
private avatarDomain: any;
private _contacts: Array;
public userContact: Contact;
private _rosterPresenceQueue: RosterPresenceQueue;
private _rosterPresenceQueue3: any;
private _invitationsService: InvitationsService;
private _presenceService: PresenceService;
//private _logger: Logger;
static getClassName() { return 'ContactsService'; }
getClassName() { return ContactsService.getClassName(); }
static getAccessorName(){ return 'contacts'; }
getAccessorName(){ return ContactsService.getAccessorName(); }
constructor(_core:Core, _eventEmitter: EventEmitter, _http: any, _logger: Logger, _startConfig: {
start_up:boolean,
optional:boolean
}) {
super(_logger, LOG_ID, _eventEmitter);
this.setLogLevels(this);
this._startConfig = _startConfig;
this.avatarDomain = _http.host.split(".").length===2 ? _http.protocol + "://cdn." + _http.host + ":" + _http.port:_http.protocol + "://" + _http.host + ":" + _http.port;
this._xmpp = null;
this._rest = null;
this._s2s = null;
this._options = {};
this._useXMPP = false;
this._useS2S = false;
this._contacts = [];
this._eventEmitter = _eventEmitter;
this._logger = _logger;
//this._rosterPresenceQueue3 = [];
this._rosterPresenceQueue = new RosterPresenceQueue(_logger, this);
this.userContact = new Contact();
this._core = _core;
this._eventEmitter.on("evt_internal_presencechanged", this._onPresenceChanged.bind(this));
this._eventEmitter.on("evt_internal_onrosterpresence", this._onRosterPresenceChanged.bind(this));
this._eventEmitter.on("evt_internal_onrostercontactinformationchanged", this._onRosterContactInfoChanged.bind(this));
this._eventEmitter.on("evt_internal_oncontactinformationchanged", this._onContactInfoChanged.bind(this));
// this._eventEmitter.on("evt_internal_userinvitemngtreceived", this._onUserInviteReceived.bind(this));
// this._eventEmitter.on("evt_internal_userinviteaccepted", this._onUserInviteAccepted.bind(this));
// this._eventEmitter.on("evt_internal_userinvitecanceled", this._onUserInviteCanceled.bind(this));
this._eventEmitter.on("evt_internal_onrosters", this._onRostersUpdate.bind(this));
this._eventEmitter.on("evt_internal_rainbowcpaasreceived", this._onrainbowcpaasreceived.bind(this));
this._eventEmitter.on("evt_internal_userpasswordconfig", this._onuserpasswordconfig.bind(this));
}
start(_options) { // , _xmpp : XMPPService, _s2s : S2SService, _rest : RESTService, _invitationsService : InvitationsService, _presenceService : PresenceService
let that = this;
that.initStartDate();
return new Promise(function (resolve, reject) {
try {
that._xmpp = that._core._xmpp;
that._rest = that._core._rest;
that._options = _options;
that._s2s = that._core._s2s;
that._useXMPP = that._options.useXMPP;
that._useS2S = that._options.useS2S;
that._invitationsService = that._core.invitations;
that._presenceService = that._core.presence;
that._contacts = [];
// Create the user contact
that._logger.log(that.DEBUG, LOG_ID + "(start) Create userContact (" + that._xmpp.jid + ")");
that.userContact = new Contact();
that.userContact.ask = null;
that.userContact.subscription = null;
// Attach _xmpp information (check)
that.userContact._id = that._xmpp.jid;
that.userContact.jid = that._xmpp.jid;
that.userContact.jidtel = "tel_" + that._xmpp.jid;
that.userContact.jid_im = that._xmpp.jid;
that.userContact.jid_tel = "tel_" + that._xmpp.jid;
//that.userContact.fullJid = that._xmpp.fullJid;
that.setStarted ();
resolve(undefined);
} catch (err) {
that._logger.log(that.ERROR, LOG_ID + "(start) Catch ErrorManager !!!");
that._logger.log(that.INTERNALERROR, LOG_ID + "(start) Catch ErrorManager !!! : ", err.message);
return reject(err);
}
});
}
stop() {
let that = this;
return new Promise(function (resolve, reject) {
try {
that._xmpp = null;
that._rest = null;
that._contacts = [];
that.setStopped ();
resolve(undefined);
} catch (err) {
return reject();
}
});
}
init(useRestAtStartup : boolean) {
return new Promise(async(resolve, reject) => {
let that = this;
if (that._rest.account) {
if (that._rest.account.id) {
let userInfo = that.getContactById(that._rest.account.id, true);
await Promise.all([userInfo]).then((contact: Contact[]) => {
//that._logger.log(that.INTERNAL, LOG_ID + "(init) before updateFromUserData ", contact);
if (contact) {
// Create the contact object
that.userContact.updateFromUserData(contact[0]);
//that.userContact.updateFromUserData(that._rest.account);
that.userContact.avatar = that.getAvatarByContactId(that._rest.account.id, that._rest.account.lastAvatarUpdateDate);
//that.userContact.status = that._presenceService.getUserConnectedPresence().presenceStatus;
//that.userContact.presence = that._presenceService.getUserConnectedPresence().presenceLevel;
}
that.setInitialized();
//return resolve(undefined);
}).catch((err) => {
//return resolve(undefined);
//return reject();
that._logger.log(that.ERROR, LOG_ID + "(init) getContactById failed : ", err);
});
return resolve();
}
if (that._rest.account.jid_im) {
let userInfo = await that._rest.getAllUsersByFilter(undefined, undefined,undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined,
undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined,
undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined,
undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined,
undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, that._rest.account.jid_im, undefined)
.then((result) => {
that._logger.log(that.INTERNAL, LOG_ID + "(init) search by jid_im result : ", result);
that.userContact.updateFromUserData(that._rest.account);
that.userContact.avatar = that.getAvatarByContactId(that._rest.account.id, that._rest.account.lastAvatarUpdateDate);
});
/* .then((contact: Contact) => {
//that._logger.log(that.INTERNAL, LOG_ID + "(init) before updateFromUserData ", contact);
that.userContact.updateFromUserData(contact);
});
// */
await Promise.all([userInfo]).then(() => {
that.setInitialized();
//resolve(undefined);
}).catch((err) => {
that._logger.log(that.WARN, LOG_ID + "(init) search by jid_im failed with error : ", err);
that.setInitialized();
//resolve(undefined);
//return reject();
});
}
} else {
that._logger.log(that.INTERNAL, LOG_ID + "(init) else from contact : ", that._rest.account);
that.setInitialized();
//resolve(undefined);
}
return resolve();
});
}
cleanMemoryCache() {
let that = this;
super.cleanMemoryCache();
for (let i = 0; i < that._contacts.length ; i++) {
if (that._contacts[i]) {
if ( that._contacts[i].isObsoleteCache()) {
that._logger.log(that.INFO, LOG_ID + "(cleanMemoryCache) contact obsolete. Will remove it from cache.");
that._logger.log(that.INTERNAL, LOG_ID + "(cleanMemoryCache) contact obsolete. Will remove it from cache : ", that._contacts[i]);
that._contacts.splice(i,1);
i--;
} else {
that._logger.log(that.INFO, LOG_ID + "(cleanMemoryCache) contact not obsolete.");
that._logger.log(that.INTERNAL, LOG_ID + "(cleanMemoryCache) contact not obsolete : ", that._contacts[i]);
}
} else {
that._logger.log(that.INFO, LOG_ID + "(cleanMemoryCache) contact empty, so it is obsolete. Will remove it from cache.");
that._contacts.splice(i,1);
i--;
}
}
}
//region Contacts MANAGEMENT
createEmptyContactContact(jid : string) {
let that = this;
let contact = that.createBasicContact(jid);
contact.initials = "?";
contact.displayName = "Unknown contact";
contact.lastName = "Unknown contact";
contact.firstName = "";
contact.temp = true;
contact.avatar = {};//new Image();
contact.avatar.src = "/resources/skins/rainbow/images/conversations/unknownContact.png";
return contact;
}
getContact(jid : string, phoneNumber : string) {
let that = this;
let contact: any;
contact = null;
let contactId = jid ? jid:phoneNumber;
if (that.isUserContactJid(contactId)) {
// Create the contact object
contact = new Contact();
// that._logger.log(that.INTERNAL, LOG_ID + "(getContact) before updateFromUserData ", contact);
contact.updateFromUserData(that._rest.account);
contact.status = that._presenceService.getUserConnectedPresence().presenceDetails;
contact.presence = that._presenceService.getUserConnectedPresence().presenceLevel;
} else {
contact = that._contacts.find((_contact) => _contact.jid_im===contactId);
}
return contact;
}
getOrCreateContact(jid : string, phoneNumber : string) {
let that = this;
// Reject stupid request
if (!jid && !phoneNumber) {
let error = ErrorManager.getErrorManager().BAD_REQUEST;
error.msg += " No jid or no phoneNumber";
return Promise.reject(error);
}
// Initialize contactsArray if necessary
if (!this._contacts) {
this._contacts = [];
}
// Try to find an existing contact
let contact = this.getContact(jid, phoneNumber);
// If contact found, return resolved promise with contact
if (contact) {
return Promise.resolve(contact);
}
// Else create the contact
contact = that.createBasicContact(jid, phoneNumber);
// Handle case where we have no jid
if (!jid) {
return Promise.resolve(contact);
}
// Fill contact with vCard informations
return that._rest.getContactInformationByJID(jid).then((_contactFromServer: any) => {
let contactIndex = that._contacts.findIndex((value) => {
return value.jid_im===_contactFromServer.jid_im;
});
if (contactIndex!== -1) {
contact = that._contacts[contactIndex];
}
//that._logger.log(that.INTERNAL, LOG_ID + "(getOrCreateContact) before updateFromUserData ", contact);
contact.updateFromUserData(_contactFromServer);
contact.avatar = that.getAvatarByContactId(_contactFromServer.id, _contactFromServer.lastAvatarUpdateDate);
//that._contacts.push(contact);
return Promise.resolve(contact);
});
}
createBasicContact(jid : string, phoneNumber? : string) {
let that = this;
that._logger.log(that.DEBUG, LOG_ID + "[contactService] CreateContact " + jid + " " /* TODO + anonymizePhoneNumber(phoneNumber) */);
// Create the contact object
let contact = new Contact();
// Handle case where we have no jid
if (!jid) {
contact.id = phoneNumber;
contact._id = phoneNumber;
contact.initials = "?";
contact.displayName = phoneNumber ? phoneNumber:"Unknown contact";
contact.lastName = phoneNumber ? phoneNumber:"Unknown contact";
contact.firstName = "";
contact.phoneProCan = phoneNumber ? phoneNumber:"";
contact.temp = true;
contact.loginEmail = "noEmail";
contact.avatar = {}; // new Image();
contact.avatar.src = "/resources/skins/rainbow/images/conversations/unknownContact.png";
contact.setNameUpdatePrio(NameUpdatePrio.NO_UPDATE_PRIO);//not yet updated
return contact;
}
// Compute the contact id
let contactId = jid;
if (!contactId) {
contactId = phoneNumber;
contact.phoneProCan = phoneNumber;
}
if (!contactId) {
contactId = "anonymous";
}
// Configure contact
contact.jid = jid;
contact.jid_im = jid;
contact.jidtel = "tel_" + jid;
contact.id = contactId;
contact._id = jid;
contact.ask = "none";
contact.subscription = "none";
// TODO ? contact.updateRichStatus();
contact.roster = false;
contact.presence = "offline";
contact.status = "";
// Append in contact list
// that._contacts[contact.id] = contact;
that._contacts.push(contact);
return contact;
}
/**
* @private
* @name getContactIdByCriteria
* @param {string|Object} info it can be a string (for a `jid` or an `email`) or a `Contact` to retrieve an id.
* @param {string} typeInfo="jid" if the `info` parameter is a string, it is possible to specify the kind of info. Possible values : "jid"
* @instance
* @description
* this method allows retrieving a contact id
*
* WARNING : this method is not finished ! Issue to make difference between email and jid.
* @returns {Promise}
*
*/
async getContactIdByCriteria(info:any, typeInfo : string = "jid") : Promise {
let that = this;
let id : string="";
if (isObject(info)) {
// it is an object so get id in it
id = info.id;
} else
if (isString(info)) {
//const emailRegex = /[\w.-]+@[\w.-]+\.\w+/; // const info = "Voici mon mail : vincent@test.com";
const strictEmailRegex = /^[\w.-]+@[\w.-]+\.\w+$/; // const info = "vincent@test.com";
if (strictEmailRegex.test(info)) {
//console.log("Email détecté !");
typeInfo = "email";
}
switch (typeInfo) {
case "jid":
case "JID":
id = (await that.getContactByJid(info).catch((err)=>{ that._logger.log(that.ERROR, LOG_ID + "(getContactIdByCriteria) getContactByJid failed : ", err); return undefined;}))?.id;
break;
case "email":
case "EMAIL":
id = await that.getContactIdByLoginEmail(info);
break;
default:
id = info;
break;
}
} else {
id = info;
}
return id;
}
//endregion Contacts MANAGEMENT
//region Contacts INFORMATION
/**
* @public
* @nodered true
* @method getAll
* @category Contacts INFORMATION
* @instance
* @return {Contact[]} the list of _contacts
* @description
* Return the list of _contacts in cache that are in the network of the connected users (aka rosters)
*/
getAll() : Array{
let that = this;
that._logger.log(that.INFOAPI, LOG_ID + API_ID + "(getAll) .");
return this._contacts?this._contacts.filter(contact => contact.roster):[];
}
/**
* @public
* @nodered true
* @method getAllContactsInCache
* @category Contacts INFORMATION
* @instance
* @return {Contact[]} the list of _contacts
* @description
* Return the list of _contacts that are in the cache of the current instance of the connected users.
* `Note:` the stored contacts can be or not in the network. Rainbow SDK only receives event of contacts in the network.
* So others are only cache about previous exchange, and are cleaned with the clean memory process. The cleaning interval is defined by "intervalBetweenCleanMemoryCache" SDK's option.
*/
getAllContactsInCache() : Array{
let that = this;
that._logger.log(that.INFOAPI, LOG_ID + API_ID + "(getAllContactsInCache) .");
return this._contacts;
}
/**
* @public
* @nodered true
* @method getContactByJid
* @instance
* @category Contacts INFORMATION
* @param {string} jid The contact jid
* @param {boolean} forceServerSearch=false Boolean to force the search of the _contacts information on the server.
* @description
* Get a contact by his JID by searching in the connected user _contacts list (full information) and if not found by searching on the server too (limited set of information)
* @async
* @return {Promise}
* @fulfil {Contact} - Found contact or null or an error object depending on the result
*/
getContactByJid(jid : string, forceServerSearch : boolean = false): Promise {
let that = this;
that._logger.log(that.INFOAPI, LOG_ID + API_ID + "(getContactByJid) jid : ", that._logger.stripStringForLogs(jid), ", forceServerSearch : ", forceServerSearch);
return new Promise((resolve, reject) => {
if (!jid) {
that._logger.log(that.WARN, LOG_ID + "(getContactByJid) bad or empty 'jid' parameter", jid);
return reject(ErrorManager.getErrorManager().BAD_REQUEST);
} else {
let contactFound = null;
let connectedUserJid = that._rest.account.jid_im;
if (that._contacts && !forceServerSearch) {
contactFound = that._contacts.find((contact) => {
return contact.jid_im===jid;
});
}
if (contactFound) {
that._logger.log(that.DEBUG, LOG_ID + "(getContactByJid) contact found locally with jid ", jid);
if (contactFound.jid_im===connectedUserJid) {
let connectedUser = that.getConnectedUser() ? that.getConnectedUser():new Contact();
resolve(connectedUser);
} else {
resolve(contactFound);
}
} else {
that._logger.log(that.DEBUG, LOG_ID + "(getContactByJid) contact not found locally. Ask the server...");
return that._rest.getContactInformationByJID(jid).then((_contactFromServer: any) => {
let contact = null;
if (_contactFromServer) {
that._logger.log(that.DEBUG, LOG_ID + "(getContactByJid) contact found on the server.");
//that._logger.log(that.INTERNAL, LOG_ID + "(getContactByJid) contact found on the server : ", _contactFromServer);
let contactIndex = that._contacts.findIndex((value) => {
return value.jid_im===_contactFromServer.jid_im;
});
if (contactIndex!== -1) {
contact = that._contacts[contactIndex];
that._logger.log(that.INTERNAL, LOG_ID + "(getContactByJid) contact found on local _contacts - contact id : ", contact.id, ", contact.displayName : ", contact.displayName, " for contact.jid : ", contact.jid);
} else {
contact = that.createBasicContact(_contactFromServer.jid_im, undefined);
}
//that._logger.log(that.INTERNAL, LOG_ID + "(getContactByJid) before updateFromUserData ", contact);
contact.updateFromUserData(_contactFromServer);
contact.avatar = that.getAvatarByContactId(_contactFromServer.id, _contactFromServer.lastAvatarUpdateDate);
if (contact.jid_im===connectedUserJid) {
contact.status = that._presenceService.getUserConnectedPresence().presenceDetails;
contact.presence = that._presenceService.getUserConnectedPresence().presenceLevel;
}
} else {
that._logger.log(that.INFO, LOG_ID + "(getContactByJid) no contact found on the server with Jid", jid);
}
return resolve(contact);
}).catch((err) => {
return reject(err);
});
}
}
});
}
/**
* @public
* @nodered true
* @method getContactById
* @instance
* @category Contacts INFORMATION
* @param {string} id The contact id
* @param {boolean} forceServerSearch=false Boolean to force the search of the _contacts information on the server.
* @description
* Get a contact by his id
* @async
* @return {Promise}
* @fulfil {Contact} - Found contact or null or an error object depending on the result
*/
getContactById(id : string, forceServerSearch: boolean = false): Promise {
let that = this;
that._logger.log(that.INFOAPI, LOG_ID + API_ID + "(getContactById) id : ", that._logger.stripStringForLogs(id), ", forceServerSearch : ", forceServerSearch);
return new Promise((resolve, reject) => {
if (!id) {
that._logger.log(that.WARN, LOG_ID + "(getContactById) bad or empty 'id' parameter", id);
return reject(ErrorManager.getErrorManager().BAD_REQUEST);
} else {
let contactFound = null;
let connectedUserId = that._rest.account.id;
if (that._contacts && !forceServerSearch) {
contactFound = that._contacts.find((contact) => {
return contact.id===id;
});
}
if (contactFound) {
that._logger.log(that.INTERNAL, LOG_ID + "(getContactById) contact found locally - contactFound id : ", contactFound.id, ", contactFound.displayName : ", contactFound.displayName, " for contact.jid : ", contactFound.jid);
if (contactFound.id===connectedUserId) {
let connectedUser = that.getConnectedUser() ? that.getConnectedUser():new Contact();
return resolve(connectedUser);
} else {
return resolve(contactFound);
}
} else {
that._logger.log(that.DEBUG, LOG_ID + "(getContactById) contact not found locally. Ask the server...");
return that._rest.getContactInformationByID(id).then((_contactFromServer: any) => {
let contact: Contact = null;
if (_contactFromServer) {
that._logger.log(that.INTERNAL, LOG_ID + "(getContactById) contact found on the server : ", _contactFromServer);
that._logger.log(that.INFO, LOG_ID + "(getContactById) contact found on the server");
let contactIndex = that._contacts.findIndex((value) => {
return value.jid_im===_contactFromServer.jid_im;
});
if (contactIndex!== -1) {
//that._logger.log(that.INFO, LOG_ID + "(getContactById) contact found on local _contacts", contact);
that._logger.log(that.INFO, LOG_ID + "(getContactById) contact found on local _contacts");
contact = that._contacts[contactIndex];
} else {
contact = that.createBasicContact(_contactFromServer.jid_im, undefined);
}
//that._logger.log(that.INTERNAL, LOG_ID + "(getContactById) before updateFromUserData ", contact);
contact.updateFromUserData(_contactFromServer);
contact.avatar = that.getAvatarByContactId(_contactFromServer.id, _contactFromServer.lastAvatarUpdateDate);
if (contact.id===connectedUserId) {
contact.status = that._presenceService.getUserConnectedPresence().presenceStatus;
contact.presence = that._presenceService.getUserConnectedPresence().presenceLevel;
}
} else {
that._logger.log(that.INFO, LOG_ID + "(getContactById) no contact found on server with id", id);
}
return resolve(contact);
}).catch((err) => {
return reject(err);
});
}
}
});
}
/**
* @public
* @nodered true
* @method getContactByLoginEmail
* @instance
* @category Contacts INFORMATION
* @param {string} loginEmail The contact loginEmail
* @param {boolean} forceServerSearch=false Boolean to force the search of the _contacts information on the server.
* @description
* Get a contact by his loginEmail
* @async
* @return {Promise}
* @fulfil {Contact} - Found contact or null or an error object depending on the result
*
*/
async getContactByLoginEmail(loginEmail : string, forceServerSearch: boolean = false): Promise {
let that = this;
that._logger.log(that.INFOAPI, LOG_ID + API_ID + "(getContactByLoginEmail) loginEmail : ", that._logger.stripStringForLogs(loginEmail), ", forceServerSearch : ", forceServerSearch);
return new Promise((resolve, reject) => {
if (!loginEmail) {
that._logger.log(that.WARN, LOG_ID + "(getContactByLoginEmail) bad or empty 'loginEmail' parameter");
that._logger.log(that.INTERNALERROR, LOG_ID + "(getContactByLoginEmail) bad or empty 'loginEmail' parameter : ", loginEmail);
return reject(ErrorManager.getErrorManager().BAD_REQUEST);
} else {
let contactFound: Contact = null;
let connectedUser = that.getConnectedUser() ? that.getConnectedUser():new Contact();
if (that._contacts && !forceServerSearch) {
contactFound = that._contacts.find((contact) => {
return contact.loginEmail===loginEmail;
});
}
if (contactFound) {
that._logger.log(that.INTERNAL, LOG_ID + "(getContactByLoginEmail) contact found locally - contactFound id : ", contactFound.id, ", contactFound.displayName : ", contactFound.displayName, " for contact.jid : ", contactFound.jid);
if (contactFound.id===connectedUser.id) {
resolve(connectedUser);
} else {
resolve(contactFound);
}
} else {
that._logger.log(that.DEBUG, LOG_ID + "(getContactByLoginEmail) contact not found locally. Ask server...");
that._rest.getContactInformationByLoginEmail(loginEmail).then(async (contactsFromServeur: [any]) => {
if (contactsFromServeur && contactsFromServeur.length > 0) {
let contact: Contact = null;
that._logger.log(that.INFO, LOG_ID + "(getContactByLoginEmail) contact found on server");
let _contactFromServer = contactsFromServeur[0];
if (_contactFromServer) {
// The contact is not found by email in the that._contacts tab, so it need to be find on server to get or update it.
await that.getContactById(_contactFromServer.id, true).then((contactInformation: Contact) => {
contact = contactInformation;
// Workaround because server does not return the email when not in same company, even if it has been found by email on server.
if (!contact.loginEmail) {
contact.loginEmail = loginEmail;
}
that._logger.log(that.INTERNAL, LOG_ID + "(getContactByLoginEmail) full data contact - contact id : ", contact.id, ", contact.displayName : ", contact.displayName, " for contact.jid : ", contact.jid, ", found on server with loginEmail : ", loginEmail);
/*let contactIndex = that._contacts.findIndex((value) => {
return value.jid_im === contactInformation.jid_im;
});
if (contactIndex !== -1) {
contact = that._contacts[contactIndex];
} else {
contact = that.createBasicContact(contactInformation.jid_im, undefined);
}
//that._logger.log(that.INTERNAL, LOG_ID + "(getContactByLoginEmail) before updateFromUserData ", contact);
contact.updateFromUserData(contactInformation);
contact.avatar = that.getAvatarByContactId(contactInformation.id, contactInformation.lastAvatarUpdateDate);
*/
if (contact.loginEmail===connectedUser.loginEmail) {
contact.status = that._presenceService.getUserConnectedPresence().presenceStatus;
contact.presence = that._presenceService.getUserConnectedPresence().presenceLevel;
}
}).catch((err)=>{ that._logger.log(that.ERROR, LOG_ID + "(getContactByLoginEmail) getContactById failed : ", err); return undefined;});
} else {
that._logger.log(that.INTERNAL, LOG_ID + "(getContactByLoginEmail) no contact found on server with loginEmail : ", loginEmail);
}
resolve(contact);
} else {
that._logger.log(that.INTERNAL, LOG_ID + "(getContactByLoginEmail) contact not found on server with loginEmail : ", loginEmail);
resolve(null);
}
}).catch((err) => {
return reject(err);
});
}
}
});
}
/**
* @public
* @nodered true
* @method getContactIdByLoginEmail
* @instance
* @category Contacts INFORMATION
* @param {string} loginEmail The contact loginEmail
* @param {boolean} forceServerSearch=false Boolean to force the search of the _contacts information on the server.
* @description
* Get a contact Id by his loginEmail
* @async
* @return {Promise}
* @fulfil {string} - Found contact Id or null or an error object depending on the result
*/
async getContactIdByLoginEmail(loginEmail : string, forceServerSearch: boolean = false): Promise {
let that = this;
that._logger.log(that.INFOAPI, LOG_ID + API_ID + "(getContactIdByLoginEmail) loginEmail : ", that._logger.stripStringForLogs(loginEmail), ", forceServerSearch : ", forceServerSearch);
return new Promise((resolve, reject) => {
if (!loginEmail) {
that._logger.log(that.WARN, LOG_ID + "(getContactByLoginEmail) bad or empty 'loginEmail' parameter");
that._logger.log(that.INTERNALERROR, LOG_ID + "(getContactByLoginEmail) bad or empty 'loginEmail' parameter : ", loginEmail);
return reject(ErrorManager.getErrorManager().BAD_REQUEST);
} else {
let contactFound: Contact = null;
let connectedUser = that.getConnectedUser() ? that.getConnectedUser():new Contact();
if (that._contacts && !forceServerSearch) {
contactFound = that._contacts.find((contact) => {
return contact.loginEmail===loginEmail;
});
}
if (contactFound) {
that._logger.log(that.INTERNAL, LOG_ID + "(getContactByLoginEmail) contact found locally - contactFound id : ", contactFound.id, ", contactFound.displayName : ", contactFound.displayName, " for contact.jid : ", contactFound.jid);
resolve(contactFound.id);
} else {
that._logger.log(that.DEBUG, LOG_ID + "(getContactByLoginEmail) contact not found locally. Ask server...");
that._rest.getContactInformationByLoginEmail(loginEmail).then(async (contactsFromServeur: [any]) => {
let contactId: string = undefined;
if (contactsFromServeur && contactsFromServeur.length > 0) {
//let contact: Contact = null;
that._logger.log(that.INFO, LOG_ID + "(getContactByLoginEmail) contact found on server");
let _contactFromServer = contactsFromServeur[0];
if (_contactFromServer) {
contactId = _contactFromServer.id;
} else {
that._logger.log(that.INTERNAL, LOG_ID + "(getContactByLoginEmail) no contact found on server with loginEmail : ", loginEmail);
}
} else {
that._logger.log(that.INTERNAL, LOG_ID + "(getContactByLoginEmail) contact not found on server with loginEmail : ", loginEmail);
}
resolve(contactId);
}).catch((err) => {
return reject(err);
});
}
}
});
}
/**
* @public
* @nodered true
* @method getMyInformations
* @instance
* @category Contacts INFORMATION
* @description
* Get information about the connected user
* @async
* @return {Promise