Moderate misbehaving users as a chat user
The Swift Chat SDK provides moderation options for chat users who want to hide messages from undesirable users on the client side.
The user IDs that a given chat user wants to hide messages from (mute them) are saved to a list. This mute list is soft-limited to 200 users and, by default, is only persisted for the duration of the user session.
You can decide to save and retrieve a local mute list during client initialization, effectively persisting the mute list beyond the scope of a single session, but then the hard 32KiB server data limit applies.
Mute list user limit
A persisted mute list can hold roughly up to 200 users (32KiB of data). If the size of the list exceeds that limit, the Swift Chat SDK throws an HTTP 413 error and the list won't be persisted. The users will still be muted for the duration of the session.
All events and messages originating from a muted user are still received by the client, but are ignored. The mute list affects the following means of message delivery:
channel.connect()channel.join()channel.getHistory()chat.listenForEvents()chat.getEventsHistory()
Requires App Context
To mute users, you must enable App Context for your app's keyset in the Admin Portal.
Mute users as a regular chat user
As a regular chat user, you can mute a specific user on all channels.
Method signature
- Async/await
- Closure
1func muteUser(userId: String) async throws
1func muteUser(
2 userId: String,
3 completion: ((Result<Void, Error>) -> Void)?
4)
Input
| Parameter | Description |
|---|---|
userId *Type: String | User ID of the user you want to mute. |
completionType: ((Result<Void, Error>) -> Void)? | Completion closure called with the result of the operation. |
Output
This method calls the completion closure with a Result<Void, Error> that succeeds when the data has been synced with the server. If syncMutedUsers is not enabled, the completion always succeeds.
Errors
If the size of the mute list exceeds 32KiB (roughly 200 users), you'll get the HTTP 413 (Request Entity Too Large) error.
Sample code
Sample code
The code samples in Swift Chat SDK focus on asynchronous code execution.
You can also write synchronous code as the parameters are shared between the async and sync methods but we don't provide usage examples of such.
- Async/await
- Closure
1import PubNubSDK
2import PubNubSwiftChatSDK
3
4let userToMute = "user_rks"
5
6Task {
7 do {
8 try await chat.mutedUsersManager.muteUser(userId: userToMute)
9 print("User muted successfully")
10 } catch {
11 print("Failed to mute user: \(error)")
12 }
13}
1import PubNubSDK
2import PubNubSwiftChatSDK
3
4let userToMute = "user_rks"
5
6chat.mutedUsersManager.muteUser(userId: userToMute) { result in
7 switch result {
8 case .success:
9 print("User muted successfully")
10 case .failure(let error):
11 print("Failed to mute user: \(error)")
12 }
13}
Unmute users as a regular chat user
You can unmute a specific user on all channels. This removes the user from the mute list, allowing the client to see all messages and events originating from the user again.
Method signature
- Async/await
- Closure
1func unmuteUser(userId: String) async throws
1func unmuteUser(
2 userId: String,
3 completion: ((Result<Void, Error>) -> Void)?
4)
Input
| Parameter | Description |
|---|---|
userId *Type: String | User ID of the user you want to unmute. |
completionType: ((Result<Void, Error>) -> Void)? | Completion closure called with the result of the operation. |
Output
This method calls the completion closure with a Result<Void, Error> that succeeds when the data has been synced with the server. If syncMutedUsers is not enabled, the completion always succeeds.
Sample code
Sample code
The code samples in Swift Chat SDK focus on asynchronous code execution.
You can also write synchronous code as the parameters are shared between the async and sync methods but we don't provide usage examples of such.
- Async/await
- Closure
1import PubNubSDK
2import PubNubSwiftChatSDK
3
4let userToUnmute = "user_rks"
5
6Task {
7 do {
8 try await chat.mutedUsersManager.unmuteUser(userId: userToUnmute)
9 print("User unmuted successfully")
10 } catch {
11 print("Failed to unmute user: \(error)")
12 }
13}
1import PubNubSDK
2import PubNubSwiftChatSDK
3
4let userToUnmute = "user_rks"
5
6chat.mutedUsersManager.unmuteUser(userId: userToUnmute) { result in
7 switch result {
8 case .success:
9 print("User unmuted successfully")
10 case .failure(let error):
11 print("Failed to unmute user: \(error)")
12 }
13}
Check muted users
You can check which users have been muted by inspecting the items in the mute list.
Method signature
1var mutedUsers: Set<String> { get }
Output
This property returns a Set<String> where each String is a user ID of a muted user.
Sample code
1for userId in chat.mutedUsersManager.mutedUsers {
2 print("Muted user: \(userId)")
3}
Persist the mute list
By default, the mute list is only persisted for the duration of the user session. You can save and retrieve the mute list during client initialization, effectively persisting the mute list by setting the syncMutedUsers parameter to true during client initialization.
Mute list and Access Manager
If you use Access Manager for user moderation within your chat app and syncMutedUsers is enabled, you must grant the Swift Chat SDK user the following permissions:
readpermission to thePN_PRV.$currentUserId.mute1channel.update,delete, andgetpermissions for thePN_PRV.$currentUserId.mute1user.
Make sure to change $currentUserId to the user ID of the chat user that will use the mute list functionality.
Client-side only
The Swift Chat SDK's mute functionality is client-side only. This means that muted users' messages are still delivered to the client but are filtered out by the SDK. For server-enforced restrictions, you would need to implement Access Manager rules through your backend systems.
Check restrictions
You can check if the chat administrator imposed any mute or ban restrictions for the following scenarios. Refer to the linked sections for more information.
- For a single user on a single channel
- For a single user on all channels
- For all users on a single channel
Sample code
Single user on a single channel
1 // reference the "chat" object and invoke the "getUser()" method
2 chat.getUser("support_agent_15").async { userResult ->
3 userResult.onSuccess { user ->
4 if (user != null) {
5 // get the "support" channel
6 chat.getChannel("support").async { channelResult ->
7 channelResult.onSuccess { channel ->
8 if (channel != null) {
9 // get the channel restrictions for the user
10 user.getChannelRestrictions(channel).async { restrictionResult ->
11 restrictionResult.onSuccess { restriction ->
12 // handle the restriction object
13 }.onFailure {
14 // handle failure
15 }
show all 30 linesAll users on a single channel
1// reference the "chat" object and invoke the "getChannel()" method
2chat.getChannel("support").async { result ->
3 result.onSuccess { channel ->
4 if (channel != null) {
5 // fetch the user restrictions for the channel
6 channel.getUsersRestrictions().async { restrictionsResult ->
7 restrictionsResult.onSuccess { getRestrictionsResponse ->
8 // process the returned restrictions
9 for (restriction in getRestrictionsResponse.restrictions) {
10 if (restriction.mute || restriction.ban) {
11 // handle the restriction object (either muted or banned)
12 println("User ${restriction.userId} is restricted in channel ${channel.id}: mute=${restriction.mute}, ban=${restriction.ban}")
13 }
14 }
15 }.onFailure {
show all 27 linesSingle user on all channels
1// reference the "chat" object and invoke the "getUser()" method
2chat.getUser("support_agent_15").async { result ->
3 result.onSuccess { user ->
4 if (user != null) {
5 // fetch the channel restrictions for the user
6 user.getChannelsRestrictions().async { restrictionsResult ->
7 restrictionsResult.onSuccess { getRestrictionsResponse ->
8 // process the returned restrictions
9 for (restriction in getRestrictionsResponse.restrictions) {
10 if (restriction.mute || restriction.ban) {
11 // handle the restriction object (either muted or banned)
12 println("User is restricted on channel ${restriction.channelId}: mute=${restriction.mute}, ban=${restriction.ban}")
13 }
14 }
15 }.onFailure {
show all 27 lines