iOS
Open Channel Advanced

Open Channel: Advanced

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


Send an admin message

If you are using the Custom Plan, you can send an admin message to an open channel using the SendBird Dashboard or the Platform API. To send the admin message through your dashboard, on the Application > Open channels panel, select an open channel, find a 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.

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 participants.

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.

Objective-C
Swift
Light Color Skin
Copy
// When a message has been successfully sent to a channel, create items with keys.
[openChannel createMessageMetaArrayKeysWithMessage:MESSAGE keys:@[@"referees", @"games"] completionHandler:^(SBDBaseMessage * _Nullable message, SBDError * _Nullable error) {
    if (error != nil) { // Error.
        return;
    }
}];

// Adding values to specific items by their keys.
NSDictionary *valuesToAdd = @{
    @"referees": @[@"John", @"Brandon", @"Harry", @"Jay"],
    @"games": @[@"soccer", @"baseball", @"basketball"],
};

[openChannel addMessageMetaArrayValuesWithMessage:MESSAGE keyValues:valuesToAdd completionHandler:^(SBDBaseMessage * _Nullable message, SBDError * _Nullable error) {
    if (error != nil) { // Error.
        return;
    }
}];

// Removing existing values of specific items by their keys.
NSDictionary *valuesToRemove = @{
    @"referees": @[@"Brandon", @"Jay"],
};

[openChannel removeMessageMetaArrayValuesWithMessage:MESSAGE keyValues:valuesToRemove completionHandler:^(SBDBaseMessage * _Nullable message, SBDError * _Nullable error) {
    if (error != nil) { // Error.
        return;
    }
}];

// Deleting items by their keys.
[openChannel deleteMessageMetaArrayKeysWithMessage:MESSAGE keys:@[@"referees", @"games"] completionHandler:^(SBDBaseMessage * _Nullable message, SBDError * _Nullable error) {
    if (error != nil) { // Error.
        return;
    }
}];
Light Color Skin
Copy
// When a message has been successfully sent to a channel, creating a map of keys.
openChannel.createMessageMetaArrayKeys(withMessage: MESSAGE, keys: ["referees", "games"], completionHandler: { (message, error) in
    guard error == nil else {   // Error. 
        return
    }
})

// Adding values to specific items by their keys.
let valuesToAdd = [
    "referees": ["John", "Brandon", "Harry", "Jay"],
    "games": ["soccer", "baseball", "basketball"]
]

openChannel.addMessageMetaArrayValues(withMessage: MESSAGE, keyValues: valuesToAdd, completionHandler: { (message, error) in
    guard error == nil else {   // Error. 
        return
    }
})

// Removing existing values of specific items by their keys.
let valuesToRemove = [
    "referees": ["Brandon", "Jay"]
]

openChannel.removeMessageMetaArrayValues(with: MESSAGE, keyValues: valuesToRemove, completionHandler: { (message, error) in
    guard error == nil else {   // Error. 
        return
    }
})

// Deleting items by their keys.
openChannel.deleteMessageMetaArrayKeys(withMessage: MESSAGE, keys: ["referees", "games"], completionHandler: { (message, error) in
    guard error == nil else {   // Error. 
        return
    }
})

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


Categorize channels by custom type

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

Note: The DATA and CUSTOM_TYPE are both NSString fields that allow you to append additional 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 School and Work channels). However, both these fields can be flexibly utilized.

Objective-C
Swift
Light Color Skin
Copy
[SBDOpenChannel createChannelWithName:NAME coverUrl:COVER_URL data:nil operatorUsers:OPERATOR_USERS customType:CUSTOM_TYPE progressHandler:nil completionHandler:^(SBDOpenChannel * _Nullable openChannel, SBDError * _Nullable error) {
    if (error != nil) { // Error.
        return;
    }
}];
Light Color Skin
Copy
SBDOpenChannel.createChannel(withName: NAME, coverUrl: COVER_URL, data: DATA, operatorUsers: OPERATOR_USERS, customType: CUSTOM_TYPE, progressHandler: nil) { (openChannel, error) in
    guard error == nil else {   // Error. 
        return
    }
}

To get a channel's custom type, read the openChannel.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 NSString, and can be useful in searching or filtering messages.

Note: The DATA and CUSTOM_TYPE are both NSString fields that allow you to append additional 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 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 SBDUserMessageParams or SBDFileMessageParams object with other values, and pass the object as a parameter to the sendUserMessageWithParams:completionHandler: or sendFileMessageWithParams:completionHandler: method.

Objective-C
Swift
Light Color Skin
Copy
SBDUserMessageParams *params = [[SBDUserMessageParams alloc] init];
[params setMessage:MESSAGE];
[params setCustomType:CUSTOM_TYPE];
...

[openChannel sendUserMessageWithParams:params completionHandler:^(SBDUserMessage * _Nullable userMessage, SBDError * _Nullable error) {
    if (error != nil) { // Error.
        return;
    }
}];
Light Color Skin
Copy
var params = SBDUserMessageParams()
params.message = MESSAGE
params.customType = CUSTOM_TYPE
...

