Skip to main content

How to Send Messages to an x-bees Channel using the x-bees Conversations SDK and Node.js

· 5 min read
Vladimir Gorobets
Vladimir Gorobets
Software Engineer

This tutorial will help you send messages to an x-bees channel using the x-bees Conversations SDK and Node.js.

Introduction

Wildix offers a unified communications solution with various tools, including x-bees, for efficient team collaboration. By integrating the x-bees Conversations SDK, you can automate notifications from your services to x-bees channels, enhancing the overall user experience. This guide will help you create a basic example of sending a message with an attachment to an x-bees conversation channel.

Prerequisites

Before you begin, ensure you have the following:

  • Basic knowledge of programming and system settings.
  • PBX with x-bees or x-hoppers licenses
  • Admin Access to the Wildix Management System (WMS) To retrieve your pbxSerial and pbxKey.
  • Node.js and npm: Ensure you have Node.js (version 18.x or higher) and npm installed.
  • Git: For cloning the repository.

Step 1: Clone the Examples Repository

Open your terminal and run the following commands:

git clone https://github.com/Wildix/sdk-examples.git
cd sdk-examples

Step 2: Install the Required Packages

Navigate to the conversation-api-send-message example directory and install the necessary packages:

cd examples/conversation-api-send-message
npm install

Step 3: Configure the Demo Script

  1. Login to the WMS terminal:
  • Login to your WMS.
  • Open the Terminal (found in the header menu).
  • Press Enter key.
  1. Receive pbxSerial and pbxKey:
  • Paste command cat /rw2/etc/sf2 | head -18 | tail -2 | xargs printf "pbxSerial: %s\npbxKey: %s\n" to the terminal and press Enter button.
  • Copy the pbxSerial value and paste it to PBX_SERIAL variable in ./src/index.ts file.
  • Copy the pbxKey value and paste it to PBX_KEY variable in ./src/index.ts file.
  1. Get the Channel ID:
  • Open x-bees in your browser.
  • Select your conversation.
  • Copy the channelId from the browser’s URL: https://app.x-bees.com/inbox/<channelId>
  • Paste channelId to variable XBS_CHANNEL_ID in ./src/index.ts file.
  1. Retrieve the User ID:
  • Open x-bees in your browser.
  • Open the DevTools console in your browser.
  • Paste and run the following command wx.stream._user.id
  • Copy the returned userId
  • Paste the userId to variable XBS_USER_FROM_ID in ./src/index.ts file.

Step 4: Run the Script

Run Script using the following command:

npm run start

A message with the attachment will be sent to your x-bees channel.

Warning

The user on whose behalf you will send a message to the channel must be present in this channel, otherwise you will get an error.

Code

Here’s a detailed explanation of the code for sending message with attachments to the x-bees channel:

import fs from 'fs';
import {PbxTokenProvider} from '@wildix/auth-utils';
import {
ConversationsClient,
GetUploadedFileInfoCommand,
SendMessageCommand,
UploadFileCommand,
} from '@wildix/xbees-conversations-client';

/*
* PBX serial & key
*
* You can receive this values after login to your PBX by ssh
* and run command `cat /rw2/etc/sf2 | head -18 | tail -2 | xargs printf "pbxSerial: %s\npbxKey: %s\n"`
* */
const PBX_SERIAL = '<pbxSerial>';
const PBX_KEY = '<pbxKey>';

/*
* x-bees channel ID
*
* You can copy the channel ID into the URL input field of your browser
* https://app.x-bees.com/inbox/<channelId>
*/
const XBS_CHANNEL_ID = '<channelId>';

/*
* x-bees userId
*
* You can get the x-bees user ID by running the following command in your browser
* from the x-bees page in the devtools console: wx.stream._user.id
*/
const XBS_USER_FROM_ID = '<userId>';

(async () => {
try {
const sendMessageResponse = await sendMessageWithAttachments(XBS_CHANNEL_ID, XBS_USER_FROM_ID, `Test message from x-bees Conversation API v2 ${new Date().toISOString()}`, [
{path: 'xbs_logo.png', contentType: 'image/png'},
{path: 'wildix_logo.png', contentType: 'image/png'},
]);
console.log('sendMessageResponse:', sendMessageResponse);
} catch (error) {
console.error('Send message error:', error);
}
})();

/**
* Sends a message to a specified channel with optional file attachments.
*
* This function first uploads any provided files to a storage service and then sends a message
* containing the text and metadata of the uploaded files to the specified channel.
*
* @async
* @param {string} channelId - The ID of the channel where the message will be sent.
* @param {string} userId - The ID of the x-bees user.
* @param {string} text - The text content of the message to be sent.
* @param {Attachment[]} [files] - An optional array of files to be attached to the message.
* Each file should contain properties like `path` and `contentType`.
*
* @returns {Promise<SendMessageOutput>} - A promise that resolves with the output of the send message operation.
* The output typically contains details about the sent message.
*
* @throws {Error} - Throws an error if the message sending or file upload fails.
* Possible reasons include invalid channel ID, file upload errors, or network issues.
*/
async function sendMessageWithAttachments(channelId, userId, text, files) {
const pbxTokenProvider = new PbxTokenProvider(PBX_SERIAL, PBX_KEY);
const client = new ConversationsClient({token: pbxTokenProvider, env: 'prod'});
let attachments = [];
if (files) {
attachments = await Promise.all(files.map((attachment) => uploadAttachment(client, channelId, userId, attachment)));
}
return client.send(new SendMessageCommand({
channelId,
text,
userId,
attachments,
}));
}

async function uploadFileToS3(presignedUploadUrl, filePath, contentType = '') {
const fileContent = fs.readFileSync(filePath);
const response = await fetch(presignedUploadUrl, {
method: 'PUT',
headers: {'Content-Type': contentType},
body: fileContent,
});
if (!response.ok) {
throw new Error(`Failed to upload file: ${response.statusText}`);
}
return response;
}

async function uploadAttachment(client, channelId, userId, attachment) {
const {fileId, presignedUploadUrl} = await client.send(new UploadFileCommand({
channelId,
name: attachment.path,
userId,
}));
const {statusText} = await uploadFileToS3(presignedUploadUrl, attachment.path, attachment.contentType);
console.log(`Upload attachment ${attachment.path} result: ${statusText}`);
const getFileInfoResponse = await client.send(new GetUploadedFileInfoCommand({
channelId,
fileId,
}));
return getFileInfoResponse.file;
}

Live demo

https://codesandbox.io/p/devbox/54yytf