Manage the user-channel membership relationship
Requires App Context
To set up and manage channel membership, you must enable App Context for your app's keyset in the Admin Portal.
When a user joins a channel or gets invited to it, a membership relationship between that user and the channel is created (Membership entity). The membership ends when this user leaves the channel.
Read on to learn how to check and update user-channel membership.
Get members
getMembers() returns the list of all channel members.
Method signature
This method takes the following parameters:
1channel.getMembers(
2    limit: Int?,
3    page: PNPage?,
4    filter: String?,
5    sort: Collection<PNSortKey<PNMemberKey>> = listOf(),
6): PNFuture<MembersResponse>
Input
| Parameter | Description | 
|---|---|
| limitType:  IntDefault: 100 | Number of objects to return in response. The default (and maximum) value is 100. | 
| pageType:  PNPageDefault: n/a | Object used for pagination to define which previous or next result page you want to fetch. | 
| filterType:  StringDefault: n/a | Expression used to filter the results. Returns only these members whose properties satisfy the given expression. The filter language is defined here. | 
| sortType:  Collection<PNSortKey<PNMemberKey>>Default: listOf() | A collection to specify the sort order. Available options are id,name, andupdated. Useascordescto specify the sorting direction, or specifynullto take the default sorting direction (ascending). For example:{name: "asc"}.  Unless specified otherwise, the items are sorted by the last updated date. Defaults to an empty list. | 
Output
| Type | Description | 
|---|---|
| PNFuture<MembersResponse> | PNFuturecontaining a set of channel members with membershipstatus,totalnumber of members, andnextandprevpages. | 
Sample code
List all members of the support channel on the premium support plan.
1// reference the "channel" object
2chat.getChannel("support").async { result ->
3    result.onSuccess { channel ->
4        // get the list of all members with the premium support plan
5        channel.getMembers(
6            filter = "custom.support_plan == 'premium'"
7        ).async { membersResult ->
8            membersResult.onSuccess { membersResponse ->
9                val membersList = membersResponse.members
10                // handle success: membersList contains the list of members
11            }.onFailure { error ->
12                // handle failure
13            }
14        }
15    }.onFailure { error ->
Get membership
getMemberships() returns the list of all channel memberships of a given user.
To get a list of all existing channels, use the getChannels() method.
Method signature
This method takes the following parameters:
1user.getMemberships(
2    limit: Int?,
3    page: PNPage?,
4    filter: String?,
5    sort: Collection<PNSortKey<PNMembershipKey>> = listOf(),
6): PNFuture<MembershipsResponse>
Input
| Parameter | Description | 
|---|---|
| limitType:  IntDefault: 100 | Number of objects to return in response. The default (and maximum) value is 100. | 
| pageType:  PNPageDefault: n/a | Object used for pagination to define which previous or next result page you want to fetch. | 
| filterType:  StringDefault: n/a | Expression used to filter the results. Returns only these members whose properties satisfy the given expression. The filter language is defined here. | 
| sortType:  Collection<PNSortKey<PNMembershipKey>>Default: listOf() | A collection to specify the sort order. Available options are id,name, andupdated. Useascordescto specify the sorting direction, or specifynullto take the default sorting direction (ascending). For example:{name: "asc"}.  Unless specified otherwise, the items are sorted by the last updated date. Defaults to an empty list. | 
Output
| Type | Description | 
|---|---|
| PNFuture<MembershipsResponse> | PNFuturecontaining a set of memberships, theirstatusandtotalnumber, andnextandprevpages. | 
Sample code
Find out which channels the support_agent_15 user is a member of.
1// reference the "support_agent_15" user
2chat.getUser("support_agent_15").async { result ->
3    result.onSuccess { user ->
4        // get the list of all user memberships
5        user.getMemberships().async { membershipsResult ->
6            membershipsResult.onSuccess { membershipsResponse ->
7                val membershipsList = membershipsResponse.memberships
8                // handle success: membershipsList contains the list of memberships
9            }.onFailure { error ->
10                // handle failure
11            }
12        }
13    }.onFailure { error ->
14        // handle failure to fetch user
15    }
Get updates
You can receive updates when specific user-channel Membership object(s) are edited (status, type, custom data) using the following methods:
- streamUpdates()checks updates on a single- Membershipobject and it's tied to an instance of the- Membershipclass.
- streamUpdatesOn()checks updates on a list of- Membershipobjects and it's tied to the- Membershipclass.
Membership changes
These methods notify you about field changes (e.g., metadata, status) for existing memberships, not new membership additions or removals.
Both methods accept a callback function as an argument. The Chat SDK invokes this callback whenever someone adds, changes, or removes membership data.
Underneath, these methods subscribe the current user to a channel and add an objects event listener to receive all objects events of type membership. These methods also return the unsubscribe function you can invoke to stop receiving objects events and unsubscribe from the channel.
Method signature
These methods take the following parameters:
- 
streamUpdates()1membership.streamUpdates(callback: (membership: Membership?) -> Unit): AutoCloseable
- 
streamUpdatesOn()1class Membership {
 2 companion object {
 3 fun streamUpdatesOn(
 4 memberships: Collection<Membership>,
 5 callback: (memberships: Collection<Membership>) -> Unit
 6 ): AutoCloseable
 7 }
 8}
Input
| Parameter | Required in streamUpdates() | Required in streamUpdatesOn() | Description | 
|---|---|---|---|
| membershipsType:  Collection<Membership>Default: n/a | No | Yes | A collection of Membershipobjects for which you want to get updates. | 
| callbackType:  (membership: Membership?) -> UnitDefault: n/a | Yes | No | Function that takes a single Membershipobject. It defines the custom behavior to be executed when detecting membership changes. | 
| callbackType:  (memberships: Collection<Membership>) -> UnitDefault: n/a | No | Yes | Function that takes a set of Membershipobjects. It defines the custom behavior to be executed when detecting membership changes. | 
Output
| Type | Description | 
|---|---|
| AutoCloseable | Interface that lets you stop receiving membership-related updates ( objectsevents) by invoking theclose()method. | 
Sample code
Get updates on the first user membership.
- 
streamUpdates()
 show all 20 lines1chat.currentUser.getMemberships().async { result ->
 2 result.onSuccess { membershipsResponse ->
 3 // handle success
 4 val firstMembership = membershipsResponse.memberships.firstOrNull()
 5 firstMembership?.let {
 6 val autoCloseable = it.streamUpdates { updatedMembership ->
 7 if (updatedMembership != null) {
 8 println("Updated membership: $updatedMembership")
 9 } else {
 10 println("Membership update failed or membership doesn't exist.")
 11 }
 12 }
 13 } ?: run {
 14 println("No memberships found.")
 15 }
Get updates on the first page of user memberships.
- 
streamUpdatesOn()
 show all 19 lines1chat.currentUser.getMemberships().async { result ->
 2 result.onSuccess { membershipsResponse ->
 3 // handle success
 4 val firstPageMemberships = membershipsResponse.memberships.take(10) // assuming one page has 10 memberships
 5
 6 val autoCloseable = Membership.streamUpdatesOn(memberships = firstPageMemberships) { updatedMemberships ->
 7 if (updatedMemberships.isNotEmpty()) {
 8 updatedMemberships.forEach { updatedMembership ->
 9 println("Updated membership: $updatedMembership")
 10 }
 11 } else {
 12 println("No membership updates available.")
 13 }
 14 }
 15 }.onFailure { exception ->
Other examples
Stop listening to updates on the first user membership.
- 
streamUpdates()
 show all 26 lines1chat.currentUser.getMemberships().async { result ->
 2 result.onSuccess { membershipsResponse ->
 3 // handle success
 4 val firstMembership = membershipsResponse.memberships.firstOrNull()
 5 firstMembership?.let {
 6 val autoCloseable = it.streamUpdates { updatedMembership ->
 7 if (updatedMembership != null) {
 8 println("Updated membership: $updatedMembership")
 9 } else {
 10 println("Membership update failed or membership doesn't exist.")
 11 }
 12 }
 13
 14 // logic to stop listening to updates can be placed here
 15 // for example, close `autoCloseable` after some condition or delay
Stop listening to updates on the first page of user memberships.
- 
streamUpdatesOn()
 show all 25 lines1chat.currentUser.getMemberships().async { result ->
 2 result.onSuccess { membershipsResponse ->
 3 // handle success
 4 val firstPageMemberships = membershipsResponse.memberships.take(10) // assuming one page has 10 memberships
 5
 6 val autoCloseable = Membership.streamUpdatesOn(memberships = firstPageMemberships) { updatedMemberships ->
 7 if (updatedMemberships.isNotEmpty()) {
 8 updatedMemberships.forEach { updatedMembership ->
 9 println("Updated membership: $updatedMembership")
 10 }
 11 } else {
 12 println("No membership updates available.")
 13 }
 14 }
 15
Update
update() updates the channel membership information for a given user.
Method signature
This method takes the following parameters:
1membership.update(custom: CustomObject): PNFuture<Membership>
Input
| Parameter | Description | 
|---|---|
| custom*Type:  ObjectCustomDefault: n/a | Any custom properties or metadata associated with the channel-user membership in the form of a JSON. Values must be scalar only; arrays or objects are not supported. App Context filtering language doesn’t support filtering by custom properties. | 
Output
| Type | Description | 
|---|---|
| PNFuture<Membership> | Returned (modified) object containing the membership data. | 
Sample code
Assign the premium-support role to support_agent_15 on the high-priority-incidents channel.
1// get the list of all user memberships and filter out the right channel
2user.getMemberships(filter = "channel.id == 'high-priority-incidents'").async {
3    it.onSuccess { membershipsResponse ->
4        membershipsResponse
5            .memberships
6            .firstOrNull()
7            // add custom metadata to the user membership
8            ?.update(mapOf("role" to "premium-support"))?.async { membership ->
9            // ...
10        }
11    }.onFailure {
12        // handle failure
13    }
14}