"use strict"; import {Logger} from "../common/Logger"; import { isDefinedAndNotEmpty, isNotDefined, isNotDefinedOrEmpty, toBoolean, updateObjectPropertiesFromAnOtherObject } from "../common/Utils"; export {}; //const config = require("./config"); import {config, DataStoreType} from "./config"; import {isDefined, loadConfigFromIniFile, saveConfigFromIniFile} from "../common/Utils.js"; import {XMPPUTils} from "../common/XMPPUtils"; const xmppUtils = XMPPUTils.getXMPPUtils(); const LOG_ID = "OPTIONS - "; class Options { public _logger: Logger; public _options: any; //OptionsType; public _hasCredentials: any; public _hasApplication: any; public _httpOptions: any; public _xmppOptions: any; public _s2sOptions: any; public _restOptions: any; public _proxyoptions: any; public _imOptions: any; public _applicationOptions: any; public _withXMPP: any; public _withS2S: any; public _CLIMode: any; public _servicesToStart: any; private _testOutdatedVersion: boolean; private _testDNSentry: boolean; private _autoReconnectIgnoreErrors: boolean; private _httpoverxmppserver: boolean; private _concurrentRequests: number; private _intervalBetweenCleanMemoryCache: number; private _requestsRate: any; private _configIniData: any; constructor(_options: any, _logger: Logger) { this._logger = _logger; this._options = _options; this._hasCredentials = true; this._hasApplication = true; this._withXMPP = true; this._withS2S = false; this._CLIMode = true; this._testOutdatedVersion = true; this._testDNSentry = true; this._autoReconnectIgnoreErrors = false; this._httpoverxmppserver = false; this._intervalBetweenCleanMemoryCache = 1000 * 60 * 60 * 6; // Every 6 hours this._configIniData = {}; } parse() { this._configIniData = loadConfigFromIniFile(); if (!this._options) { this._logger.log("error", LOG_ID + "(constructor) No 'options' parameter. Can't sign-in. Check the documentation to configure it"); this._hasCredentials = false; } if (!this._options.rainbow || !this._options.rainbow.host) { this._logger.log("warn", LOG_ID + "(constructor) 'host' property is not defined. Use default: 'sandbox'. Check the documentation to configure it"); this._options.rainbow = {host: "sandbox", mode: "xmpp"}; } if (!this._options.proxy) { this._logger.log("debug", LOG_ID + "(constructor) 'proxy' property is not defined. Use default: no proxy. Check the documentation to enable it"); this._options.proxy = {}; // this._options.proxy = {host: "", protocol: "http", port: 80, user : undefined, password : undefined, secureProtocol: undefined}; } if (!this._options.credentials) { this._logger.log("error", LOG_ID + "(constructor) 'credentials' property is not defined. Can't sign-in. Check the documentation to configure it"); this._hasCredentials = false; } else if (( this._options.credentials.login || this._options.credentials.password ) && isNotDefined(this._options.credentials.apikey)) { this._logger.log("info", LOG_ID + "(constructor) 'credentials' property is defined. login."); this._hasCredentials = true; } else if (( !this._options.credentials.login || !this._options.credentials.password ) && isDefined(this._options.credentials.apikey)) { this._logger.log("info", LOG_ID + "(constructor) 'credentials' property is defined. apikey."); this._hasCredentials = true; } else if (( !this._options.credentials.login || !this._options.credentials.password ) && isNotDefined(this._options.credentials.apikey)) { this._logger.log("error", LOG_ID + "(constructor) 'login' or 'password' is not defined. Can't sign-in. Check the documentation to configure it"); this._hasCredentials = false; } else if (isNotDefined(this._options.credentials.apikey)) { this._logger.log("error", LOG_ID + "(constructor) 'apikey' is not defined. Can't sign-in. Check the documentation to configure it"); this._hasCredentials = false; } if (!this._options.application) { this._logger.log("error", LOG_ID + "(constructor) 'application' property is not defined. Can't sign-in. Check the documentation to configure it"); this._hasApplication = false; } else if (!this._options.application.appID || !this._options.application.appSecret) { this._logger.log("error", LOG_ID + "(constructor) 'appId' or 'appSecret' is not defined. Can't sign-in. Check the documentation to configure it"); this._hasApplication = false; } this._httpOptions = this._getHTTPOptions(); this._xmppOptions = this._getXMPPOptions(); this._s2sOptions = this._getS2SOptions(); this._restOptions = this._getRESTOptions(); this._proxyoptions = this._getProxyOptions(); this._imOptions = this._getIMOptions(); this._applicationOptions = this._getApplicationsOptions(); let mode = this._getModeOption(); // Disable the xmpp mode if the ApiKey is used to connect SDK. if (this._hasCredentials === true) { if (isNotDefinedOrEmpty(this._options.credentials.login) && isNotDefinedOrEmpty(this._options.credentials.password) && isDefinedAndNotEmpty(this._options.credentials.apikey)) { mode = "cli"; } } this._withXMPP = mode==="xmpp"; this._withS2S = mode === "s2s"; this._CLIMode = mode === "cli"; this._servicesToStart = this._getservicesToStart(); this._testOutdatedVersion = this._gettestOutdatedVersion(); this._testDNSentry = this._gettestDNSentry(); this._autoReconnectIgnoreErrors = this._getautoReconnectIgnoreErrors(); this._httpoverxmppserver = this._gethttpoverxmppserver(); this._intervalBetweenCleanMemoryCache = this._getintervalBetweenCleanMemoryCache(); //this._concurrentRequests = this._getConcurrentRequestsOption(); this._requestsRate = this._getRequestsRateOption(); saveConfigFromIniFile(this._configIniData); } get testOutdatedVersion(): boolean { return this._testOutdatedVersion; } set testOutdatedVersion(value: boolean) { this._testOutdatedVersion = toBoolean(value); } get testDNSentry(): boolean { return this._testDNSentry; } set testDNSentry(value: boolean) { this._testDNSentry = toBoolean(value); } get autoReconnectIgnoreErrors(): boolean { return this._autoReconnectIgnoreErrors; } set autoReconnectIgnoreErrors(value: boolean) { this._autoReconnectIgnoreErrors = toBoolean(value); } get testhttpoverxmppserver(): boolean { return this._httpoverxmppserver; } set testhttpoverxmppserver(value: boolean) { this._httpoverxmppserver = toBoolean(value); } get intervalBetweenCleanMemoryCache(): number { return this._intervalBetweenCleanMemoryCache; } set intervalBetweenCleanMemoryCache(value: number) { this._intervalBetweenCleanMemoryCache = value; } get servicesToStart () { return this._servicesToStart; } get httpOptions() { return this._httpOptions; } get xmppOptions() { return this._xmppOptions; } get s2sOptions() { return this._s2sOptions; } get restOptions() { return this._restOptions; } get proxyOptions() { return this._proxyoptions; } get imOptions() { return this._imOptions; } get applicationOptions() { return this._applicationOptions; } get hasCredentials() { return this._hasCredentials; } get hasApplication() { return this._hasApplication; } get useXMPP() { return this._withXMPP; } get useS2S() { return this._withS2S; } get useCLIMode() { return this._CLIMode; } get credentials() { return this._options.credentials; } get concurrentRequests(): number { return this._concurrentRequests; } get requestsRate(): { "useRequestRateLimiter": number, "maxReqByIntervalForRequestRate": number, "intervalForRequestRate": number, "timeoutRequestForRequestRate": number } { return this._requestsRate; } _gettestOutdatedVersion() { if ( isDefined(this._options["testOutdatedVersion"]) ) { return toBoolean(this._options.testOutdatedVersion); } else { return config.testOutdatedVersion; } } _gettestDNSentry() { if ( isDefined(this._options["testDNSentry"] ) ) { return toBoolean(this._options.testDNSentry); } else { return config.testDNSentry; } } _getautoReconnectIgnoreErrors() { if ( isDefined(this._options["autoReconnectIgnoreErrors"]) ) { return toBoolean(this._options.autoReconnectIgnoreErrors); } else { return config.autoReconnectIgnoreErrors; } } _gethttpoverxmppserver() { if ( isDefined(this._options["httpoverxmppserver"]) ) { return toBoolean(this._options.httpoverxmppserver); } else { return config.httpoverxmppserver; } } _getintervalBetweenCleanMemoryCache() { if ( isDefined(this._options["intervalBetweenCleanMemoryCache"])) { return this._options.intervalBetweenCleanMemoryCache; } else { return config.intervalBetweenCleanMemoryCache; } } _getservicesToStart() { let svceToStart = {}; if (!this._options.servicesToStart) { svceToStart = Object.assign({},config.servicesToStart); } else { svceToStart = Object.assign({},config.servicesToStart); // Read each property one by one in the option parameter. To avoid missed service config. if ( typeof(this._options.servicesToStart) === 'object') { Object.keys(this._options.servicesToStart).forEach((key) => { if (!svceToStart[key]) { this._logger.log("warn", LOG_ID + "(_getservicesToStart) the service ", key, " is requested have start up to be configured, but it is not defined in default config."); svceToStart[key] = {}; } svceToStart[key].start_up = "start_up" in this._options.servicesToStart[key] ? this._options.servicesToStart[key].start_up : config.servicesToStart[key].start_up; svceToStart[key].optional = "optional" in this._options.servicesToStart[key] ? this._options.servicesToStart[key].optional : config.servicesToStart[key].optional; }); } // Else the options parameter is not well completed, so keep default values to start services. } return svceToStart; } _isOfficialRainbow () { return (this._options.rainbow.host === "official" || this._options.rainbow.host === "openrainbow.com"); //return (this._options.rainbow.host === "official" ); } _getHTTPOptions() { let httpOptions = config.sandbox.http; switch (this._options.rainbow.host) { case "openrainbow.com": case "official": httpOptions = config.official.http; this._logger.log("debug", LOG_ID + "(constructor) Use REST services on Rainbow Official platform"); break; case "sandbox": httpOptions = config.sandbox.http; this._logger.log("debug", LOG_ID + "(constructor) Use REST services on Rainbow Sandbox platform"); break; default: httpOptions = config.any.http; httpOptions.host = this._options.rainbow.host; this._logger.log("debug", LOG_ID + "(constructor) Use REST services on Rainbow " + this._options.rainbow.host + " platform"); break; } return httpOptions; } _getXMPPOptions() { let xmppOptions = config.sandbox.xmpp; switch (this._options.rainbow.host) { case "openrainbow.com": case "official": xmppOptions = config.official.xmpp; this._logger.log("debug", LOG_ID + "(constructor) Use XMPP services on Rainbow Official platform"); break; case "sandbox": xmppOptions = config.sandbox.xmpp; this._logger.log("debug", LOG_ID + "(constructor) Use XMPP services on Rainbow Sandbox platform"); break; default: xmppOptions = config.any.xmpp; xmppOptions.host = this._options.rainbow.host; if ( this._options.xmpp && this._options.xmpp.protocol ) { xmppOptions.protocol = this._options.xmpp.protocol; } if ( this._options.xmpp && this._options.xmpp.port) { xmppOptions.port = this._options.xmpp.port; } this._logger.log("warn", LOG_ID + "(constructor) Be careful, an unofficial Rainbow core is used : " + JSON.stringify(xmppOptions)); this._logger.log("debug", LOG_ID + "(constructor) Use XMPP services on Rainbow " + this._options.rainbow.host + " platform"); break; } if ( this._options.xmpp ) { if (isDefined(this._options.xmpp.raiseLowLevelXmppInEvent)) { xmppOptions.raiseLowLevelXmppInEvent = toBoolean(this._options.xmpp.raiseLowLevelXmppInEvent); } if (isDefined(this._options.xmpp.xmppRessourceName)) { xmppOptions.xmppRessourceName = this._options.xmpp.xmppRessourceName; } if (isDefined(this._options.xmpp.raiseLowLevelXmppOutReq)) { xmppOptions.raiseLowLevelXmppOutReq = toBoolean(this._options.xmpp.raiseLowLevelXmppOutReq); } if (isDefined(this._options.xmpp.maxIdleTimer)) { xmppOptions.maxIdleTimer = this._options.xmpp.maxIdleTimer; } if (isDefined(this._options.xmpp.timeBetweenXmppRequests)) { xmppOptions.timeBetweenXmppRequests = this._options.xmpp.timeBetweenXmppRequests; } if (isDefined(this._options.xmpp.maxPendingAsyncLockXmppQueue)) { xmppOptions.maxPendingAsyncLockXmppQueue = this._options.xmpp.maxPendingAsyncLockXmppQueue; } if (isDefined(this._options.xmpp.maxPingAnswerTimer)) { xmppOptions.maxPingAnswerTimer = this._options.xmpp.maxPingAnswerTimer; } if (isDefined(this._options.xmpp.stanzaMaxLength)) { xmppOptions.stanzaMaxLength = this._options.xmpp.stanzaMaxLength; } /* let paramArray = []; paramArray.push(xmppOptions); updateObjectPropertiesFromAnOtherObject(paramArray, this._options.xmpp); // */ } if (!xmppOptions.xmppRessourceName ) { if (isDefined(this._configIniData.xmppRessourceName)) { xmppOptions.xmppRessourceName = this._configIniData.xmppRessourceName; } else { xmppOptions.xmppRessourceName = xmppUtils.generateRandomID(); this._configIniData.xmppRessourceName = xmppOptions.xmppRessourceName; } } return xmppOptions; } _getS2SOptions() { let s2sOptions = config.sandbox.s2s; switch (this._options.rainbow.host) { case "openrainbow.com": case "official": s2sOptions = config.official.s2s; if ( this._options.s2s && this._options.s2s.hostCallback ) { s2sOptions.hostCallback = this._options.s2s.hostCallback; } if ( this._options.s2s && this._options.s2s.locallistenningport ) { s2sOptions.locallistenningport = this._options.s2s.locallistenningport; } if ( this._options.s2s && this._options.s2s.expressEngine) { s2sOptions.expressEngine = this._options.s2s.expressEngine; } this._logger.log("debug", LOG_ID + "(constructor) Use S2S services on Rainbow Official platform"); break; case "sandbox": s2sOptions = config.sandbox.s2s; if ( this._options.s2s && this._options.s2s.hostCallback ) { s2sOptions.hostCallback = this._options.s2s.hostCallback; } if ( this._options.s2s && this._options.s2s.locallistenningport ) { s2sOptions.locallistenningport = this._options.s2s.locallistenningport; } if ( this._options.s2s && this._options.s2s.expressEngine) { s2sOptions.expressEngine = this._options.s2s.expressEngine; } this._logger.log("debug", LOG_ID + "(constructor) Use S2S services on Rainbow Sandbox platform"); break; default: s2sOptions = config.any.s2s; if ( this._options.s2s && this._options.s2s.hostCallback ) { s2sOptions.hostCallback = this._options.s2s.hostCallback; } if ( this._options.s2s && this._options.s2s.locallistenningport ) { s2sOptions.locallistenningport = this._options.s2s.locallistenningport; } if ( this._options.s2s && this._options.s2s.expressEngine) { s2sOptions.expressEngine = this._options.s2s.expressEngine; } this._logger.log("warn", LOG_ID + "(constructor) Be careful, an unofficial Rainbow core is used : " + JSON.stringify(s2sOptions)); this._logger.log("debug", LOG_ID + "(constructor) Use S2S services on Rainbow " + this._options.rainbow.host + " platform"); break; } return s2sOptions; } _getRESTOptions() { let restOptions = config.any.rest; if ("rest" in this._options) { let restArray = []; restArray.push(restOptions); updateObjectPropertiesFromAnOtherObject(restArray, this._options.rest); //restOptions = this._options.rest; } return restOptions; } _getModeOption() { let mode = config.mode; if ("rainbow" in this._options && "mode" in this._options.rainbow) { switch (this._options.rainbow.mode) { case "xmpp": case "s2s": case "hook": case "cli": mode = this._options.rainbow.mode; break; default: mode = config.mode; break; } } return mode; } /* _getConcurrentRequestsOption() { let concurrentRequests = config.concurrentRequests; if ("rainbow" in this._options && "concurrentRequests" in this._options.rainbow) { concurrentRequests = this._options.rainbow.concurrentRequests; } return concurrentRequests; } // */ _getRequestsRateOption() { let requestsRate = config.requestsRate; if ("rainbow" in this._options && "requestsRate" in this._options) { requestsRate = this._options.requestsRate; } return requestsRate; } _getProxyOptions() { let proxyOptions = { "protocol": "http", "host": "", "port": 80, "user": undefined, "password": undefined, "secureProtocol": undefined }; if (!("host" in this._options.proxy)) { this._logger.log("warn", LOG_ID + "(constructor) 'host' property is not defined. No proxy will be used"); delete proxyOptions["host"]; } else { proxyOptions.host = this._options.proxy.host; } if (!("port" in this._options.proxy)) { this._logger.log("debug", LOG_ID + "(constructor) 'port' property is not defined. Use default 80"); delete proxyOptions["port"]; } else { proxyOptions.port = this._options.proxy.port; } if (!("protocol" in this._options.proxy)) { this._logger.log("debug", LOG_ID + "(constructor) 'protocol' property not defined. Use default 'http'"); delete proxyOptions["protocol"]; } else { proxyOptions.protocol = this._options.proxy.protocol; } if (!("user" in this._options.proxy)) { this._logger.log("debug", LOG_ID + "(constructor) 'user' property not defined. No authentication. "); delete proxyOptions["user"]; } else { proxyOptions.user = this._options.proxy.user; } if (!("password" in this._options.proxy)) { this._logger.log("debug", LOG_ID + "(constructor) 'password' property not defined. No authentication."); delete proxyOptions["password"]; } else { proxyOptions.password = this._options.proxy.password; } if (!("secureProtocol" in this._options.proxy)) { this._logger.log("debug", LOG_ID + "(constructor) 'secureProtocol' property not defined. No SSL3."); delete proxyOptions["secureProtocol"]; } else { proxyOptions.secureProtocol = this._options.proxy.secureProtocol; } return proxyOptions; } _getIMOptions() { let optionsIM = { "sendReadReceipt":true, "messageMaxLength" : 16384, // Max stanza size on server is 18432 "sendMessageToConnectedUser": false, "conversationsRetrievedFormat": "small", "storeMessages": false, "copyMessage": true, "nbMaxConversations": 15, "rateLimitPerHour": 10000, "messagesDataStore": DataStoreType.UsestoreMessagesField, "autoInitialGetBubbles": true, "autoInitialBubblePresence": true, "maxBubbleJoinInProgress": 10, "autoInitialBubbleFormat": "full", "autoInitialBubbleUnsubscribed": false, "autoLoadConversations": true, "autoLoadConversationHistory": false, "autoLoadContacts": true, "autoInitialLoadContactsInfoBulk": true, "autoLoadCallLog": false, "forceHistoryGetContactFromServer": false, "enableCarbon": true, "enablesendurgentpushmessages": false, "useMessageEditionAndDeletionV2": true, "storeMessagesInConversation": true, "maxMessagesStoredInConversation": 1000 }; optionsIM.sendReadReceipt = isDefined(config.im.sendReadReceipt) ? toBoolean(config.im.sendReadReceipt) : this._options.im.sendReadReceipt; optionsIM.messageMaxLength = isDefined(this._options.im.messageMaxLength) ? this._options.im.messageMaxLength : config.im.messageMaxLength; optionsIM.sendMessageToConnectedUser = isDefined(this._options.im.sendMessageToConnectedUser) ? toBoolean(this._options.im.sendMessageToConnectedUser) : config.im.sendMessageToConnectedUser; optionsIM.conversationsRetrievedFormat = isDefined(this._options.im.conversationsRetrievedFormat) ? this._options.im.conversationsRetrievedFormat : config.im.conversationsRetrievedFormat; optionsIM.storeMessages = isDefined(this._options.im.storeMessages) ? toBoolean(this._options.im.storeMessages) : config.im.storeMessages; optionsIM.copyMessage = isDefined(this._options.im.copyMessage) ? toBoolean(this._options.im.copyMessage) : config.im.copyMessage; optionsIM.nbMaxConversations = isDefined(this._options.im.nbMaxConversations) ? this._options.im.nbMaxConversations : config.im.nbMaxConversations; optionsIM.rateLimitPerHour = isDefined(this._options.im.rateLimitPerHour) ? this._options.im.rateLimitPerHour : config.im.rateLimitPerHour; optionsIM.messagesDataStore = isDefined(this._options.im.messagesDataStore) ? this._options.im.messagesDataStore : config.im.messagesDataStore; optionsIM.autoInitialGetBubbles = isDefined(this._options.im.autoInitialGetBubbles) ? toBoolean(this._options.im.autoInitialGetBubbles) : config.im.autoInitialGetBubbles; optionsIM.autoInitialBubblePresence = isDefined(this._options.im.autoInitialBubblePresence) ? toBoolean(this._options.im.autoInitialBubblePresence) : config.im.autoInitialBubblePresence; optionsIM.maxBubbleJoinInProgress = isDefined(this._options.im.maxBubbleJoinInProgress) ? this._options.im.maxBubbleJoinInProgress : config.im.maxBubbleJoinInProgress; optionsIM.autoInitialBubbleFormat = isDefined(this._options.im.autoInitialBubbleFormat) ? this._options.im.autoInitialBubbleFormat : config.im.autoInitialBubbleFormat; optionsIM.autoInitialBubbleUnsubscribed = isDefined(this._options.im.autoInitialBubbleUnsubscribed) ? toBoolean(this._options.im.autoInitialBubbleUnsubscribed) : config.im.autoInitialBubbleUnsubscribed; optionsIM.autoLoadConversations = isDefined(this._options.im.autoLoadConversations) ? toBoolean(this._options.im.autoLoadConversations) : config.im.autoLoadConversations; optionsIM.autoLoadConversationHistory = isDefined(this._options.im.autoLoadConversationHistory) ? toBoolean(this._options.im.autoLoadConversationHistory) : config.im.autoLoadConversationHistory; optionsIM.autoLoadContacts = isDefined(this._options.im.autoLoadContacts) ? toBoolean(this._options.im.autoLoadContacts) : config.im.autoLoadContacts; optionsIM.autoInitialLoadContactsInfoBulk = isDefined(this._options.im.autoInitialLoadContactsInfoBulk) ? toBoolean(this._options.im.autoInitialLoadContactsInfoBulk) : config.im.autoInitialLoadContactsInfoBulk; optionsIM.autoLoadCallLog = isDefined(this._options.im.autoLoadCallLog) ? toBoolean(this._options.im.autoLoadCallLog) : config.im.autoLoadCallLog; optionsIM.forceHistoryGetContactFromServer = isDefined(this._options.im.forceHistoryGetContactFromServer) ? toBoolean(this._options.im.forceHistoryGetContactFromServer) : config.im.forceHistoryGetContactFromServer; optionsIM.enableCarbon = isDefined(this._options.im.enableCarbon) ? toBoolean(this._options.im.enableCarbon) : config.im.enableCarbon; optionsIM.enablesendurgentpushmessages = isDefined(this._options.im.enablesendurgentpushmessages) ? toBoolean(this._options.im.enablesendurgentpushmessages) : config.im.enablesendurgentpushmessages; optionsIM.useMessageEditionAndDeletionV2 = isDefined(this._options.im.useMessageEditionAndDeletionV2) ? toBoolean(this._options.im.useMessageEditionAndDeletionV2) : config.im.useMessageEditionAndDeletionV2; optionsIM.storeMessagesInConversation = isDefined(this._options.im.storeMessagesInConversation) ? toBoolean(this._options.im.storeMessagesInConversation) : config.im.storeMessagesInConversation; optionsIM.maxMessagesStoredInConversation = isDefined(this._options.im.maxMessagesStoredInConversation) ? this._options.im.maxMessagesStoredInConversation : config.im.maxMessagesStoredInConversation; return optionsIM; } _getApplicationsOptions() { let applicationOptions = { "appID": "", "appSecret": "" }; if ("application" in this._options) { if (!("appID" in this._options.application)) { this._logger.log("warn", LOG_ID + "(constructor) 'appID' property is not defined. No application ID will be used"); } else { applicationOptions.appID = this._options.application.appID; } if (!("appSecret" in this._options.application)) { this._logger.log("warn", LOG_ID + "(constructor) 'appSecret' property is not defined. No application Secret will be used"); } else { applicationOptions.appSecret = this._options.application.appSecret; } } else { this._logger.log("warn", LOG_ID + "(constructor) 'appID' property is not defined. No application ID will be used"); this._logger.log("warn", LOG_ID + "(constructor) 'appSecret' property is not defined. No application Secret will be used"); } return applicationOptions; } /* get messageMaxLength () { let messageMaxLength = 16384; messageMaxLength = this._options.im.messageMaxLength ? this._options.im.messageMaxLength : config.im.messageMaxLength; return messageMaxLength } */ } module.exports.Options = Options; export {Options};