"use strict";
import {Contact} from "../common/models/Contact";
import {ErrorManager} from "../common/ErrorManager";
import {Appreciation, Channel} from "../common/models/Channel";
import {ChannelEventHandler} from "../connection/XMPPServiceHandler/channelEventHandler";
import {XMPPService} from "../connection/XMPPService";
import {RESTService} from "../connection/RESTService";
import {EventEmitter} from "events";
import * as PubSub from "pubsub-js";
import * as fs from "fs";
import * as mimetypes from "mime-types";
import {isDefined, isStarted, logEntryExit} from "../common/Utils";
import {Logger} from "../common/Logger";
import {S2SService} from "./S2SService";
import {Core} from "../Core";
import {GenericService} from "./GenericService";
import {ContactsService} from "./ContactsService.js";
export {};
const LOG_ID = "CHANNELS/SVCE - ";
const API_ID = "API_CALL - ";
@logEntryExit(LOG_ID)
@isStarted([])
/**
* @module
* @name ChannelsService
* @version SDKVERSION
* @public
* @description
* This service manages ChannelsService. This service is in Beta.
*
* The main methods proposed in that module allow to:
* - Create a new channel
* - Manage a channel: update, delete
* - Manage users in a channel
*/
class ChannelsService extends GenericService {
private _channels: any;
private _channelsList: any;
public MAX_ITEMS: any;
public MAX_PAYLOAD_SIZE: any;
public PUBLIC_VISIBILITY: any;
public PRIVATE_VISIBILITY: any;
public CLOSED_VISIBILITY: any;
private channelEventHandler: ChannelEventHandler;
private channelHandlerToken: any;
public invitationCounter: number = 0;
private _contacts: ContactsService;
static getClassName(){ return 'ChannelsService'; }
getClassName(){ return ChannelsService.getClassName(); }
static getAccessorName(){ return 'channels'; }
getAccessorName(){ return ChannelsService.getAccessorName(); }
public LIST_EVENT_TYPE = {
ADD: {code : 0, label : "ADD"},
UPDATE: {code : 1, label : "UPDATE"},
REMOVE: {code : 2, label : "REMOVE"},
DELETE: {code : 3, label : "DELETE"},
SUBSCRIBE: {code : 4, label : "SUBSCRIBE"},
UNSUBSCRIBE: {code : 5, label : "UNSUBSCRIBE"},
CREATE: {code : 6, label : "CREATE"}
};
public USER_ROLE = {
NONE: "none",
OWNER: "owner",
PUBLISHER: "publisher",
MEMBER: "member"
};
constructor(_core:Core, _eventEmitter : EventEmitter, _logger : Logger, _startConfig: {
start_up:boolean,
optional:boolean
}) {
super(_logger, LOG_ID, _eventEmitter);
this.setLogLevels(this);
this._startConfig = _startConfig;
this._xmpp = null;
this._rest = null;
this._s2s = null;
this._options = {};
this._useXMPP = false;
this._useS2S = false;
this._channels = null;
this._channelsList = null;
this._contacts = null;
this._eventEmitter = _eventEmitter;
this._logger = _logger;
this.MAX_ITEMS = 100;
this.MAX_PAYLOAD_SIZE = 60000;
this.PUBLIC_VISIBILITY = "company";
this.PRIVATE_VISIBILITY = "private";
this.CLOSED_VISIBILITY = "closed";
this._core = _core;
this._eventEmitter.on("evt_internal_channelitemreceived", this._onChannelMessageReceived.bind(this));
this._eventEmitter.on("evt_internal_channelbyidmyappreciationreceived", this._onChannelMyAppreciationReceived.bind(this));
this._eventEmitter.on("evt_internal_addtochannel", this.onAddToChannel.bind(this));
this._eventEmitter.on("evt_internal_updatetochannel", this.onUpdateToChannel.bind(this));
this._eventEmitter.on("evt_internal_removefromchannel", this.onRemovedFromChannel.bind(this));
this._eventEmitter.on("evt_internal_subscribetochannel", this.onSubscribeToChannel.bind(this));
this._eventEmitter.on("evt_internal_unsubscribetochannel", this.onUnsubscribeToChannel.bind(this));
this._eventEmitter.on("evt_internal_deletechannel", this.onDeleteChannel.bind(this));
this._eventEmitter.on("evt_internal_usersubscribechannel", this.onUserSubscribeEvent.bind(this));
this._eventEmitter.on("evt_internal_userunsubscribechannel", this.onUserUnsubscribeEvent.bind(this));
}
start(_options) { // , _xmpp : XMPPService, _s2s : S2SService, _rest : RESTService
let that = this;
that.initStartDate();
return new Promise((resolve, reject) => {
try {
that._xmpp = that._core._xmpp;
that._rest = that._core._rest;
that._options = _options;
that._s2s = that._core._s2s;
that._contacts = that._core._contacts;
that._useXMPP = that._options.useXMPP;
that._useS2S = that._options.useS2S;
that._channels = [];
that._channelsList = [];
that.attachHandlers();
that.setStarted ();
resolve(undefined);
}
catch (err) {
that._logger.log(that.ERROR, LOG_ID + "(start) error ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(start) error : ", err);
return reject(err);
}
});
}
stop() {
let that = this;
return new Promise((resolve, reject) => {
try {
that._xmpp = null;
that._rest = null;
that._channels = null;
that._channelsList = null;
// that._eventEmitter.removeListener("rainbow_onchannelmessagereceived", that._onChannelMessageReceived);
if (that.channelHandlerToken) {
that.channelHandlerToken.forEach((token) => PubSub.unsubscribe(token));
}
that.channelHandlerToken = [];
that.setStopped ();
resolve(undefined);
} catch (err) {
that._logger.log(that.ERROR, LOG_ID + "(stop) error ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(stop) error : ", err);
return reject(err);
}
});
}
async init (useRestAtStartup : boolean) {
let that = this;
if (useRestAtStartup) {
await that.fetchMyChannels().then((result)=>{
that.setInitialized();
}).catch((err)=>{
that.setInitialized();
});
}
}
attachHandlers() {
let that = this;
that.channelEventHandler = new ChannelEventHandler(that._xmpp, that);
that.channelHandlerToken = [
// PubSub.subscribe( that._xmpp.hash + "." + that.conversationEventHandler.MESSAGE_CHAT, that.conversationEventHandler.onChatMessageReceived),
// PubSub.subscribe( that._xmpp.hash + "." + that.conversationEventHandler.MESSAGE_GROUPCHAT, that.conversationEventHandler.onChatMessageReceived),
// PubSub.subscribe( that._xmpp.hash + "." + that.conversationEventHandler.MESSAGE_WEBRTC, that.conversationEventHandler.onWebRTCMessageReceived),
PubSub.subscribe( that._xmpp.hash + "." + that.channelEventHandler.MESSAGE_MANAGEMENT, that.channelEventHandler.onManagementMessageReceived.bind(that.channelEventHandler)),
PubSub.subscribe( that._xmpp.hash + "." + that.channelEventHandler.MESSAGE_ERROR, that.channelEventHandler.onErrorMessageReceived.bind(that.channelEventHandler)),
PubSub.subscribe( that._xmpp.hash + "." + that.channelEventHandler.MESSAGE_HEADLINE, that.channelEventHandler.onHeadlineMessageReceived.bind(that.channelEventHandler)),
// PubSub.subscribe( that._xmpp.hash + "." + that.conversationEventHandler.MESSAGE_CLOSE, that.conversationEventHandler.onCloseMessageReceived)
];
}
//region Channels MANAGEMENT
/**
* @public
* @nodered true
* @method createChannel
* @instance
* @async
* @category Channels MANAGEMENT
* @param {string} name The name of the channel to create (max-length=255)
* @param {string} channelTopic The description of the channel to create (max-length=255)
* @return {Promise} New Channel
* @description
* Create a new public channel with a visibility limited to my company
*/
createChannel(name: string, channelTopic: string) {
let that = this;
return that.createPublicChannel(name, channelTopic, "globalnews");
}
/**
* @public
* @nodered true
* @method createPublicChannel
* @instance
* @async
* @category Channels MANAGEMENT
* @param {string} name The name of the channel to create (max-length=255)
* @param {string} channelTopic The description of the channel to create (max-length=255)
* @param {string} category="" The category of the channel
* @return {Promise} New Channel
* @description
* Create a new public channel with a visibility limited to my company
*/
createPublicChannel(name: string, channelTopic: string, category : string="") : Promise{
let that = this;
that._logger.log(that.INFOAPI, LOG_ID + API_ID + "(createPublicChannel) is name defined : ", isDefined(name), " is channelTopic defined : ", isDefined(channelTopic));
return new Promise((resolve, reject) => {
if (!name) {
that._logger.log(that.WARN, LOG_ID + "(createPublicChannel) bad or empty 'name' parameter");
that._logger.log(that.INTERNALERROR, LOG_ID + "(createPublicChannel) bad or empty 'name' parameter : ", name);
reject(ErrorManager.getErrorManager().BAD_REQUEST);
return;
}
that._rest.createPublicChannel(name, channelTopic, category, that.PUBLIC_VISIBILITY, that.MAX_ITEMS, that.MAX_PAYLOAD_SIZE).then((channel) => {
that._logger.log(that.DEBUG, LOG_ID + "(createPublicChannel) creation successfull");
//let channelObj : Channel = that.addOrUpdateChannelToCache(channel);
let channelObj : Channel = Channel.ChannelFactory()(channel, that._rest.http.serverURL);
resolve(channelObj);
}).catch((err) => {
that._logger.log(that.ERROR, LOG_ID + "(createPublicChannel) error ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(createPublicChannel) error : ", err);
return reject(err);
});
});
}
/**
* @public
* @nodered true
* @method createClosedChannel (ex: createPrivateChannel)
* @instance
* @async
* @category Channels MANAGEMENT
* @param {string} name The name of the channel to create (max-length=255)
* @param {string} description The description of the channel to create (max-length=255)
* @param {string} category="" The category of the channel
* @return {Promise} New Channel
* @description
* (old createPrivateChannel)
* Create a new closed channel
*/
createClosedChannel(name: string, description : string, category : string = "") : Promise {
let that = this;
that._logger.log(that.INFOAPI, LOG_ID + API_ID + "(createClosedChannel) is name defined : ", isDefined(name), " is description defined : ", isDefined(description));
return new Promise((resolve, reject) => {
if (!name) {
that._logger.log(that.WARN, LOG_ID + "(createClosedChannel) bad or empty 'name' parameter");
that._logger.log(that.INTERNALERROR, LOG_ID + "(createClosedChannel) bad or empty 'name' parameter : ", name);
reject(ErrorManager.getErrorManager().BAD_REQUEST);
return;
}
that._rest.createPublicChannel(name, description, category, that.PRIVATE_VISIBILITY, that.MAX_ITEMS, that.MAX_PAYLOAD_SIZE).then((channel) => {
that._logger.log(that.DEBUG, LOG_ID + "(createClosedChannel) creation successfull");
//let channelObj : Channel = that.addOrUpdateChannelToCache(channel);
let channelObj : Channel = Channel.ChannelFactory()(channel, that._rest.http.serverURL);
resolve(channelObj);
}).catch((err) => {
that._logger.log(that.ERROR, LOG_ID + "(createClosedChannel) error ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(createClosedChannel) error : ", err);
return reject(err);
});
});
}
/**
* @public
* @nodered true
* @method deleteChannel
* @instance
* @async
* @category Channels MANAGEMENT
* @param {Channel} channel The channel to delete
* @return {Promise} Promise object represents The channel deleted
* @description
* Delete an owned channel
*/
deleteChannel(channel: Channel) : Promise {
let that = this;
that._logger.log(that.INFOAPI, LOG_ID + API_ID + "(deleteChannel) is channel defined : ", isDefined(channel));
return new Promise((resolve, reject) => {
if (!channel || !channel.id) {
that._logger.log(that.WARN, LOG_ID + "(deleteChannel) bad or empty 'channel' parameter");
that._logger.log(that.INTERNALERROR, LOG_ID + "(deleteChannel) bad or empty 'channel' parameter : ", channel);
reject(ErrorManager.getErrorManager().BAD_REQUEST);
return;
}
that._rest.deleteChannel(channel.id).then(async (status) => {
that._logger.log(that.DEBUG, LOG_ID + "(deleteChannel) channel deleted status : ", status);
/*let channelRemoved = that._channels.splice(that._channels.findIndex((el) => {
return el.id === channel.id;
}), 1); // */
let channelRemoved = await that.removeChannelFromCache(channel.id);
that._logger.log(that.INTERNAL, LOG_ID + "(deleteChannel) channel deleted : ", channelRemoved);
if (channelRemoved) {
resolve(channelRemoved);
} else {
that._logger.log(that.WARN, LOG_ID + "(deleteChannel) the channel deleted was unknown from SDK cache ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(deleteChannel) the channel deleted was unknown from SDK cache : ", channel);
resolve(channel);
}
}).catch((err) => {
that._logger.log(that.ERROR, LOG_ID + "(deleteChannel) error ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(deleteChannel) error : ", err);
return reject(err);
});
});
}
/**
* @public
* @nodered true
* @method findChannelsByName
* @instance
* @async
* @category Channels MANAGEMENT
* @param {string} name Search this provided substring in the channel name (case insensitive).
* @return {Promise>} ChannelsService found
* @description
* Find channels by name. Only channels with visibility equals to 'company' can be found. First 100 results are returned.
*/
findChannelsByName(name : string) : Promise<[Channel]> {
let that = this;
that._logger.log(that.INFOAPI, LOG_ID + API_ID + "(findChannelsByName) is name defined : ", isDefined(name));
if (!name) {
that._logger.log(that.WARN, LOG_ID + "(findChannelsByName) bad or empty 'name' parameter ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(findChannelsByName) bad or empty 'name' parameter : ", name);
return Promise.reject(ErrorManager.getErrorManager().BAD_REQUEST);
}
return that._findChannels(name, null);
}
/**
* @public
* @nodered true
* @method findChannelsByTopic
* @instance
* @async
* @category Channels MANAGEMENT
* @param {string} topic Search this provided substring in the channel topic (case insensitive).
* @return {Promise>} ChannelsService found
* @description
* Find channels by topic. Only channels with visibility equals to 'company' can be found. First 100 results are returned.
*/
findChannelsByTopic(topic : string) : Promise<[Channel]> {
let that = this;
that._logger.log(that.INFOAPI, LOG_ID + API_ID + "(findChannelsByTopic) is topic defined : ", isDefined(topic));
if (!topic) {
that._logger.log(that.WARN, LOG_ID + "(findChannelsByTopic) bad or empty 'topic' parameter ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(findChannelsByTopic) bad or empty 'topic' parameter : ", topic);
return Promise.reject(ErrorManager.getErrorManager().BAD_REQUEST);
}
return that._findChannels(null, topic);
}
/**
* @private
* @method findChannels
* @category Channels MANAGEMENT
*/
private _findChannels(name : string, topic : string) : Promise<[Channel]> {
let that = this;
//hack
let getChannel = (id) : Promise => {
return new Promise((resolve) => {
that.fetchChannel(id).then((channel : Channel) => {
resolve(channel);
}).catch((err) => {
that._logger.log(that.ERROR, LOG_ID + "(_findChannels) error getChannel ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(_findChannels) error getChannel : ", err);
resolve(null);
});
});
};
return new Promise((resolve, reject) => {
that._rest.findChannels(name, topic, null, null, null, null, null).then((channels : []) => {
that._logger.log(that.INFO, LOG_ID + "(_findChannels) findChannels channels found ");
that._logger.log(that.INTERNAL, LOG_ID + "(_findChannels) findChannels channels found : ", channels);
let promises = [];
channels.forEach((channel : any) => {
promises.push(getChannel(channel.id));
});
Promise.all(promises).then((listOfChannels : [Channel]) => {
resolve(listOfChannels);
});
}).catch((err) => {
that._logger.log(that.ERROR, LOG_ID + "(_findChannels) error ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(_findChannels) error : ", err);
return reject(err);
});
});
}
/**
* @public
* @nodered true
* @method fetchChannel
* @instance
* @async
* @category Channels MANAGEMENT
* @param {string} id The id of the channel)
* @param {boolean} force=false True to force a request to the server
* @return {Promise} The channel found
* @description
* (old getChannelById)
* Find a channel by its id (locally if exists or by sending a request to Rainbow)
*/
async fetchChannel(id : string, force : boolean = false) : Promise{
let that = this;
that._logger.log(that.INFOAPI, LOG_ID + API_ID + "(fetchChannel) is id defined : ", isDefined(id));
return new Promise(async (resolve, reject) => {
if (!id) {
that._logger.log(that.WARN, LOG_ID + "(fetchChannel) bad or empty 'jid' parameter");
that._logger.log(that.INTERNALERROR, LOG_ID + "(fetchChannel) bad or empty 'jid' parameter : ", id);
return reject(ErrorManager.getErrorManager().BAD_REQUEST);
}
else {
let channelFound = that.getChannelFromCache(id);
if (channelFound && !force) {
that._logger.log(that.INFO, LOG_ID + "(fetchChannel) channel found locally");
that._logger.log(that.INTERNAL, LOG_ID + "(fetchChannel) channel found locally : ", channelFound);
resolve(channelFound);
} else {
that._logger.log(that.DEBUG, LOG_ID + "(fetchChannel) channel not found locally. Ask the server for id : ", id);
try {
let channel = await that.getChannel(id);
let channelObj: Channel = that.addOrUpdateChannelToCache(channel);
resolve(channelObj);
} catch (err) {
that._logger.log(that.INTERNAL, LOG_ID + "(fetchChannel) channel not found on serveur, err : ", err);
reject(err);
}
}
}
});
}
/**
* @public
* @nodered true
* @method fetchChannelsByFilter
* @since 1.55
* @instance
* @category Channels MANAGEMENT
* @description
* Find channels using a filter (on name, topic)
* Result may be filtered with result limit, offet and sortField or SortOrder
* Return a promise.
* @param {Object} filter The filter with at least [filter.name] or [filter.topic] defined
* {string} [filter.name] search by channel names (case insensitive substring).
* {string} [filter.topic] search by channel topics (case insensitive substring).
* {Number} [filter.limit=100] allow to specify the number of channels to retrieve.
* {Number} [filter.offset] allow to specify the position of first channel to retrieve (first channel if not specified). Warning: if offset > total, no results are returned.
* {string} [filter.sortField="name"] sort channel list based on the given field.
* {Number} [filter.sortOrder="1"] specify order ascending/descending. 1 for ascending, -1 for descending.
* @return {Promise} Result of the find with
* {Array} found channels informations with an array of { id, name, topic, creatorId, visibility, users_count }
*/
fetchChannelsByFilter (filter:any) : Promise<[Channel]> {
let that = this;
that._logger.log(that.INFOAPI, LOG_ID + API_ID + "(fetchChannelsByFilter) is filter defined : ", isDefined(filter));
let getChannel = (id) : Promise => {
return new Promise((resolve) => {
that.fetchChannel(id).then((channel : Channel) => {
resolve(channel);
}).catch((err) => {
that._logger.log(that.ERROR, LOG_ID + "(fetchChannelsByFilter) error getChannel ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(fetchChannelsByFilter) error getChannel : ", err);
resolve(null);
});
});
};
if (!filter) {
that._logger.log(that.DEBUG, LOG_ID + "(fetchChannelsByFilter) bad or empty 'channel' parameter ");
that._logger.log(that.INTERNAL, LOG_ID + "(fetchChannelsByFilter) bad or empty 'channel' parameter : ", filter);
return Promise.reject(ErrorManager.getErrorManager().BAD_REQUEST);
}
return new Promise((resolve, reject) => {
that._rest.findChannels(filter.name, filter.topic, filter.category, filter.limit, filter.offset, filter.sortField, (filter.sortOrder && (filter.sortOrder === 1) ? "1" : "-1")).then((channels : []) => {
that._logger.log(that.INFO, LOG_ID + "(fetchChannelsByFilter) channels found");
that._logger.log(that.INTERNAL, LOG_ID + "(fetchChannelsByFilter) channels found : ", channels);
let promises = [];
channels.forEach((channel : Channel) => {
promises.push(getChannel(channel.id));
});
Promise.all(promises).then((listOfChannels : [Channel]) => {
resolve(listOfChannels);
});
}).catch((err) => {
that._logger.log(that.ERROR, LOG_ID + "(fetchChannelsByFilter) error ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(fetchChannelsByFilter) error : ", err);
return reject(err);
});
});
};
/**
* @public
* @nodered true
* @method fetchMyChannels
* @since 1.38
* @instance
* @category Channels MANAGEMENT
* @param {boolean} force=false Boolean to force the get of channels's informations from server.
* @description
* (old getChannels)
* Get the channels you own, are subscribed to, are publisher
* Return a promise.
* @return {Promise} Return Promise with a list of channels or an empty array if no channel has been found
*/
fetchMyChannels(force : boolean = false) : Promise<[Channel]>{
let that = this;
that._logger.log(that.INFOAPI, LOG_ID + API_ID + "(fetchMyChannels) is force defined : ", isDefined(force));
let getChannel = (id) : Promise => {
return new Promise((resolve) => {
that.fetchChannel(id, force).then((channel) => {
resolve(channel);
}).catch((err) => {
that._logger.log(that.ERROR, LOG_ID + "(fetchMyChannels) error fetchChannel ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(fetchMyChannels) error fetchChannel : ", err);
resolve(null);
});
});
};
return new Promise((resolve) => {
that._rest.getChannels().then((listOfChannels : any) => {
// Hack waiting server change
let promises = [];
if (Array.isArray(listOfChannels)) {
listOfChannels.forEach((channel) => {
promises.push(getChannel(channel.id));
});
} else {
if ( "owner" in listOfChannels) {
listOfChannels.owner.forEach((channel) => {
promises.push(getChannel(channel.id));
});
}
if ( "publisher" in listOfChannels) {
listOfChannels.publisher.forEach((channel) => {
promises.push(getChannel(channel.id));
});
}
if ( "member" in listOfChannels) {
listOfChannels.member.forEach((channel) => {
promises.push(getChannel(channel.id));
});
}
}
that._logger.log(that.INFO, LOG_ID + "(fetchMyChannels) hack start get channel data individually from server...");
Promise.all(promises).then((channels : [Channel]) => {
that._logger.log(that.INTERNAL, LOG_ID + "(fetchMyChannels) hack done : ", channels);
that._channels = [];
if (channels) {
channels.forEach((channel) => {
that.addOrUpdateChannelToCache(channel);
})
}
//that._logger.log(that.INTERNAL, LOG_ID + "(fetchMyChannels) get successfully and updated the channels cache : ", that._channels);
resolve(that._channels);
});
}).catch((err) => {
that._logger.log(that.ERROR, LOG_ID + "(fetchMyChannels) error ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(fetchMyChannels) error : ", err);
// Do not block the startup on VM without channels API
that._channels = [];
resolve(that._channels);
});
});
}
/**
* @public
* @nodered true
* @method getAllChannels
* @category Channels MANAGEMENT
* @instance
* @return {Channel[]} An array of channels (owned, invited, subscribed)
* @description
* Return the list of channels (owned, invited, subscribed)
*/
getAllChannels() : [Channel] {
let that = this;
that._logger.log(that.INFOAPI, LOG_ID + API_ID + "(getAllChannels) .");
return that._channels;
}
/**
* @public
* @nodered true
* @method getAllOwnedChannels
* @category Channels MANAGEMENT
* @instance
* @return {Channel[]} An array of channels (owned only)
* @description
* (old getAllOwnedChannel)
* Return the list of owned channels only
*/
getAllOwnedChannels() : [Channel] {
let that = this;
that._logger.log(that.INFOAPI, LOG_ID + API_ID + "(getAllOwnedChannels) .");
return that._channels.filter((channel) => {
return channel.creatorId === that._rest.userId;
});
}
/**
* @public
* @nodered true
* @method getAllPendingChannels
* @category Channels MANAGEMENT
* @instance
* @return {Channel[]} An array of channels (invited only)
* @description
* Return the list of invited channels only
*/
getAllPendingChannels() : [Channel] {
let that = this;
that._logger.log(that.INFOAPI, LOG_ID + API_ID + "(getAllPendingChannels) .");
return that._channels.filter((channel) => {
return channel.invited;
});
}
/**
* @public
* @nodered true
* @method updateChannelTopic
* @instance
* @async
* @category Channels MANAGEMENT
* @param {Channel} channel The channel to update
* @param {string} description The description of the channel to update (max-length=255)
* @return {Promise} Updated channel
* @description
* Update the description of a channel.
*/
updateChannelTopic (channel : Channel, description : string) : Promise {
let that = this;
that._logger.log(that.INFOAPI, LOG_ID + API_ID + "(updateChannelTopic) is channel defined : ", isDefined(channel));
return that.updateChannelDescription(channel, description);
}
/**
* @public
* @nodered true
* @method updateChannelDescription
* @instance
* @async
* @category Channels MANAGEMENT
* @param {Channel} channel The channel to update
* @param {string} description The description of the channel to update (max-length=255)
* @return {Promise} Updated channel
* @description
* Update the description of a channel.
*
*/
updateChannelDescription(channel: Channel, description : string) : Promise {
let that = this;
that._logger.log(that.INFOAPI, LOG_ID + API_ID + "(updateChannelDescription) is channel defined : ", isDefined(channel));
if (!channel || !channel.id) {
that._logger.log(that.WARN, LOG_ID + "(updateChannelDescription) bad or empty 'channel' parameter ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(updateChannelDescription) bad or empty 'channel' parameter : ", channel);
return Promise.reject(ErrorManager.getErrorManager().BAD_REQUEST);
}
if (!channel.id) {
that._logger.log(that.WARN, LOG_ID + "(updateChannelDescription) bad or empty 'channel.id' parameter ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(updateChannelDescription) bad or empty 'channel.id' parameter : ", channel.id);
return Promise.reject(ErrorManager.getErrorManager().BAD_REQUEST);
}
if (!description) {
that._logger.log(that.WARN, LOG_ID + "(updateChannelDescription) bad or empty 'description' parameter ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(updateChannelDescription) bad or empty 'description' parameter : ", description);
return Promise.reject(ErrorManager.getErrorManager().BAD_REQUEST);
}
return new Promise((resolve, reject) => {
that._rest.updateChannel(channel.id, description, null, null , null, null, null).then((channelUpdated : any) => {
that._logger.log(that.INFO, LOG_ID + "(updateChannelDescription) channel updated");
that._logger.log(that.INTERNAL, LOG_ID + "(updateChannelDescription) channel updated : ", channelUpdated);
let channelObj = that.addOrUpdateChannelToCache(channelUpdated);
/*let foundIndex = that._channels.findIndex(channelItem => channelItem.id === channelUpdated.id);
let channelObj : Channel = Channel.ChannelFactory()(channelUpdated, that._rest.http.serverURL);
that._channels[foundIndex] = channelObj; // */
resolve(channelObj);
}).catch((err) => {
that._logger.log(that.ERROR, LOG_ID + "(updateChannelDescription) error ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(updateChannelDescription) error : ", err);
return reject(err);
});
});
}
/**
* @public
* @nodered true
* @method updateChannelName
* @since 1.46
* @instance
* @category Channels MANAGEMENT
* @description
* Update a channel name
* Return a promise.
* @param {Channel} channel The channel to update
* @param {string} channelName The name of the channel
* @return {Channel} Return the channel updated or an error
*/
updateChannelName(channel : Channel, channelName : string) {
let that = this;
that._logger.log(that.INFOAPI, LOG_ID + API_ID + "(updateChannelName) is channel defined : ", isDefined(channel));
if (!channel || !channel.id) {
that._logger.log(that.WARN, LOG_ID + "(updateChannelName) bad or empty 'channel' parameter ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(updateChannelName) bad or empty 'channel' parameter : ", channel);
return Promise.reject(ErrorManager.getErrorManager().BAD_REQUEST);
}
if (!channel.id) {
that._logger.log(that.WARN, LOG_ID + "(updateChannelName) bad or empty 'channel.id' parameter ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(updateChannelName) bad or empty 'channel.id' parameter : ", channel.id);
return Promise.reject(ErrorManager.getErrorManager().BAD_REQUEST);
}
if (!channelName) {
that._logger.log(that.WARN, LOG_ID + "(updateChannelName) bad or empty 'channelName' parameter ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(updateChannelName) bad or empty 'channelName' parameter : ", channelName);
return Promise.reject(ErrorManager.getErrorManager().BAD_REQUEST);
}
return new Promise((resolve, reject) => {
that._rest.updateChannel(channel.id, null, null, null , null, channelName, null).then((channelUpdated : any) => {
that._logger.log(that.INFO, LOG_ID + "(updateChannelName) channel updated ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(updateChannelName) channel updated : ", channelUpdated);
let channelObj = that.addOrUpdateChannelToCache(channelUpdated);
/*let foundIndex = that._channels.findIndex(channelItem => channelItem.id === channelUpdated.id);
let channelObj : Channel = Channel.ChannelFactory()(channelUpdated, that._rest.http.serverURL);
that._channels[foundIndex] = channelObj; */
resolve(channelObj);
}).catch((err) => {
that._logger.log(that.ERROR, LOG_ID + "(updateChannelName) error ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(updateChannelName) error : ", err);
return reject(err);
});
});
};
/**
* @public
* @nodered true
* @method updateChannel
* @since 1.38
* @category Channels MANAGEMENT
* @instance
* @description
* Update a channel
* May be updated: name, topic, visibility, max_items and max_payload
* Please put null to not update a property.
* Return a promise.
* @param {string} id The id of the channel
* @param {string} channelTopic The topic of the channel
* @param {string} visibility=public public/company/closed group visibility for search
* @param {Number} max_items=30 max # of items to persist in the channel
* @param {Number} max_payload_size=60000 max # of items to persist in the channel
* @param {string} channelName The name of the channel
* @param {string} category The category of the channel
* @return {Promise} Return the channel created or an error
*/
updateChannel( id : string, channelTopic : string=undefined, visibility : string="public", max_items : Number=30, max_payload_size : Number = 60000, channelName : string = undefined, category : string = undefined) {
let that = this;
that._logger.log(that.INFOAPI, LOG_ID + API_ID + "(updateChannel) is id defined : ", isDefined(id));
if (!id) {
that._logger.log(that.WARN, LOG_ID + "(updateChannel) bad or empty 'id' parameter ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(updateChannel) bad or empty 'id' parameter : ", id);
return Promise.reject(ErrorManager.getErrorManager().BAD_REQUEST);
} else {
let options : any = {};
if (channelTopic != null) {
options.topic = channelTopic;
}
if (visibility != null) {
options.mode = visibility === "company" ? "company_public" : "company_closed";
}
if (max_items != null) {
options.max_items = max_items;
}
if (max_payload_size != null) {
options.max_payload_size = max_payload_size;
}
if (channelName != null) {
options.name = channelName;
}
if (category != null) {
options.cateogry = category;
}
return new Promise((resolve, reject) =>
{
that._rest.updateChannel(id, options.topic, null, options.max_items, options.max_payload_size, options.name, options.mode)
.then((channelUpdated) => {
that._logger.log(that.INTERNAL, LOG_ID + "(updateChannel) channel channelUpdated : ", channelUpdated);
let channelObj = that.addOrUpdateChannelToCache(channelUpdated);
that._logger.log(that.INTERNAL, LOG_ID + "(updateChannel) channel updated, channelObj : ", channelObj);
resolve(channelObj);
})
.catch(function (err) {
return reject(err);
});
});
}
};
/**
* @public
* @nodered true
* @method updateChannelVisibility
* @since 1.55
* @category Channels MANAGEMENT
* @instance
* @description
* Update a channel visibility
* Return a promise.
* @param {Channel} channel The channel to update
* @param {string} visibility The new channel visibility (closed or company)
* @return {Promise} Return the channel updated or an error
*/
updateChannelVisibility(channel : Channel, visibility : string) {
let that = this;
that._logger.log(that.INFOAPI, LOG_ID + API_ID + "(updateChannelVisibility) is channel defined : ", isDefined(channel));
if (!channel || !channel.id) {
that._logger.log(that.WARN, LOG_ID + "(updateChannelVisibility) bad or empty 'channel' parameter ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(updateChannelVisibility) bad or empty 'channel' parameter : ", channel);
return Promise.reject(ErrorManager.getErrorManager().BAD_REQUEST);
}
if (!channel.id) {
that._logger.log(that.WARN, LOG_ID + "(updateChannelVisibility) bad or empty 'channel.id' parameter ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(updateChannelVisibility) bad or empty 'channel.id' parameter : ", channel.id);
return Promise.reject(ErrorManager.getErrorManager().BAD_REQUEST);
}
if (!visibility) {
that._logger.log(that.WARN, LOG_ID + "(updateChannelVisibility) bad or empty 'visibility' parameter ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(updateChannelVisibility) bad or empty 'visibility' parameter : ", visibility);
return Promise.reject(ErrorManager.getErrorManager().BAD_REQUEST);
}
let mode = visibility === "company" ? "company_public" : "company_closed";
let name = channel.name;
return new Promise((resolve, reject) => {
that._rest.updateChannel(channel.id, null, null, null , null, name, mode).then((channelUpdated : any) => {
that._logger.log(that.INTERNAL, LOG_ID + "(updateChannelVisibility) channel updated : ", channelUpdated);
let channelObj = that.addOrUpdateChannelToCache(channelUpdated);
/*let foundIndex = that._channels.findIndex(channelItem => channelItem.id === channelUpdated.id);
let channelObj : Channel = Channel.ChannelFactory()(channelUpdated, that._rest.http.serverURL);
that._channels[foundIndex] = channelObj;
*/
that._logger.log(that.INTERNAL, LOG_ID + "(updateChannelVisibility) channel updated : ", channelObj);
resolve(channelObj);
}).catch((err) => {
that._logger.log(that.ERROR, LOG_ID + "(updateChannelVisibility) error ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(updateChannelVisibility) error : ", err);
return reject(err);
});
});
};
/**
* @public
* @nodered true
* @method updateChannelVisibilityToPublic
* @since 1.55
* @category Channels MANAGEMENT
* @instance
* @description
* Set the channel visibility to company (visible for users in that company)
* Return a promise.
* @param {Channel} channel The channel to update
* @return {Channel} Return the channel updated or an error
*/
public updateChannelVisibilityToPublic(channel: Channel) {
let that = this;
that._logger.log(that.INFOAPI, LOG_ID + API_ID + "(updateChannelVisibilityToPublic) is channel defined : ", isDefined(channel));
return that.updateChannelVisibility(channel, "company");
}
/**
* @public
* @nodered true
* @method updateChannelVisibilityToClosed
* @since 1.55
* @instance
* @category Channels MANAGEMENT
* @description
* Set the channel visibility to closed (not visible by users)
* Return a promise.
* @param {Channel} channel The channel to update
* @return {Channel} Return the channel updated or an error
*/
public updateChannelVisibilityToClosed(channel: Channel) {
let that = this;
that._logger.log(that.INFOAPI, LOG_ID + API_ID + "(updateChannelVisibilityToClosed) is channel defined : ", isDefined(channel));
//channel.name = channel.name + "_updateToClosed";
return that.updateChannelVisibility(channel, "closed");
}
/**
* @public
* @nodered true
* @method updateChannelAvatar
* @since 1.43
* @instance
* @category Channels MANAGEMENT
* @description
* Update a channel avatar
* Return a promise.
* @param {Channel} channel The Channel to update
* @param {string} urlAvatar The avatar Url. It must be resized to 512 pixels before calling this API.
* @return {Channel} Return the channel updated or an error
*/
updateChannelAvatar (channel : Channel, urlAvatar : string) {
let that = this;
that._logger.log(that.INFOAPI, LOG_ID + API_ID + "(updateChannelAvatar) is channel defined : ", isDefined(channel));
if (!channel || !channel.id) {
that._logger.log(that.WARN, LOG_ID + "(updateChannelAvatar) bad or empty 'channel' parameter ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(updateChannelAvatar) bad or empty 'channel' parameter : ", channel);
return Promise.reject(ErrorManager.getErrorManager().BAD_REQUEST);
} else if (!urlAvatar) {
that._logger.log(that.WARN, LOG_ID + "(updateChannelAvatar) bad or empty 'urlAvatar' parameter ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(updateChannelAvatar) bad or empty 'urlAvatar' parameter : ", urlAvatar);
return Promise.reject(ErrorManager.getErrorManager().BAD_REQUEST);
} else {
return new Promise((resolve, reject) => {
try {
that._logger.log(that.INTERNAL, LOG_ID + "(updateChannelAvatar) channel : ", channel);
let id = channel.id;
let fileStats = fs.statSync(urlAvatar);
let fd = fs.openSync(urlAvatar, "r+");
let buf = new Buffer(fileStats.size);
fs.readSync(fd, buf, 0, fileStats.size, null);
let fileType = mimetypes.lookup(urlAvatar) + "";
that._rest.uploadChannelAvatar(id, buf, fileStats.size/* should resize the picture to 512*/, fileType).then(function () {
that._logger.log(that.INTERNAL, LOG_ID + "(updateChannelAvatar) channel : ", channel);
resolve({
code: "OK",
label: "OK"
});
}).catch(function (err) {
that._logger.log(that.ERROR, LOG_ID + "(updateChannelAvatar) !!! CATCH Error ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(updateChannelAvatar) !!! CATCH Error ", err, ", for channel : ", channel);
return reject(err);
});
} catch (err2) {
that._logger.log(that.ERROR, LOG_ID + "(updateChannelAvatar) !!! CATCH Error ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(updateChannelAvatar) !!! CATCH Error ", err2, ", for channel : ", channel);
return reject(err2);
}
});
}
};
/**
* @public
* @nodered true
* @method deleteChannelAvatar
* @since 1.43
* @instance
* @category Channels MANAGEMENT
* @description
* Delete a channel avatar
* Return a promise.
* @param {Channel} channel The channel to update
* @return {Channel} Return the channel updated or an error
*/
deleteChannelAvatar(channel : Channel) {
let that = this;
that._logger.log(that.INFOAPI, LOG_ID + API_ID + "(deleteChannelAvatar) is channel defined : ", isDefined(channel));
if (!channel || !channel.id) {
that._logger.log(that.WARN, LOG_ID + "(updateChannelAvatar) bad or empty 'channel' parameter ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(updateChannelAvatar) bad or empty 'channel' parameter : ", channel);
return Promise.reject(ErrorManager.getErrorManager().BAD_REQUEST);
} else {
return new Promise((resolve, reject) => {
let id = channel.id;
that._rest.deleteChannelAvatar(id)
.then(function () {
that._logger.log(that.INTERNAL, LOG_ID + "(updateChannelAvatar) channel : ", channel);
resolve({
code: "OK",
label: "OK"
});
})
.catch(function (err) {
return reject(err);
});
});
}
};
/**
* @private
* @param channelId
* @category Channels MANAGEMENT
* @description
* GET A CHANNEL
*/
public getChannel(channelId: string): Promise {
let that = this;
return new Promise((resolve, reject) => {
that._rest.getChannel(channelId).then((channel) => {
that._logger.log(that.INFO, LOG_ID + "(getChannel) channel found on the server");
that._logger.log(that.INTERNAL, LOG_ID + "(getChannel) channel found on the server : ", channel);
let channelObj : Channel = Channel.ChannelFactory()(channel, that._rest.http.serverURL);
resolve(channelObj);
}).catch((err) => {
that._logger.log(that.ERROR, LOG_ID + "(getChannel) error ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(getChannel) error : ", err);
return reject(err);
});
});
};
/**
* @private
* @param channelId
* @category Channels MANAGEMENT
* @description
* GET A CHANNEL FROM CACHE
*/
private getChannelFromCache(channelId: string): Channel {
let channelFound = null;
let that = this;
that._logger.log(that.INTERNAL, LOG_ID + "(getChannelFromCache) search id : ", channelId);
if (that._channels) {
let channelFoundindex = that._channels.findIndex((channel) => {
return channel.id === channelId;
});
if (channelFoundindex != -1) {
that._logger.log(that.INTERNAL, LOG_ID + "(getChannelFromCache) channel found : ", that._channels[channelFoundindex], " with id : ", channelId);
return that._channels[channelFoundindex];
}
}
that._logger.log(that.INTERNAL, LOG_ID + "(getChannelFromCache) channel found : ", channelFound, " with id : ", channelId);
return channelFound ;
}
private updateChannelsList(): void {
let that = this;
//that._logger.log(that.DEBUG, LOG_ID + "(updateChannelsList) keys : ", Object.keys(that._channels));
that._channelsList = that._channels.map((chnl) => { return chnl.id; });
that._logger.log(that.INTERNAL, LOG_ID + "(updateChannelsList) that._channelsList : ", that._channelsList);
}
private addOrUpdateChannelToCache(channel: any): Channel {
let that = this;
let channelObj : Channel = Channel.ChannelFactory()(channel, that._rest.http.serverURL);
let channelFoundindex = that._channels.findIndex((channelIter) => {
return channelIter.id === channel.id;
});
if (channelFoundindex != -1) {
that._logger.log(that.INTERNAL, LOG_ID + "(addOrUpdateChannelToCache) update in cache with channel : ", channel, ", at channelFoundindex : ", channelFoundindex);
//that._channels.splice(channelFoundindex,1,channelObj);
//channelCached = channelObj;
that._logger.log(that.INTERNAL, LOG_ID + "(addOrUpdateChannelToCache) in update that._channels : ", that._channels);
that._channels[channelFoundindex].updateChannel(channel);
channelObj = that._channels[channelFoundindex];
} else {
that._logger.log(that.INTERNAL, LOG_ID + "(addOrUpdateChannelToCache) add in cache channelObj : ", channelObj);
that._channels.push(channelObj);
}
that.updateChannelsList();
return channelObj;
}
private removeChannelFromCache(channelId: string): Promise {
let that = this;
return new Promise((resolve, reject) => {
// Get the channel to remove
let channelToRemove = that.getChannelFromCache(channelId);
if (channelToRemove) {
// Store channel name
//let channelName = channelToRemove.name;
// Handle invitation channel
if (channelToRemove.invited) { that.decrementInvitationCounter(); }
// Remove from channels
let channelId = channelToRemove.id;
that._logger.log(that.INTERNAL, LOG_ID + "(removeChannelFromCache) remove from cache channelId : ", channelId);
that._channels = that._channels.filter( function(chnl) {
return !(chnl.id === channelId);
});
that.updateChannelsList();
// Update messagesList
//that.feedChannel.messages = [];
that.retrieveLatests()
.then(() => { resolve(channelToRemove); })
.catch((err) => {
that._logger.log(that.ERROR, LOG_ID + "(removeChannelFromCache) error retrieveLatests ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(removeChannelFromCache) error retrieveLatests : ", err);
return reject(err);
});
} else {
resolve(null);
}
});
}
//endregion Channels MANAGEMENT
//region Channels MESSAGES/ITEMS
/**
* @public
* @nodered true
* @method publishMessageToChannel
* @instance
* @async
* @category Channels MESSAGES/ITEMS
* @param {Channel} channel The channel where to publish the message
* @param {string} message Message content
* @param {string} title Message title, limit=256.
* @param {string} url An URL
* @param {any} imagesIds=null An Array of ids of the files stored in Rainbow
* @param {string} type="basic" An optional message content type (could be basic, markdown, html or data)
* @param {Object} customDatas={} A JSON object with custom datas merged to the payload send to server.
* @return {Promise} OK if successfull
* @description
* Publish to a channel
*/
publishMessageToChannel(channel : Channel, message : string, title : string = undefined, url : string=undefined, imagesIds : any=null, type : string="basic", customDatas : any = {}) : Promise<{}> {
let that = this;
that._logger.log(that.INFOAPI, LOG_ID + API_ID + "(publishMessageToChannel) is channel defined : ", isDefined(channel));
return that.createItem(channel, message, title, url, imagesIds, type, customDatas);
}
/**
* @public
* @method createItem
* @instance
* @async
* @category Channels MESSAGES/ITEMS
* @param {Channel} channel The channel where to publish the message
* @param {string} message Message content
* @param {string} title="" Message title, limit=256.
* @param {string} url="" An URL
* @param {any} imagesIds An Array of ids of the files stored in Rainbow
* @param {string} type="basic" An optional message content type (could be basic, markdown, html or data)
* @param {Object} customDatas={} A JSON object with custom datas merged to the payload send to server.
* @return {Promise} OK if successfull
* @description
* Publish to a channel
*/
createItem(channel : Channel, message : string, title : string="", url : string="", imagesIds : any, type : string="basic", customDatas : any = {}) : Promise <{}> {
let that = this;
that._logger.log(that.INFOAPI, LOG_ID + API_ID + "(createItem) is channel defined : ", isDefined(channel));
if (!channel || !channel.id) {
that._logger.log(that.WARN, LOG_ID + "(createItem) bad or empty 'channel' parameter ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(createItem) bad or empty 'channel' parameter : ", channel);
return Promise.reject(ErrorManager.getErrorManager().BAD_REQUEST);
}
if (!message) {
that._logger.log(that.WARN, LOG_ID + "(createItem) bad or empty 'title' parameter ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(createItem) bad or empty 'title' parameter : ", title);
return Promise.reject(ErrorManager.getErrorManager().BAD_REQUEST);
}
if (imagesIds && typeof imagesIds !== "object" && imagesIds.length < 1) {
that._logger.log(that.WARN, LOG_ID + "(createItem) bad or empty 'imagesIds' parameter ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(createItem) bad or empty 'imagesIds' parameter : ", imagesIds);
return Promise.reject(ErrorManager.getErrorManager().BAD_REQUEST);
}
if (type && ["basic", "markdown", "html", "data"].indexOf(type) === -1) {
that._logger.log(that.WARN, LOG_ID + "(createItem) bad or empty 'type' parameter ", type, " \"Parameter 'type' could be 'basic', 'markdown', 'html' or 'data'\"");
return Promise.reject(ErrorManager);
}
return new Promise((resolve, reject) => {
type = type ? "urn:xmpp:channels:" + type : "urn:xmpp:channels:basic";
that._rest.publishMessage(channel.id, message, title, url, imagesIds, type, customDatas).then((status) => {
that._logger.log(that.INFO, LOG_ID + "(createItem) message published");
that._logger.log(that.INTERNAL, LOG_ID + "(createItem) message published : ", status);
resolve(Object.assign({"publishResult" : status}, ErrorManager.getErrorManager().OK));
}).catch((err) => {
that._logger.log(that.ERROR, LOG_ID + "(createItem) error ");
that._logger.log(that.INTERNALERROR, LOG_ID + "(createItem) error : ", err);
return reject(err);
});
});
}
/**
* @public
* @nodered true
* @method fetchChannelItems
* @instance
* @async
* @category Channels MESSAGES/ITEMS
* @param {Channel} channel The channel
* @param {number} maxMessages=100 [optional] number of messages to get, 100 by default
* @param {Date} beforeDate [optional] - show items before a specific timestamp (ISO 8601 format)
* @param {Date} afterDate [optional] - show items after a specific timestamp (ISO 8601 format)
* @return {Promise