openChannel.sendUserMessage(with: params, completionHandler: { (userMessage, error) in
    guard error == nil else {   // Error.
        return
    }
})

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


Search channels by name, URL, or custom type

You can search for specific open channels by adding keywords to a SBDOpenChannelListQuery 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 open channels that partially match the specified Name keyword in the names of the channels.

Objective-C
Swift
Light Color Skin
Copy
SBDOpenChannelListQuery *query = [SBDOpenChannel createOpenChannelListQuery];
[query setChannelNameFilter:@"SendBird"];
[query loadNextPageWithCompletionHandler:^(NSArray<SBDOpenChannel *> * _Nullable openChannels, SBDError * _Nullable error) {
    if (error != nil) { // Error.
        return;
    }

    // A list of open channels that partially match "SendBird" in their names is returned.
}];
Light Color Skin
Copy
let query = SBDOpenChannel.createOpenChannelListQuery()
query?.channelNameFilter = "SendBird"
query?.loadNextPage(completionHandler: { (openChannels, error) in
    guard error == nil else {   // Error.
            return
    }

    // A list of open channels that partially match "SendBird" in their names is returned.
})

The following shows the query instance which returns a list of open channels that partially match the specified URL keyword in the URLs of the channels.

Objective-C
Swift
Light Color Skin
Copy
SBDOpenChannelListQuery *query = [SBDOpenChannel createOpenChannelListQuery];
[query setChannelUrlFilter:@"seminar"];
[query loadNextPageWithCompletionHandler:^(NSArray<SBDOpenChannel *> * _Nullable openChannels, SBDError * _Nullable error) {
    if (error != nil) { // Error.
        return;
    }

    // A list of open channels that partially match "seminar" in their names is returned.
}];
Light Color Skin
Copy
let query = SBDOpenChannel.createOpenChannelListQuery()
query?.channelUrlFilter = "seminar"
query?.loadNextPage(completionHandler: { (openChannels, error) in
    guard error == nil else {   // Error.
        return
    }

    // A list of open channels that partially match "seminar" in their names is returned.
})

Using the setCustomTypeFilter: like the following, you can also search for open channels with a specific custom type.

Objective-C
Swift
Light Color Skin
Copy
SBDOpenChannelListQuery *query = [SBDOpenChannel createOpenChannelListQuery];
[query setCustomTypeFilter:@"movie"];
[query loadNextPageWithCompletionHandler:^(NSArray<SBDOpenChannel *> * _Nullable openChannels, SBDError * _Nullable error) {
    if (error != nil) {     // Error.
        return;
    }

    // A list of open channels with a "moive" custom type is returned.
}];
Light Color Skin
Copy
let query = SBDOpenChannel.createOpenChannelListQuery()
query?.customTypeFilter = "movie"
query?.loadNextPage(completionHandler: { (openChannels, error) in
    guard error == nil else {       // Error.
        return
    }

    // A list of open channels with a "moive" custom type is returned.
})

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 with a file URL.

The sendFileMessageWithParams:completionHandler: method requires that you pass a SBDFileMessageParams object as a parameter, containing a NSArray of SBDThumbnailSize objects which each specify the maximum values of width and height of a thumbnail image with the SBDThumbnailSize's makeWithMaxCGSize: or makeWithMaxWidth:maxHeight: constructors. The completionHandler: callback subsequently returns a NSArray of SBDThumbnail objects that each contain the URL of the generated thumbnail image file.

Objective-C
Swift
Light Color Skin
Copy
NSMutableArray<SBDThumbnailSize *> *thumbnailSizes = [[NSMutableArray alloc] init];

// Creating and adding a SBDThumbnailSize object (allowed number of thumbnail images: 3).
[thumbnailSizes addObject:[SBDThumbnailSize makeWithMaxCGSize:CGSizeMake(100.0, 100.0)]];
[thumbnailSizes addObject:[SBDThumbnailSize makeWithMaxWidth:200.0 maxHeight:200.0]];

SBDFileMessageParams *params = [[SBDFileMessageParams alloc] init];
...
[params setFile:FILE]; 
[params setFileName:FILE_NAME];
[params setFileSize:FILE_SIZE];
[params setMimeType:MIME_TYPE];
[params setThumbnailSizes:thumbnailSizes];  // Set a SBDThumbnailSize object to a SBDFileMessageParams object.

[openChannel sendFileMessageWithParams:params completionHandler:^(SBDFileMessage * _Nonnull fileMessage, SBDError * _Nullable error) {
    if (error != nil) { // Error.
        return;
    }
    
    SBDThumbnail *first = fileMessage.thumbnails[0];
    SBDThumbnail *second = fileMessage.thumbnails[1];

    CGSize maxSizeFirst = first.maxSize;    // 100
    CGSize maxSizeSecond = second.maxSize;  // 200

    NSString *urlFirst = first.url;
    NSString *urlSecond = second.url;
}];
Light Color Skin
Copy
var thumbnailSizes = [SBDThumbnailSize]()

