"use strict";
import * as util from "util";
import {isDefined, isStarted, logEntryExit, makeId, setTimeoutPromised} from "../common/Utils";
import * as PubSub from "pubsub-js";
import {Conversation} from "../common/models/Conversation";
import {XMPPUTils} from "../common/XMPPUtils";
import {NameSpacesLabels, XMPPService} from "../connection/XMPPService";
import {RESTService} from "../connection/RESTService";
import {ErrorManager} from "../common/ErrorManager";
import {InvitationEventHandler} from "../connection/XMPPServiceHandler/invitationEventHandler";
import {S2SServiceEventHandler} from "../connection/S2S/S2SServiceEventHandler";
import {EventEmitter} from "events";
import {Logger} from "../common/Logger";
import {ProxyImpl} from "../ProxyImpl";
import {GenericService} from "./GenericService";
import {Core} from "../Core.js";
import {RPCoverXMPPService} from "./RPCoverXMPPService.js";
const express = require( "express" );
const LOG_ID = "S2S - ";
const API_ID = "API_CALL - ";
@logEntryExit(LOG_ID)
@isStarted([])
/**
* @module
* @name s2s
* @version SDKVERSION
* @public
* @description
* This module handles the s2s API's methods to Rainbow.
*
* The main methods proposed in that module allow to:
* - Signin in s2s mode
* - List the user's connections in s2s mode
* - Manage presence
* - Send presence in bubble
* - Send messages
* - ...
*/
class S2SService extends GenericService{
private serverURL: any;
private host: any;
public version: any;
public jid_im: any;
public jid_tel: any;
public jid_password: any;
public fullJid: any;
public jid: any;
public userId: any;
private proxy: any;
private xmppUtils: XMPPUTils;
private generatedRandomId: string;
private hash: string;
private hostCallback: any;
private expressEngine: any;
private app: any;
private locallistenningport: string;
private s2sEventHandler: S2SServiceEventHandler;
private _contacts: any;
private _conversations: any;
static getClassName(){ return 'S2SService'; }
getClassName(){ return S2SService.getClassName(); }
static getAccessorName(){ return 's2s'; }
getAccessorName(){ return S2SService.getAccessorName(); }
constructor(_core:Core, _s2s: { hostCallback:string, locallistenningport:string, expressEngine:any }, _im, _application, _eventEmitter : EventEmitter, _logger: Logger, _proxy: ProxyImpl, _startConfig: { start_up:boolean, optional:boolean }) {
super(_logger, LOG_ID, _eventEmitter);
this.setLogLevels(this);
let that = this;
this._startConfig = _startConfig;
this.serverURL = ""; //_s2s.protocol + "://" + _s2s.host + ":" + _s2s.port + "/websocket";
this.hostCallback = _s2s.hostCallback;
this.locallistenningport = _s2s.locallistenningport;
this.expressEngine = _s2s.expressEngine;
this._eventEmitter = _eventEmitter;
this.version = "0.1";
this.jid_im = "";
this.jid_tel = "";
this.jid_password = "";
this.fullJid = "";
this.jid = "";
this.userId = "";
// this.initialPresence = true;
// this.xmppClient = null;
this._logger = _logger;
this.proxy = _proxy;
this._useS2S = false;
/*
this.shouldSendMessageToConnectedUser = _im.sendMessageToConnectedUser;
this.storeMessages = _im.storeMessages;
this.copyMessage = _im.copyMessage;
this.rateLimitPerHour = _im.rateLimitPerHour;
this.messagesDataStore = _im.messagesDataStore;
this.useXMPP = true;
this.timeBetweenXmppRequests = _xmpp.timeBetweenXmppRequests;
this.isReconnecting = false;
this.maxAttempts = 1;
this.idleTimer = null;
this.pingTimer = null;
this.forceClose = false;
this.applicationId = _application.appID;
// */
this._core = _core;
this.xmppUtils = XMPPUTils.getXMPPUtils();
this.generatedRandomId = this.xmppUtils.generateRandomID();
this.hash = makeId(8);
this.s2sEventHandler = new S2SServiceEventHandler(_im, _application, _eventEmitter, _logger, _s2s.hostCallback);
this._eventEmitter.on("evt_internal_ons2sready", this.onS2SReady.bind(this));
that._logger.log(that.INTERNAL, LOG_ID + "(S2SService) ", this._logger.colors.yellow("S2SService contructor."));
}
start(_options) {
let that = this;
that.initStartDate();
return new Promise(async (resolve, reject) => {
try {
that._options = _options;
that._useS2S = that._options.useS2S;
that._rest = that._core._rest;
that._contacts = that._core._contacts;
that._conversations = that._core._conversations;
await that.s2sEventHandler.start(that._core);
if (that._useS2S) {
if (!that.app) {
if (!that.expressEngine) {
that._logger.log(that.INFO, LOG_ID + "(start) Server app is not defined and nop expressEngine is provided, so construct it.");
that.app = express();
that.app.use(express.json());
that.app.listen(that.locallistenningport, function () {
that._logger.log(that.INFO, LOG_ID + "(start) Server app is running on " + that.locallistenningport + " port");
});
} else {
that._logger.log(that.INFO, LOG_ID + "(start) Server app is not defined and a expressEngine is provided, so use the expressEngine parameter.");
that.app = that.expressEngine;
}
} else {
that._logger.log(that.INFO, LOG_ID + "(start) Server app is already existing, so keep it.");
}
that._logger.log(that.DEBUG, LOG_ID + "(start) S2S hostCallback used : ", that.hostCallback, ", on locallistenningport : ", that.locallistenningport);
//that._logger.log(that.INFO, LOG_ID + "(start) S2S URL : ", that.serverUR);
/* that.app.post( "/message", (req, res ) => {
// console.log( "received a message")
// console.log( req.body )
// console.log( req.body.message.conversation_id )
sendMessageToConv(req.body.message.conversation_id, "J'ai bien recu ton message :" + req.body.message.body )
res.send("");
}
) // */
that._logger.log(that.INFO, LOG_ID + "(start) listen for * route of Server app.");
that.app.all('*', async (req, res, next: any) => {
//res.send('
Hello World!
');
that._logger.log(that.HTTP, LOG_ID + "*************************************************");
//that._logger.log(that.HTTP, LOG_ID + "next() called.");
that._logger.log(that.HTTP, LOG_ID + "received an event: ");
that._logger.log(that.HTTP, LOG_ID + "METHOD : ", req.method);
that._logger.log(that.HTTP, LOG_ID + "BASELURL : ", req.baseUrl);
that._logger.log(that.HTTP, LOG_ID + "ORIGINALURL : ", req.originalUrl);
that._logger.log(that.INTERNAL, LOG_ID + "BODY : ", req.body);
that._logger.log(that.HTTP, LOG_ID + "*************************************************");
let body = req.body;
let handleS2SEventResult = that.s2sEventHandler.handleS2SEvent(req);
if (handleS2SEventResult.isEventForMe) {-
that._logger.log(that.HTTP, LOG_ID + "before res.send() call.");
//next();
res.send('Hello World!
');
that._logger.log(that.HTTP, LOG_ID + "after res.send() call.");
} else {
that._logger.log(that.HTTP, LOG_ID + "before next() call.");
//next();
that._logger.log(that.HTTP, LOG_ID + "after next() call.");
}
});
/*
// for test of double middleware.
that.app.all('*', async (req, res, next: any) => {
//res.send('Hello World!
');
that._logger.log(that.HTTP, LOG_ID + "MiddleWare2 : *************************************************");
that._logger.log(that.HTTP, LOG_ID + "MiddleWare2 : received an event: ");
that._logger.log(that.HTTP, LOG_ID + "MiddleWare2 : METHOD : ", req.method );
that._logger.log(that.HTTP, LOG_ID + "MiddleWare2 : BASELURL : ", req.baseUrl );
that._logger.log(that.HTTP, LOG_ID + "MiddleWare2 : ORIGINALURL : ", req.originalUrl );
that._logger.log(that.INTERNAL, LOG_ID + "MiddleWare2 : BODY : ", req.body );
that._logger.log(that.HTTP, LOG_ID + "MiddleWare2 : *************************************************");
that._logger.log(that.HTTP, LOG_ID + "MiddleWare2 : before next() call.");
next();
that._logger.log(that.HTTP, LOG_ID + "MiddleWare2 : after next() call.");
}); // */
that.setStarted();
return resolve(undefined);
} else {
that._logger.log(that.INFO, LOG_ID + "(start) S2S connection blocked by configuration");
that.setStarted ();
return resolve(undefined);
}
} catch (err) {
return reject(err);
}
});
}
/**
* @private
* @name signin
* @param account
* @param headers
*/
signin(account, headers) {
let that = this;
return new Promise(async (resolve) => {
that.jid_im = account.jid_im;
that.jid_tel = account.jid_tel;
that.jid_password = account.jid_password;
that.userId = account.id;
that.fullJid = that.xmppUtils.generateRandomFullJidForS2SNode(that.jid_im, that.generatedRandomId);
that.jid = account.jid_im;
that._logger.log(that.INTERNAL, LOG_ID + "(signin) account used, jid_im : ", that.jid_im, ", fullJid : ", that.fullJid);
await that.deleteAllConnectionsS2S();
this.s2sEventHandler.setAccount(account);
resolve(await that.loginS2S(that.hostCallback));
});
}
/**
* @private
* @param forceStop
*/
stop(forceStop: boolean = false) {
let that = this;
return new Promise(function (resolve) {
that.jid_im = "";
that.jid_tel = "";
that.jid_password = "";
that.fullJid = "";
that.userId = "";
that._logger.log(that.DEBUG, LOG_ID + "(stop)" );
if (that._useS2S || forceStop) {
resolve(that.deleteAllConnectionsS2S().then(() => {
that.setStopped ();
}));
} else {
that.setStopped ();
resolve(undefined);
}
});
}
async init (useRestAtStartup : boolean) {
let that = this;
that.setInitialized();
}
// region S2S Management
/**
* @public
* @nodered true
* @method listConnectionsS2S
* @instance
* @category S2S Management
* @description
* List all the connected user's connexions.
* @async
* @return {Promise