JavaScript
Group Channel Advanced

Group Channel: Advanced

This page explains the advanced features for group channels. Some of them are the premium features available only to a paying user.


Add users as friends

To find and chat with other users within the application easily, users can add friends by using unique identifiers such as hashed phone numbers for privacy. When the unique identifier, which is used as the discovering keys, linked to a user using our service is uploaded, the SendBird system can match and retrieve the users and then automatically register them as friends.

Note: To use this ability, you should make sure the unique identifiers of every user are registered individually in advance by using the platform API's update a user action.

Light Color Skin
Copy
// Uploading friend discovery keys
var discoveryMap = {
    '0001-0002-0003': 'John',
    '0004-0005-0006': 'Jay',
    '0007-0008-0009': 'Jin'
};
sb.uploadFriendDiscoveries(discoveryMap, function(response, error) {
    if (error) {
        return;
    }
});

// Deleting friend discovery keys
var discoveryKeys = [
    '0001-0002-0003',
    '0004-0005-0006'
];
sb.deleteFriendDiscoveries(discoveryKeys, function(response, error) {
    if (error) {
        return;
    }
});

Or you can make any user add and delete friends by using an array of the IDs of other users like the below.

Light Color Skin
Copy
var userIds = ['Harry'];

// Adding friends
sb.addFriends(userIds, function(response, error) {
    if (error) {
        return;
    }
});

// Deleting friends
sb.deleteFriends(userIds, function(response, error) {
    if (error) {
        return;
    }
});

After creating a query instance from the createFriendListQuery() method and using the next() method which returns a list of User objects, you can retrieve a list.

Light Color Skin
Copy
var friendListQuery = sb.createFriendListQuery();
friendListQuery.next(function(users, error) {
    if (error) {
        return;
    }

    console(users);
});

Send typing indicators to other members

If the startTyping() and endTyping() methods are called when a user is typing a text message, SendBird server notifies of the event to the client apps of all channel members through the onTypingStatusUpdate() of the registered channel event handler.

Light Color Skin
Copy
groupChannel.startTyping();
groupChannel.endTyping();
...

// To listen for an update from all the other channel members' client apps, implement the 'onTypingStatusUpdated()' with things to do when notified.  
var handler = new sb.ChannelHandler();
handler.onTypingStatusUpdated = function(groupChannel) {
    var members = groupChannel.getTypingMembers();
    // Refresh typing status of members within channel.
};

sb.addChannelHandler(UNIQUE_HANDLER_ID, handler);

Mark messages as read

To maintain the most up-to-date and accurate read status of messages for each member in a group channel, the markAsRead() method should be called when any one of the members reads messages in the channel by entering the channel from a channel list or making the opened channel view in the background to be active on the screen.

When the markAsRead() is called, SendBird server updates the number of the current user's unread messages both in a group channel and in all joined channels. The server then notifies the change of read status to all the other channel members' client apps through the onReadReceiptUpdated() method of the channel event handler.

Light Color Skin
Copy
// Call the 'markAsRead()' when the current user views unread messages in a group channel. 
groupChannel.markAsRead();
...

// To listen for an update from all the other channel members' client apps, implement the 'onReadReceiptUpdated()' with things to do when notified.  
var handler = new sb.ChannelHandler();
handler.onReadReceiptUpdated = function(groupChannel) { 
    if (currentGroupChannel.url === groupChannel.url) { 
        // For example, code for redrawing a channel view. 
    }
};

sb.addChannelHandler(UNIQUE_HANDLER_ID, handler);

Retrieve members who have read a message

Using the getReadMembers() method, you can view members who have read a specific message in a group channel. A list of the members for each message is depending on the read receipt of each member.

If you want to keep track of who have read a new message, we recommend you implement the getReadMembers() in the onReadReceiptUpdated() method. Then it will receive a callback from SendBird server when any other member has read a message. Afterwards you should pass the newly received message object via the onReadReceiptUpdated() to the getReadMembers() as a parameter.

