'use strict';
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/*
* Nexmo Client SDK
* Conversation Object Model
*
* Copyright (c) Nexmo Inc.
*/
const WildEmitter = require('wildemitter');
const loglevel_1 = require("loglevel");
const nexmoClientError_1 = require("./nexmoClientError");
const member_1 = __importDefault(require("./member"));
const nxmEvent_1 = __importDefault(require("./events/nxmEvent"));
const text_event_1 = __importDefault(require("./events/text_event"));
const message_event_1 = __importDefault(require("./events/message_event"));
const media_1 = __importDefault(require("./modules/media"));
const conversation_events_1 = __importDefault(require("./handlers/conversation_events"));
const utils_1 = __importDefault(require("./utils"));
const page_config_1 = __importDefault(require("./pages/page_config"));
const events_page_1 = __importDefault(require("./pages/events_page"));
const members_page_1 = __importDefault(require("./pages/members_page"));
const application_1 = __importDefault(require("./application"));
/**
* A single conversation Object.
* @class Conversation
* @property {Member} me - my Member object that belongs to this conversation
* @property {Application} application - the parent Application
* @property {string} name - the name of the Conversation (unique)
* @property {string} [display_name] - the display_name of the Conversation
* @property {Map<string, Member>} [members] - the members of the Conversation keyed by a member's id
* @property {Map<string, NXMEvent>} [events] - the events of the Conversation keyed by an event's id
* @property {number} [sequence_number] - the last event id
*/
class Conversation {
constructor(application, params) {
this.log = loglevel_1.getLogger(this.constructor.name);
this.application = application;
this.id = null;
this.name = null;
this.display_name = null;
this.timestamp = null;
this.members = new Map();
this.events = new Map();
this.sequence_number = 0;
this.pageConfig = new page_config_1.default(((this.application.session || {}).config || {}).events_page_config);
this.events_page_last = null;
this.members_page_last = null;
this.conversationEventHandler = new conversation_events_1.default(application, this);
this.media = new media_1.default(this);
/**
* A Member Object representing the current user.
* Only set if the user is or has been a member of the Conversation,
* otherwise the value will be `null`.
* @type Member
*/
this.me = null; // We are not in the conversation ourselves by default
// Map the params (which includes the id)
this._updateObjectInstance(params);
WildEmitter.mixin(Conversation);
}
/** Update Conversation object params
* @property {object} params the params to update
* @private
*/
_updateObjectInstance(params) {
for (let key in params) {
switch (key) {
case 'id':
this.id = params.id;
break;
case 'name':
this.name = params.name;
break;
case 'display_name':
this.display_name = params.display_name;
break;
case 'members':
// update the conversation javascript object
params.members.forEach((m) => {
if (this.members.has(m.member_id)) {
this.members.get(m.member_id)._normalise(m);
if (m.user_id === this.application.me.id && m.state !== 'LEFT') {
this.me = this.members.get(m.member_id);
this.members.set(this.me.id, this.me);
}
}
else {
const member = new member_1.default(this, m);
if (m.user_id === this.application.me.id && m.state !== 'LEFT') {
this.me = member;
}
this.members.set(member.id, member);
}
});
break;
case 'timestamp':
this.timestamp = params.timestamp;
break;
case 'sequence_number':
this.sequence_number = params.sequence_number;
break;
case 'member_id':
// filter needed params to create the object
// the conversation list gives us the member_id to prepare the member/this object
const object_params = {
id: params.member_id,
state: params.state,
user: this.application.me
};
// update the member object or create a new instance
if (this.members.has(params.member_id)) {
const member_object = this.members.get(params.member_id);
Object.assign(member_object, object_params);
}
else {
const member = new member_1.default(this, object_params);
this.me = member;
this.members.set(member.id, member);
}
break;
}
}
}
/**
* Join the given User to this Conversation. Will typically be used this to join
* ourselves to a Conversation we create.
* Accept an invitation if our Member has state INVITED and no user_id / user_name is given
*
* @param {object} [params = this.application.me.id] The User to join (defaults to this)
* @param {string} params.user_name the user_name of the User to join
* @param {string} params.user_id the user_id of the User to join
* @returns {Promise<Member>}
*
* @example <caption>join a user to the Conversation</caption>
*
* conversation.join().then((member) => {
* console.log("joined as member: ", member)
* }).catch((error) => {
* console.error("error joining conversation ", error);
* });
*/
async join(params) {
var _a, _b;
try {
let data = {
state: 'joined',
channel: {
type: 'app'
},
user: {
...(!params && { name: this.application.me.name, id: this.application.me.id }),
...(params && params.user_name && { name: params.user_name }),
...(params && params.user_id && { id: params.user_id }),
},
};
if (((_a = this === null || this === void 0 ? void 0 : this.me) === null || _a === void 0 ? void 0 : _a.id) && ((_b = this === null || this === void 0 ? void 0 : this.me) === null || _b === void 0 ? void 0 : _b.state) !== 'LEFT') {
data["from"] = this.me.id;
}
const response = await this.application.session.sendNetworkRequest({
type: 'POST',
path: `conversations/${this.id}/members`,
version: 'v0.3',
data
});
const member = new member_1.default(this, response);
if (response._embedded.user.id === this.application.me.id) {
this.me = member;
this.members.set(member.id, member);
}
// use case where between the time we got the conversation and the time we finished joining
// the conversation object changed.
this.application.getConversation(this.id, application_1.default.CONVERSATION_API_VERSION.v3);
return member;
}
catch (error) {
throw new nexmoClientError_1.NexmoApiError(error);
}
}
/**
* Delete a conversation
* @returns {Promise}
* @example <caption>delete the Conversation</caption>
*
* conversation.del().then(() => {
* console.log("conversation deleted");
* }).catch((error) => {
* console.error("error deleting conversation ", error);
* });
*/
async del() {
try {
const response = await this.application.session.sendNetworkRequest({
type: 'DELETE',
path: `conversations/${this.id}`
});
this.application.conversations.delete(this.id);
return response;
}
catch (error) {
throw new nexmoClientError_1.NexmoApiError(error);
}
}
/**
* Delete an NXMEvent (e.g. Text)
* @param {NXMEvent} event
* @returns {Promise}
* @example <caption>delete an Event</caption>
*
* conversation.deleteEvent(eventToBeDeleted).then(() => {
* console.log("event was deleted");
* }).catch((error) => {
* console.error("error deleting the event ", error);
* });
*
*/
deleteEvent(event) {
return event.del();
}
/**
* Invite the given user (id or name) to this conversation
* @param {Member} params
* @param {string} [params.id or user_name] - the id or the username of the User to invite
*
* @returns {Promise<Member>}
*
* @example <caption>invite a user to a Conversation</caption>
* const user_id = 'id of User to invite';
* const user_name = 'username of User to invite';
*
* conversation.invite({
* id: user_id,
* user_name: user_name
* }).then((member) => {
* displayMessage(member.state + " user: " + user_id + " " + user_name);
* }).catch((error) => {
* console.error("error inviting user ", error);
* });
*
*/
async invite(params) {
var _a, _b;
if (!params || (!params.id && !params.user_name)) {
throw new nexmoClientError_1.NexmoClientError('error:invite:missing:params');
}
const data = {
state: 'invited',
user: {
...(params.id && { id: params.id }),
...(params.user_name && { name: params.user_name })
},
media: params.media,
channel: {
from: {
type: 'app'
},
to: {
type: 'app'
},
type: 'app'
}
};
if (((_a = this === null || this === void 0 ? void 0 : this.me) === null || _a === void 0 ? void 0 : _a.id) && ((_b = this === null || this === void 0 ? void 0 : this.me) === null || _b === void 0 ? void 0 : _b.state) !== 'LEFT') {
data["from"] = this.me.id;
}
try {
const response = await this.application.session.sendNetworkRequest({
type: 'POST',
path: `conversations/${this.id}/members`,
version: 'v0.3',
data
});
const member = new member_1.default(this, response);
return member;
}
catch (error) {
throw new nexmoClientError_1.NexmoApiError(error);
}
}
/**
* Invite the given user (id or name) to this conversation with media audio
* @param {Member} params
* @param {string} [params.id or user_name] - the id or the username of the User to invite
*
* @returns {Promise<Member>}
*
* @example <caption>invite a user to a conversation</caption>
* const user_id = 'id of User to invite';
* const user_name = 'username of User to invite';
*
* conversation.inviteWithAudio({
* id: user_id,
* user_name: user_name
* }).then((member) => {
* displayMessage(member.state + " user: " + user_id + " " + user_name);
* }).catch((error) => {
* console.error("error inviting user ", error);
* });
*
*/
inviteWithAudio(params) {
if (!params || (!params.id && !params.user_name)) {
return Promise.reject(new nexmoClientError_1.NexmoClientError('error:invite:missing:params'));
}
params.media = {
audio_settings: {
enabled: true,
muted: false,
earmuffed: false
}
};
return this.invite(params);
}
/**
* Leave from the Conversation
* @param {object} [reason] the reason for leaving the conversation
* @param {string} [reason.reason_code] the code of the reason
* @param {string} [reason.reason_text] the description of the reason
* @returns {Promise}
* @example <caption>leave the Conversation</caption>
*
* conversation.leave({reason_code: "mycode", reason_text: "my reason for leaving"}).then(() => {
* console.log("successfully left conversation");
* }).catch((error) => {
* console.error("error leaving conversation ", error);
* });
*
*/
leave(reason) {
return this.me.kick(reason);
}
/**
* Send a text message to the conversation, which will be relayed to every other member of the conversation
* @param {string} text - the text message to be sent
*
* @returns {Promise<TextEvent>} - the text message that was sent
*
* @example <caption> sending a text </caption>
* conversation.sendText("Hi Vonage").then((event) => {
* console.log("message was sent", event);
* }).catch((error)=>{
* console.error("error sending the message ", error);
* });
*
* @deprecated since version 8.3.0
*
*/
async sendText(text) {
try {
if (this.me === null) {
throw new nexmoClientError_1.NexmoClientError('error:self');
}
const msg = {
type: 'text',
cid: this.id,
from: this.me.id,
body: {
text
}
};
const { id, timestamp } = await this.application.session.sendNetworkRequest({
type: 'POST',
path: `conversations/${this.id}/events`,
data: msg
});
msg.id = id;
msg.body.timestamp = timestamp;
return new text_event_1.default(this, msg);
}
catch (error) {
throw new nexmoClientError_1.NexmoApiError(error);
}
}
/**
* Send a custom event to the Conversation
* @param {object} params - params of the custom event
* @param {string} params.type the name of the custom event. Must not exceed 100 char length and contain only alpha numerics and '-' and '_' characters.
* @param {object} params.body customizable key value pairs
*
* @returns {Promise<NXMEvent>} - the custom event that was sent
*
* @example <caption> sending a custom event </caption>
* conversation.sendCustomEvent({ type: "my-event", body: { mykey: "my value" }}).then((event) => {
* console.log("custom event was sent", event);
* }).catch((error)=>{
* console.error("error sending the custom event", error);
* });
*
*/
async sendCustomEvent({ type, body }) {
try {
if (this.me === null) {
throw new nexmoClientError_1.NexmoClientError('error:self');
}
else if (!type || typeof type !== 'string' || type.length < 1) {
throw new nexmoClientError_1.NexmoClientError('error:custom-event:invalid');
}
const data = {
type: `custom:${type}`,
cid: this.id,
from: this.me.id,
body
};
const { id, timestamp } = await this.application.session.sendNetworkRequest({
type: 'POST',
path: `conversations/${this.id}/events`,
data
});
data.id = id;
data.timestamp = timestamp;
return new nxmEvent_1.default(this, data);
}
catch (error) {
throw new nexmoClientError_1.NexmoApiError(error);
}
}
/**
* Send an ephemeral event to the Conversation
* @param {object} body - customizable key value pairs
*
* @returns {Promise<NXMEvent>} - the ephemeral event that was sent
*
* @example <caption> sending an ephemeral event </caption>
* conversation.sendEphemeralEvent({ mykey: "my value" }).then((event) => {
* console.log("ephemeral event was sent", event);
* }).catch((error)=>{
* console.error("error sending the ephemeral event", error);
* });
*
*/
async sendEphemeralEvent(body) {
try {
if (this.me === null) {
throw new nexmoClientError_1.NexmoClientError('error:self');
}
const data = {
type: 'ephemeral',
cid: this.id,
from: this.me.id,
body
};
const { id, timestamp } = await this.application.session.sendNetworkRequest({
type: 'POST',
path: `conversations/${this.id}/events`,
data
});
data.timestamp = timestamp;
return new nxmEvent_1.default(this, data);
}
catch (error) {
throw new nexmoClientError_1.NexmoApiError(error);
}
}
/**
* Uploads an Image to Media Service.
* implements xhr (https://xhr.spec.whatwg.org/) - this.imageRequest
*
* @param {File} file single input file (jpeg/jpg)
* @param {object} params - params of image sent
* @param {string} [params.quality_ratio = 100] a value between 0 and 100. 0 indicates 'maximum compression' and the lowest quality, 100 will result in the highest quality image
* @param {string} [params.medium_size_ratio = 50] a value between 1 and 100. 1 indicates the new image is 1% of original, 100 - same size as original
* @param {string} [params.thumbnail_size_ratio = 30] a value between 1 and 100. 1 indicates the new image is 1% of original, 100 - same size as original
*
* @returns {Promise<XMLHttpRequest>}
*
* @example <caption>uploading an image</caption>
* const params = {
* quality_ratio : "90",
* medium_size_ratio: "40",
* thumbnail_size_ratio: "20"
* }
* conversation.uploadImage(fileInput.files[0], params).then((uploadImageRequest) => {
* uploadImageRequest.onprogress = (e) => {
* console.log("Image request progress: ", e);
* console.log("Image progress: " + e.loaded + "/" + e.total);
* };
* uploadImageRequest.onabort = (e) => {
* console.log("Image request aborted: ", e);
* console.log("Image: " + e.type);
* };
* uploadImageRequest.onloadend = (e) => {
* console.log("Image request successful: ", e);
* console.log("Image: " + e.type);
* };
* uploadImageRequest.onreadystatechange = () => {
* if (uploadImageRequest.readyState === 4 && uploadImageRequest.status === 200) {
* const representations = JSON.parse(uploadImageRequest.responseText);
* console.log("Original image url: ", representations.original.url);
* console.log("Medium image url: ", representations.medium.url);
* console.log("Thumbnail image url: ", representations.thumbnail.url);
* }
* };
* }).catch((error) => {
* console.error("error uploading the image ", error);
* });
*/
async uploadImage(fileInput, params = {
quality_ratio: '100',
medium_size_ratio: '50',
thumbnail_size_ratio: '30'
}) {
const formData = new FormData();
formData.append('file', fileInput);
formData.append('quality_ratio', params.quality_ratio);
formData.append('medium_size_ratio', params.medium_size_ratio);
formData.append('thumbnail_size_ratio', params.thumbnail_size_ratio);
const imageRequest = await utils_1.default.networkRequest({
type: 'POST',
url: this.application.session.config.ips_url,
data: formData,
token: this.application.session.config.token
});
imageRequest.upload.addEventListener('progress', (evt) => {
if (evt.lengthComputable) {
this.log.debug('uploading image ' + evt.loaded + '/' + evt.total);
}
}, false);
imageRequest.onreadystatechange = () => {
if (imageRequest.status !== 200) {
this.log.error(imageRequest);
}
};
return imageRequest;
}
/**
* Send an Image message to the conversation, which will be relayed to every other member of the conversation.
* implements xhr (https://xhr.spec.whatwg.org/) - this.imageRequest
*
* @param {File} file single input file (jpeg/jpg)
* @param {object} params - params of image sent
* @param {string} [params.quality_ratio = 100] a value between 0 and 100. 0 indicates 'maximum compression' and the lowest quality, 100 will result in the highest quality image
* @param {string} [params.medium_size_ratio = 50] a value between 1 and 100. 1 indicates the new image is 1% of original, 100 - same size as original
* @param {string} [params.thumbnail_size_ratio = 30] a value between 1 and 100. 1 indicates the new image is 1% of original, 100 - same size as original
*
* @returns {Promise<XMLHttpRequest>}
*
* @example <caption>sending an image</caption>
* const params = {
* quality_ratio : "90",
* medium_size_ratio: "40",
* thumbnail_size_ratio: "20"
* }
* conversation.sendImage(fileInput.files[0], params).then((imageRequest) => {
* imageRequest.onprogress = (e) => {
* console.log("Image request progress: ", e);
* console.log("Image progress: " + e.loaded + "/" + e.total);
* };
* imageRequest.onabort = (e) => {
* console.log("Image request aborted: ", e);
* console.log("Image: " + e.type);
* };
* imageRequest.onloadend = (e) => {
* console.log("Image request successful: ", e);
* console.log("Image: " + e.type);
* };
* }).catch((error) => {
* console.error("error sending the image ", error);
* });
*
* @deprecated since version 8.3.0
*/
async sendImage(fileInput, params = {
quality_ratio: '100',
medium_size_ratio: '50',
thumbnail_size_ratio: '30'
}) {
const imageRequest = await this.uploadImage(fileInput, params);
imageRequest.onreadystatechange = () => {
if (imageRequest.readyState === 4 && imageRequest.status === 200) {
try {
this.application.session.sendNetworkRequest({
type: 'POST',
path: `conversations/${this.id}/events`,
data: {
type: 'image',
from: this.me.id,
body: {
representations: JSON.parse(imageRequest.responseText)
}
}
});
this.log.info(imageRequest);
}
catch (error) {
this.log.error(new nexmoClientError_1.NexmoApiError(error));
}
}
};
return imageRequest;
}
/**
* Cancel uploading or sending an Image message to the conversation.
*
* @param {XMLHttpRequest} imageRequest
*
* @returns void
*
* @example <caption>cancel sending an image</caption>
* conversation.sendImage(fileInput.files[0]).then((imageRequest) => {
* conversation.abortSendImage(imageRequest);
* }).catch((error) => {
* console.error("error sending the image ", error);
* });
*
* @example <caption>cancel uploading an image</caption>
* conversation.uploadImage(fileInput.files[0]).then((imageRequest) => {
* conversation.abortSendImage(imageRequest);
* }).catch((error) => {
* console.error("error uploading the image ", error);
* });
*/
abortSendImage(imageRequest) {
if (imageRequest instanceof XMLHttpRequest) {
return imageRequest.abort();
}
else {
return new nexmoClientError_1.NexmoClientError('error:invalid:param:type');
}
}
/**
* Send a message event to the conversation, which will be relayed to every other member of the conversation
*
* @param {object} params the content of the message you want sent
* @param {string} params.message_type the type of the message. It should be one of 'text', 'image', 'audio', 'video', 'file'
* @param {string} [params.text] the text content when message type is 'text
* @param {object} [params.image]
* @param {string} params.image.url the image url when message type is 'image'
* @param {object} [params.audio]
* @param {string} params.audio.url the audio url when message type is 'audio'
* @param {object} [params.video]
* @param {string} params.video.url the video url when message type is 'video'
* @param {object} [params.file]
* @param {string} params.file.url the file url when message type is 'file'
*
* @returns {Promise<MessageEvent>} - the message that was sent
*
* @example <caption> sending a message </caption>
* conversation.sendMessage({ "message_type": "text", "text": "Hi Vonage!" }).then((event) => {
* console.log("message was sent", event);
* }).catch((error)=>{
* console.error("error sending the message ", error);
* });
*
*/
async sendMessage(params) {
if (this.me === null) {
throw new nexmoClientError_1.NexmoClientError('error:self');
}
else if (!(params === null || params === void 0 ? void 0 : params.message_type)) {
throw new nexmoClientError_1.NexmoClientError('error:message-event:invalid');
}
try {
const msg = {
type: 'message',
cid: this.id,
from: this.me.id,
body: {
...params
}
};
const { id, timestamp } = await this.application.session.sendNetworkRequest({
type: 'POST',
path: `conversations/${this.id}/events`,
data: msg
});
msg.id = id;
msg.body.timestamp = timestamp;
return new message_event_1.default(this, msg);
}
catch (error) {
throw new nexmoClientError_1.NexmoApiError(error);
}
}
async _typing(state) {
const params = {
activity: (state === 'on') ? 1 : 0
};
const data = {
type: 'text:typing:' + state,
cid: this.id,
from: this.me.id,
body: params
};
try {
await this.application.session.sendNetworkRequest({
type: 'POST',
path: `conversations/${this.id}/events`,
data
});
return `text:typing:${state}:success`;
}
catch (error) {
throw new nexmoClientError_1.NexmoApiError(error);
}
}
/**
* Send start typing indication
*
* @returns {Promise} - resolves the promise on successful sent
*
* @example <caption>send start typing event when key is pressed</caption>
* messageTextarea.addEventListener('keypress', (event) => {
* conversation.startTyping();
* });
*/
startTyping() {
return this._typing('on');
}
/**
* Send stop typing indication
*
* @returns {Promise} - resolves the promise on successful sent
*
* @example <caption>send stop typing event when a key has not been pressed for half a second</caption>
* let timeout = null;
* messageTextarea.addEventListener('keyup', (event) => {
* clearTimeout(timeout);
* timeout = setTimeout(() => {
* conversation.stopTyping();
* }, 500);
* });
*/
stopTyping() {
return this._typing('off');
}
/**
* Query the service to get a list of events in this conversation.
*
* @param {object} params configure defaults for paginated events query
* @param {string} params.order 'asc' or 'desc' ordering of resources based on creation time
* @param {number} params.page_size the number of resources returned in a single request list
* @param {string} [params.cursor] string to access the starting point of a dataset
* @param {string} [params.event_type] the type of event used to filter event requests. Supports wildcard options with :* eg. 'members:*'
*
* @returns {Promise<EventsPage<Map<Events>>>} - Populate Conversations.events.
* @example <caption>Get Events</caption>
* conversation.getEvents({ event_type: 'member:*' }).then((events_page) => {
* events_page.items.forEach(event => {
* render(event)
* })
* }).catch((error) => {
* console.error("error getting the events ", error);
* });
*/
async getEvents(params = {}) {
const url = `${this.application.session.config.nexmo_api_url}/beta2/conversations/${this.id}/events`;
// Create pageConfig if given params otherwise use default
let pageConfig = Object.keys(params).length === 0 ? this.pageConfig : new page_config_1.default(params);
try {
const response = await utils_1.default.paginationRequest(url, pageConfig, this.application.session.config.token);
response.application = this.application;
response.conversation = this;
const events_page = new events_page_1.default(response);
this.events_page_last = events_page;
return events_page;
}
catch (error) {
throw new nexmoClientError_1.NexmoApiError(error);
}
}
/**
* Query the service to get a list of members in this conversation.
*
* @param {object} params configure defaults for paginated events query
* @param {string} params.order 'asc' or 'desc' ordering of resources based on creation time
* @param {number} params.page_size the number of resources returned in a single request list
* @param {string} [params.cursor] string to access the starting point of a dataset
*
* @returns {Promise<MembersPage<Map<Member>>>}
* @example <caption>Get Members</caption>
* const params = {
* order: "desc",
* page_size: 100
* }
* conversation.getMembers(params).then((members_page) => {
* members_page.items.forEach(member => {
* render(member)
* })
* }).catch((error) => {
* console.error("error getting the members ", error);
* });
*/
async getMembers(params = {}) {
const url = `${this.application.session.config.nexmo_api_url}/beta2/conversations/${this.id}/members`;
// Create pageConfig if given params otherwise use default
let pageConfig = Object.keys(params).length === 0 ? this.pageConfig : new page_config_1.default(params);
try {
const response = await utils_1.default.paginationRequest(url, pageConfig, this.application.session.config.token);
response.application = this.application;
response.conversation = this;
const members_page = new members_page_1.default(response);
this.members_page_last = members_page;
return members_page;
}
catch (error) {
throw new nexmoClientError_1.NexmoApiError(error);
}
}
/**
* Query the service to get my member in this conversation.
*
* @returns {Promise<Member>}
* @example <caption>Get My Member</caption>
* conversation.getMyMember().then((member) => {
* render(member)
* }).catch((error) => {
* console.error("error getting my member", error);
* });
*/
async getMyMember() {
try {
const response = await this.application.session.sendNetworkRequest({
type: 'GET',
path: `conversations/${this.id}/members/me`,
version: 'v0.3'
});
const member = new member_1.default(this, response);
return member;
}
catch (error) {
throw new nexmoClientError_1.NexmoApiError(error);
}
}
/**
* Query the service to get a member in this conversation.
*
* @param {string} member_id the id of the member to return
*
* @returns {Promise<Member>}
* @example <caption>Get Member</caption>
* conversation.getMember("MEM-id").then((member) => {
* render(member)
* }).catch((error) => {
* console.error("error getting member", error);
* });
*/
async getMember(member_id) {
try {
const response = await this.application.session.sendNetworkRequest({
type: 'GET',
path: `conversations/${this.id}/members/${member_id}`,
version: 'v0.3'
});
const member = new member_1.default(this, response);
return member;
}
catch (error) {
throw new nexmoClientError_1.NexmoApiError(error);
}
}
/**
* Handle and event from the cloud.
* using conversationEventHandler
* @param {object} event
* @private
*/
_handleEvent(event) {
var _a, _b;
if (event.type.startsWith('rtc')) {
// keep the rtc events going to the application layer, we use them in media module
this.emit(event.type, event);
return Promise.resolve(event);
}
this.sequence_number++;
// make sure the event_id is not a string
if (event.body && event.body.event_id && typeof event.body.event_id === 'string') {
event.body.event_id = parseInt(event.body.event_id);
}
let memberInfo = { memberId: event.from };
if ((_a = event === null || event === void 0 ? void 0 : event.body) === null || _a === void 0 ? void 0 : _a.user) {
const { id, name, display_name, image_url, custom_data } = event.body.user;
memberInfo = { ...memberInfo, ...{
...(id && { userId: id }),
...(name && { userName: name }),
...(display_name && { displayName: display_name }),
...(image_url && { imageUrl: image_url }),
...(custom_data && { customData: custom_data })
} };
}
else if ((_b = event === null || event === void 0 ? void 0 : event._embedded) === null || _b === void 0 ? void 0 : _b.from_user) {
const { id, name, display_name, image_url, custom_data } = event._embedded.from_user;
memberInfo = { ...memberInfo, ...{
...(id && { userId: id }),
...(name && { userName: name }),
...(display_name && { displayName: display_name }),
...(image_url && { imageUrl: image_url }),
...(custom_data && { customData: custom_data })
} };
}
let constructed_event = this.conversationEventHandler.handleEvent(event);
// Unless they are typing events, add the event to the conversation.events map
if (!['text:typing:on', 'text:typing:off', 'ephemeral'].includes(event.type)) {
this.events.set(constructed_event.id, constructed_event);
}
// For custom events remove the custom: prefix before emitting event
if (event.type.startsWith('custom:')) {
this.emit(constructed_event.type, memberInfo, constructed_event);
return Promise.resolve(event);
}
this.emit(event.type, memberInfo, constructed_event);
return Promise.resolve(event);
}
}
exports.default = Conversation;
module.exports = Conversation;