// Creating and adding a SBDThumbnailSize object (allowed number of thumbnail images: 3).
thumbnailSizes.append(SBDThumbnailSize.make(withMaxCGSize: CGSize(width: 100.0, height: 100.0))!)
thumbnailSizes.append(SBDThumbnailSize.make(withMaxWidth: 200.0, maxHeight: 200.0)!)

var params = SBDFileMessageParams()
...
params.file = FILE 
params.fileName = FILE_NAME
params.fileSize = FILE_SIZE
params.mimeType = MIME_TYPE
params.thumbnailSizes = thumbnailSizes  // Set a SBDThumbnailSize object to a SBDFileMessageParams object.

openChannel.sendFileMessage(with: params, completionHandler: { (fileMessage, error) in
    guard error == nil else {   // Error.
        return
    }

    let first = fileMessage?.thumbnails?[0]
    let second = fileMessage?.thumbnails?[1]

    let maxSizeFirst = first?.maxSize   // 100
    let maxSizeSecond = second?.maxSize // 200

    let urlFirst = first?.url
    let urlSecond = second?.url
})

A thumbnail image is generated evenly to fit within the bounds of (maxWidth, maxHeight), which are provided through the constructor. 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.


Share an encrypted file with other participants

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 an open channel, encrypted files and thumbnail images will be decrypted and accessed securely only by the participants. 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 participating in the open 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 participant can send in an open channel per second. By doing so, all excess messages from a participant will be deleted and only the number of messages allowed to be sent per participant per second will be delivered. This feature protects your app from some participants 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 from our side. You can contact our engineering team about this setting. This is one of SendBird's premium features, first contact our sales team for further assistance.


Smart throttling

You can use this feature to customize the number of messages displayed in an open channel per second. By doing so, you can adjust the pace of the conversation in a chat so that the participants can read the messages more clearly. In fact, each participant's channel will display the messages they have sent and those that other participants have sent up to this limit in chronological order.

Note: Our default system setting is 5 messages per second. This limit can be manually adjusted only from our side. You can contact our engineering team on this setting. This is one of SendBird's premium features, first 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 a NSArray of language codes to a SBDUserMessageParams object and then pass the object as a parameter to the sendUserMessageWithParams:completionHandler: 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.

Objective-C
Swift
Light Color Skin
Copy
SBDUserMessageParams *params = [[SBDUserMessageParams alloc] init];
...
[params setTargetLanguages:@[@"es", @"ko"]];    // Spanish and Korean       

[openChannel sendUserMessageWithParams:params completionHandler:^(SBDUserMessage * _Nonnull userMessage, SBDError * _Nullable error) {
    if (error != nil) { // Error.
        return;
    }
}];
Light Color Skin
Copy
var params = SBDUserMessageParams()
...
params.targetLanguages = ["es", "ko"]   // Spanish and Korean

openChannel.sendUserMessage(with: params, completionHandler: { (userMessage, error) in
    guard error == nil else {   // Error.
        return
    }
})

You can retrieve translations of a text message using the userMessage.translations property which has a NSArray 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.

Objective-C
Swift
Light Color Skin
Copy
- (void)channel:(SBDBaseChannel * _Nonnull)sender didReceiveMessage:(SBDBaseMessage * _Nonnull)message {
    NSArray *translations = ((SBDUserMessage *)message).translations;
    NSString *esTranslatedMessage = translations[@"es"];    // Spanish
    ...
    // Display translation in UI.
}
Light Color Skin
Copy
func channel(_ sender: SBDBaseChannel, didReceive message: SBDBaseMessage) {
    let translations = (message as! SBDUserMessage).translations
    let esTranslatedMessage = translations["es"]    // Spanish
    ...
    // Display translation in UI.
}

Using the translateUserMessage:targetLanguages:completionHandler: method, you can also translate an already sent text message into other languages for your specific needs.

Objective-C
Swift
Light Color Skin
Copy
NSArray<NSString *> *targetLanguages = @[@"es", @"de"];         // Spanish and German

// The USER_MESSAGE below indicates a SBDUserMessage object which represents an already sent text message.
[openChannel translateUserMessage:USER_MESSAGE targetLanguages:targetLanguages completionHandler:^(SBDUserMessage * _Nullable userMessage, SBDError * _Nullable error) {
    if (error != nil) { // Error.
        return;
    }

    NSArray *translations = ((SBDUserMessage *)userMessage).translations;
    NSString *esTranslatedMessage = translations[@"es"];    // Spanish
    NSString *deTranslatedMessage = translations[@"de"];    // German
    ...
    // Display translations in UI.
}];
Light Color Skin
Copy
let targetLanguages = ["es", "de"]

// The USER_MESSAGE below indicates a SBDUserMessage object which represents an already sent text message.
openChannel.translateUserMessage(USER_MESSAGE, targetLanguages: targetLanguages, completionHandler: { (userMessage, error) in
    guard error == nil else {   // Error.
        return
    }

    let translations = (userMessage as! SBDUserMessage).translations
    let esTranslatedMessage = translations["es"]
    let deTranslatedMessage = translations["de"]
    ...
    // Display translations in UI.
})

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