Light Color Skin
Copy
var readMembers = groupChannel.getReadMembers(MESSAGE);

The getReadMembers() returns a list of members who have read a message except the current user and the message sender.

Note: Using the getUnreadMembers() method, you can also view members who have not read a specific message in a group channel, except the current user and the message sender. And using the getReadStatus() method, you can get a list of information on the read receipt of each member, except the current user. The read receipt indicates the timestamp of when each user has last read the messages in the channel, in Unix milliseconds.


Retrieve number of members who have not read a message

Using the getReadReceipt() method, you can get the number of members who have not read a specific message in a group channel. To get the exact value, you should first update the channel by the markAsRead() before calling the getReadReceipt().

Light Color Skin
Copy
// Call the 'markAsRead()' when the current user views unread messages in a group channel. 
groupChannel.markAsRead();
...

// To listen for an update from all the other channel members' client apps, implement the 'onReadReceiptUpdated()' with things to do when notified.  
var handler = new sb.ChannelHandler();
handler.onReadReceiptUpdated = function(groupChannel) {
    if (currentGroupChannel.url === groupChannel.url) { 
        ...
        
        for (var message in messages) { 
            var unreadCount = groupChannel.getReadReceipt(message);
            if (unreadCount <= 0) {
                // All members have read the message.
            } else {
                // Some of members haven't read the message.
            }
        }
    }
};

sb.addChannelHandler(UNIQUE_HANDLER_ID, handler);

Retrieve the last message of a channel

You can view the last message of a group channel.

Light Color Skin
Copy
groupChannel.lastMessage;

Retrieve number of unread messages in a channel

You can retrieve the total number of the current user's unread messages in a group channel.

Light Color Skin
Copy
groupChannel.unreadMessageCount;

Retrieve number of unread messages in all channels

You can retrieve the total number of the current user's unread messages in all joined group channels.

Light Color Skin
Copy
sb.getTotalUnreadMessageCount(function(count, error) {
    if (error) {
        return;
    }
    
    console.log(count);
});

Retrieve number of channels with unread messages

You can retrieve the total number of the current user's joined group channels which one or more unread messages.

Light Color Skin
Copy
sb.getTotalUnreadChannelCount(function(count, error) {
    if (error) {
        return;
    }
    
    console.log(count);
});

Send an admin message

If you are using the Custom Plan, you can send admin messages to a group channel using the SendBird Dashboard or the Platform API. To send an admin message through your dashboard, go to the Moderation > Group Channels panel, select a group channel, find the message box below, click the Admin Message tab, and then write your message in the box. An admin message is limited to 1,000 characters.

Unlike other types of messages, a push notification for an admin message is not available by default. If you want assistance on this, contact our sales team.

Note: For clients using the Free Plan, a suggesting message to upgrade to the Custom Plan will be returned when attempting to send an admin message using the Platform API.


Add extra data to a message

You have the option to create further actions in a channel by using extra data in a message. You can add one or more key-values items to a message which you can save, update, or remove, when necessary. Based on those items, you can design and implement several different actions such as measuring user engagement within a chosen time limit through polls or counting how many times a message has been copied by members.

Note: For the quality of performance, every SendBird application has its own limits to how many key-values items you can add to a single message, as well as the maximum number of values an item can have. If you would like more information on these limits, contact our engineering team.

Light Color Skin
Copy
// When a message has been successfully sent to a channel, create items with keys.
groupChannel.createMessageMetaArrayKeys(MESSAGE, ['referees', 'games'], function (message, error) {
    if (error) {
        return;
    }
});

// Add values to specific items by their keys.
var valuesToAdd = {
    'referees': ['John', 'Brandon', 'Harry', 'Jay'],
    'games': ['soccer', 'baseball', 'basketball']
};

groupChannel.addMessageMetaArrayValues(MESSAGE, valuesToAdd, function (message, error) {
    if (error) {
        return;
    }
});

// Remove existing values of specific items by their keys.
var valuesToRemove = {
    'referees': ['Brandon', 'Jay']
};

groupChannel.removeMessageMetaArrayValues(MESSAGE, valuesToRemove, function (message, error) {
    if (error) {
        return;
    }
});

// Delete items by their keys.
groupChannel.deleteMessageMetaArrayKeys(MESSAGE, ['referees', 'games'], function (message, error) {
    if (error) {
        return;
    }
});

To get the key-values items of a message, read the message.metaArrays.


Categorize channels by custom type

When creating a channel, you can additionally specify a custom channel type for further channel grouping. This custom type takes on the form of a String, and can be useful in searching or filtering channels.

Note: The DATA and CUSTOM_TYPE are both String fields that allow you to append information to your channels. As mentioned above, a common use case for the CUSTOM_TYPE is to contain information for channel grouping (for example, categorizing into School and Work channels). However, both these fields can be flexibly utilized.

Light Color Skin
Copy
var params = new sb.GroupChannelParams();
params.addUserIds(['James', 'Chris']);
params.name = NAME;
params.customType = CUSTOM_TYPE;
...

sb.GroupChannel.createChannel(params, function(groupChannel, error) {
    if (error) {
        return;
    }
    
    console.log(groupChannel);
});

To get a channel's custom type, read the groupChannel.customType.


Categorize messages by custom type

When sending a message, you can additionally specify a custom message type for further message grouping. This custom type takes on the form of a String, and can be useful in searching or filtering messages.

Note: The DATA and CUSTOM_TYPE are both String fields that allow you to append information to your messages. As mentioned above, a common use case for the CUSTOM_TYPE is to contain information for message grouping (for example, categorizing into Notes and Contacts messages). However, both these fields can be flexibly utilized.

To embed a custom type into a message, set a value of the type to a UserMessageParams or FileMessageParams object with other values, and then pass the object as a parameter to the sendUserMessage() or sendFileMessage() methods.

Light Color Skin
Copy
const params = new sb.UserMessageParams();
params.message = TEXT_MESSAGE;
params.customType = CUSTOM_TYPE;
...

groupChannel.sendUserMessage(params, function(userMessage, error) {
    if (error) {
        return;
    }

    console.log(message);
});

To get a message's custom type, read the userMessage.customType.


Search channels by name, URL, or other filters

You can search for specific group channels by adding keywords to a MyGroupChannelListQuery instance. There are two types of keywords: a Name and a URL. The code sample below shows the query instance which returns a list of the current user's group channels that partially match the specified Name keyword in the names of the channels.

Light Color Skin
Copy
var myChannelListQuery = sb.GroupChannel.createMyGroupChannelListQuery();
myChannelListQuery.includeEmpty = true;
myChannelListQuery.channelNameContainsFilter = 'SendBird';

myChannelListQuery.next(function(groupChannels, error) {
    if (error) {
        return;
    }
        
    // A list of group channels that have 'SendBird' in their names is returned.
    console.log(groupChannels);
});

The following shows the query instance which returns a list of the current user's group channels that partially match the specified URL keywords in the URLs of the channels.

Light Color Skin
Copy
var myChannelListQuery = sb.GroupChannel.createMyGroupChannelListQuery();
myChannelListQuery.includeEmpty = true;
myChannelListQuery.channelUrlsFilter = ['seminar', 'lecture'];

myChannelListQuery.next(function(groupChannels, error) {
    if (error) {
        return;
    }

    // A list of group channels that have 'seminar' or 'lecture' in their URLs is returned.
    console.log(groupChannels);
});

The following table shows all the supported filters for GroupChannelListQuery to search for group channels you want to retrieve. You can use any filters in a similar way with the sample code above.

NameFilters...

CustomTypesFilter

Group channels with the specified one or more custom types.

CustomTypeStartsWithFilter

Group channels with the custom type which starts with the specified value.

ChannelNameContainsFilter

Group channels that contain the specified value in their names.

ChannelUrlsFilter

Group channels with the specified one or more channel URLs.

SuperChannelFilter

Either super or nonsuper group channels.

PublicChannelFilter

Either public or private group channels.

UnreadChannelFilter

Group channels with one or more unread messages.

HiddenChannelFilter

Group channels with the specified state and operating behavior.

MemberStateFilter

Group channels based on whether or not the user has accepted an invitation, or whether or not the user was invited by a friend.

UserIdsExactFilter

Group channels where the members with the specified one or more user IDs are exactly in.

UserIdsIncludeFilter

Group channels that include one or more members with the specified user IDs.

NicknameContainsFilter

Group channels with members whos nicknames contain the specified value.

MetaDataOrderKeyFilter

Group channels with metadata containing an item with the specified value as its key. This filter is effective only when the metadata are sorted in the alphabetical order.


Generate thumbnails of a file message

When sending an image file, you can determine whether to create thumbnails of the image to fetch and render into your UI. You can specify up to 3 different dimensions to generate thumbnail images in for supporting various display densities.

Note: Supported file types are files whose media type is image/* or video/*. The SDK doesn't support creating thumbnails when sending a file message via a file URL.

The sendFileMessage() method requires that you pass a FileMessageParams object as a parameter, containing an array of items which each specify the maximum values of width and height of a thumbnail image. The callback function subsequently returns a list of Thumbnail items that each contain the URL of the generated thumbnail image file.

Light Color Skin
Copy
const params = new sb.FileMessageParams();
...
params.file = FILE;
params.fileName = FILE_NAME;
params.fileSize = FILE_SIZE;
params.mimeType = MIME_TYPE;
params.thumbnailSizes = [{maxWidth: 100, maxHeight: 100}, {maxWidth: 200, maxHeight: 200}]; // Add the maximum sizes of thumbnail images (allowed number of thumbnail images: 3).

groupChannel.sendFileMessage(params, function(fileMessage, error) {
    if (error) {
        return;
    }
    
    var thumbnailFirst = fileMessage.thumbnails[0];
    var thumbnailSecond = fileMessage.thumbnails[1];

    var maxHeightFirst = thumbnailFirst.maxHeight;      // 100
    var maxHeightSecond = thumbnailSecond.maxHeight;    // 200

    var urlFirst = thumbnailFirst.url;      // URL of first thumbnail file.
    var urlSecond = thumbnailSecond.url;    // URL of second thumbnail file.
});

A thumbnail image is generated evenly to fit within the bounds of provided (maxWidth, maxHeight). Note that if the original image is smaller than the specified dimensions, the thumbnail isn't resized. The url returns the location of the generated thumbnail file within SendBird server.

This is one of SendBird's premium features, contact our sales team for further assistance.


Track file upload progress using a handler

You can track the file upload progress by passing progressHandler as a parameter when calling sendFileMessage().

Light Color Skin
Copy
const params = new sb.FileMessageParams();
params.file = FILE;
params.fileName = FILE_NAME;
params.customType = CUSTOM_TYPE;
params.data = DATA;

var sentFileMessage = groupChannel.sendFileMessage(params, 
    function(event) {   // Check progress of file upload here.
        console.log(parseInt(Math.floor(e.loaded / e.total * 100)) + '%');
    },
    function(fileMessage, error) {  // callback
        // Do something with the sent file message.
        console.log(fileMessage, error);
    }
);

Cancel an in-progress file upload

Using the cancelUploadingFileMessage() method, you can cancel an in-progress file upload while it is not completed yet. If the function operates successfully, true is returned.

Note: If you attempt to cancel the uploading after it is already completed, or canceled, or returned an error, the function returns false.

Light Color Skin
Copy
const params = new sb.FileMessageParams();
params.file = FILE;
params.fileName = FILE_NAME;
params.customType = CUSTOM_TYPE;
params.data = DATA;

var sentFileMessage = groupChannel.sendFileMessage(params, function(fileMessage, error) { 
    ...
    console.log(fileMessage, error);
});

// Cancel uploading a file in the file message.
var cancelResult = groupChannel.cancelUploadingFileMessage(sentFileMessage.reqId);
console.log(cancelResult);

Share an encrypted file with other members

This file encryption feature prevents users without access from opening and reading encrypted files that have been shared within a group of users. When this feature is turned on, all types of sent files and thumbnail images will be first uploaded to SendBird server, and then encrypted by AES256.

In a group channel, encrypted files and thumbnail images will be decrypted and accessed securely only by the members. Anyone outside of the channel and application will not have access to those files and thumbnail images. The following explains how this data security works and what to do at the SDK level to apply it to your client apps.

The SendBird system enables secure encryption and decryption of files by generating and distributing an opaque and unique encryption key for each user. An encryption key is managed internally by the system, and is valid for 3 days. It is generated every time the user logs in to SendBird server through the SDK, which then gets delivered to the SDK from the server.

When the SDK requests an encrypted file by its URL, the parameter auth should be added to the URL to access the file, which is specified with an encryption key of the user such as ?auth=RW5jb2RlIHaXMgdGV4eA==. With the specified key in the auth, SendBird server first decrypts the file, then checks if the user is a member of the group channel, and finally, allows the user to access and open the file in the channel.

This can be easily done by retrieving the fileMessage.url property, which returns the unique file URL containing the parameter auth with an encryption key of the current user.

This is one of SendBird's premium features, contact our sales team for further assistance. This feature will also require customized implementation efforts from your side.


Spam flood protection

This feature allows you to customize the number of messages a member can send in a group channel per second. By doing so, all excess messages will be deleted and only the number of messages allowed to be sent per member per second will be delivered. This feature protects your app from some members spamming others in the channel with the same messages.

Note: Our default system setting is 5 messages per second. This limit can be manually adjusted only by our side. You can contact our engineering team about this setting. This is one of SendBird's premium features, contact our sales team for further assistance.


Message auto-translation

It is possible for text messages to be sent in different languages through the SendBird's auto-translation feature. When sending a text message, set an array of language codes to a UserMessageParams object and then pass the object as a parameter to the sendUserMessage() method to request translated messages in the corresponding languages.

Note: This message auto-translation feature is powered by Google Cloud Translation API recognition engine and Microsoft Translator engine. It is by default that Google's Cloud Translation API recognition engine is used for message auto-translation, whereas if your SendBird application has been created before June 26, 2019, Microsoft Translator engine is used.

Light Color Skin
Copy
const params = new sb.UserMessageParams();
...
params.translationTargetLanguages = ['es', 'ko'];   // Spanish and Korean

groupChannel.sendUserMessage(params, function(userMessage, error) {
    if (error) {
        return;
    }

    // onSent
});

You can retrieve translations of a text message using the userMessage.translations property which has a Map object containing the language codes and translations.

Note: The two translation engines support a wide variety of languages, and you can see their language code tables in the Miscellaneous > Language support section.

Light Color Skin
Copy
var ChannelHandler = new sb.ChannelHandler();

ChannelHandler.onMessageReceived = function(channel, message) {
    var esTranslatedMessage = message.translations['es'];   // Spanish
    ...
    // Display translation in UI.
};

sb.addChannelHandler(UNIQUE_HANDLER_ID, ChannelHandler);

Using the groupChannel.translateUserMessage() method, you can also translate an already sent text message into other languages for your specific needs.

Light Color Skin
Copy
const targetLanguages = ['es', 'de'];   // Spanish and German

// The USER_MESSAGE below indicates a UserMessage object which represents an already sent text message.
groupChannel.translateUserMessage(USER_MESSAGE, targetLanguages, function(userMessage, error) {
    if (error) {
        return;
    }

    var esTranslatedMessage = userMessage.translations['es'];   // Spanish
    var deTranslatedMessage = userMessage.translations['de'];   // German 
    ...
    // Display translations in UI.
});

Note: This is one of SendBird's premium features, contact our sales team for further assistance.