This how-to article is part of a series of articles that discuss PubNub's data management capabilities, collectively known as BizOps Workspace:
How to Monitor and Moderate Conversations with BizOps Workspace
BizOps Workspace is a set of tools that help you manage your application. This article will look at the 'Channel Monitor' feature, which allows an administrator to watch live previews of conversations happening in real-time and take action to manually moderate that conversation, for example, by muting or banning users.
Prerequisites for the Channel Monitor
PubNub's recommended way to develop a chat application is to use our dedicated Chat SDK, which supports Typescript & JavaScript. The Chat SDK is built on top of PubNub's infrastructure, so you get the scalability and robustness of PubNub using an API designed for chat use cases such as 'conversations,' 'typing indicators,' and 'threading.'
Although the Channel Monitor can be used by all PubNub applications that use App context, those developed using the Chat SDK have access to additional features such as the ability to view and reply to threads and watch, mute, and ban users.
Channel Monitor Configuration
If you are using PubNub's dedicated Chat SDK, the message structure is predefined, so you do not have to worry about additional configuration of the Channel Monitor.
Developers not using the Chat SDK need to define how your application structures its messages and how your application handles message editing and deletion. This is done by configuring the Channel Monitor
Keyset requirements for the Channel Monitor
To use the Channel Monitor, you will also need to enable the following on your keyset in the PubNub admin portal:
App context. This stores metadata about your channels and users. I discuss app context in more detail in my previous article about the 'User and Channel Management'. For your app to receive updates when App Context data is changed, you need to enable the following:
User Metadata Events
,Channel Metadata Events
, andMembership Events
.Message persistence. This stores your message history with PubNub so the administrator can review and edit conversations.
Please see the Channel Monitor documentation for other requirements, such as the availability based on your PubNub plan.
Other keyset properties, though not required, are strongly recommended to get the most benefit from your Chat application:
Access Manager. Prevents unauthorized access to data and is required to create a secure moderation solution, as discussed later in this article.
Assuming you are using the Chat SDK, the configuration documentation also lists Presence to track whether a user is online or offline.
What is the Channel Monitor?
The Channel Monitor lets chat moderators watch live previews of conversations happening in real-time across multiple channels. If the moderator spots anything disturbing, for example, a misbehaving user or offensive messages, they can act immediately and take action to alleviate the issue.
The moderator has a lot of flexibility for which action they can take:
Observe a user without limiting their access rights (watch)
Edit the offending message
Delete the offending message
Limit the user's ability to publish messages (mute)
Limit the user's ability to read or publish messages (ban)
All of the capabilities under the "Monitor" feature are manual: Manually reviewing messages, manually muting users, etc. Automatic moderation is not discussed in this article.
Monitoring Channels
Our 'Monitor Channels' documentation will give you step-by-step instructions to get started viewing channel activity.
In summary:
Log into the Admin portal, go to the BizOps Workspace section in the left navigation panel, and select Channel Monitor. If you do not see the BizOps Workspace section, you almost certainly need to upgrade your PubNub plan, but please contact our support if you have any issues.
You will be prompted to enable App context on the keyset if it is currently disabled.
Select your channels to start moderation. If you do not see any channels or only a subset of your channels, this is because only channels with Channel context associated with them are shown. The Chat SDK will create context automatically for you, or you can do this manually with the setChannelMetadata() API available for all of our SDKs.
You can select up to 5 channels for simultaneous moderation.
The channel messages will be displayed in real time, including previous messages if you have persistence enabled on your keyset.
For an overview of the capabilities of the monitor view, please refer to the 'Channel monitor' documentation. The remainder of this article will discuss the moderation of messages and users in more detail, with reference to a sample implementation.
The Chat SDK Sample App
The same busy engineering team responsible for developing the Channel Monitor and the Chat SDK has also created a sample application written in React Native that uses the Chat SDK.
The sample shows the capabilities of the SDK as well as best practices for developing a realistic and fully-featured chat app using PubNub. The sample is open source and part of the same repository in Github that holds the Chat SDK under /samples/react-native-group-chat.
Since the app is authoritative, this article will use it to show how the Channel Monitor can be used with a 'real' app. The app is also hosted as part of our Chat SDK for Mobile demo, so you can use the app without having to install its dependencies (Expo, React Native, device emulators). If you would like to follow along with some of the examples in this how-to, please follow the installation instructions in the sample's README (At the time of writing, the latest commit is 0c12f3f).
Chat Sample App Avatars
To avoid dependencies, the avatars used by the chat app are embedded within the app and not stored in the user's app context. This means that the avatar shown in the app will not match the avatar shown in the monitor view - this is a limitation of the application and not a limitation of PubNub.
Using the Sample App with the Channel Monitor
The following steps will get you up and running with the sample app and Channel Monitor:
Clone and build the sample application, following the instructions given in the application's readme.
Run the application on two devices so you can show a conversation between two individuals. The screenshots in this article use an Android and an iOS emulator.
Log into the left device, then log into the right device. On the right device, initiate a conversation using the floating action button. Send a message from the right device, and it will show up as an unread message on the left device.
Launch the Channel Monitor as described previously. Select the appropriate channel, which will be named '1:1 with XXX', where XXX is the name you logged into the left device with.
If you see something similar to the screenshot below, you can now 'Start moderation'.
Moderate Messages
Although the Channel Monitor can be used by all PubNub applications that use App context to edit or delete messages, those developed using the Chat SDK have access to additional features, such as the ability to watch, mute, and ban users.
Editing a message as the moderator
You can edit any message as the moderator. Doing so will update the admin UI as well as the message displayed on the clients. The screenshot below shows the message "Hello" edited to be "Hello - edited by moderator"
Under the covers, the monitor view has called the Chat SDK message edit() method. The client receives the update automatically using the streamUpdatesOn() API. In the sample app, this can be seen in Chat.tsx.
Note that the original message is not deleted, but the edit is stored as an addition (action) to the original message. For more details, see the edit() message documentation.
Send messages as the moderator.
As a moderator, you can publish messages to the specified channel, which all channel members will receive. The following screenshot shows the message "That's right, I am a moderator" being received by all clients. Note that you can edit and delete your messages as the moderator but (obviously) cannot mute or ban yourself.
In order to participate in the conversation, the Channel Monitor has created a new user with the ID set to 'PUBNUB_INTERNAL_MODERATOR', which you can view using the User Management tab.
Since the sample application does not specifically handle the 'PUBNUB_INTERNAL_MODERATOR' user, it just appears as a standard message in the conversation with a default avatar. You might want to handle this moderator message in your app by assigning it some special significance, such as making the background a different color.
As a very basic example, you could modify the logic that displays the message text and prepend some indication that the message is from a moderator, for instance:
{messageProps.currentMessage?.originalPnMessage.userId ==
"PUBNUB_INTERNAL_MODERATOR" ? "MOD: " : ""}
Then the UI would look like this:
Deleting messages as the moderator
If you press the 'Delete' button next to the message, the message is marked as deleted in the 'Monitor' view, and clients are notified about the update.
Deleting a message is the same as calling the Chat SDK 'delete()' method, and it is very important to note that this is a soft delete, which means that the message remains in storage and is just flagged as 'deleted.' It is up to the client to read the status of the 'deleted' flag and take the appropriate action; as you can see, the sample application chooses to replace the message text with "(Message softly deleted)."
The relevant section of the client app is reproduced below or can also be found on Github
<Text variant="body">
{messageProps.currentMessage?.originalPnMessage.deleted
? "(Message softly deleted)"
: messageElements.map((msgPart, index) =>
renderMessagePart(
msgPart,
index,
messageProps.currentMessage?.originalPnMessage.userId || ""
)
)}
</Text>
By using the non-permanent soft delete, the message can be later restored by the moderator or other authorized user if needed.
Restore messages as the moderator.
Restoring messages is exactly the opposite of deleting a message and is the equivalent of calling the Chat SDK 'restore()' method.
The deleted message text is reinstated in the 'Monitor' view, and the 'deleted' flag is unset on the message object. See the code given above, which handled the 'deleted' flag in the sample app to restore the original text.
Moderate Users
Components of a moderation solution
Before we discuss how moderation works with the Channel Monitor, let's look at the different components of a robust and mature moderation solution and how those map to what is available in the Chat SDK.
Restrict what actions a user can perform:
If a User has misbehaved, you will want to restrict their ability to post (mute) or restrict their ability to interact with anyone else at all (ban)
On the server side, you need some way for a moderator to mute or ban a User, as well as a way for that user to be unmuted or unbanned. You also need to put rules in place that ensure messages cannot be sent or received to users who should not receive them - doing this on the server is far more secure than relying on client-side moderation, which a pernicious user could bypass.
The Chat SDK exposes the setRestrictions() method, which will 'mute' or 'ban' a user on a specific channel, as well as allow you to define a 'ban reason.' The setRestrictions() API itself does NOT apply any limitations on what the client can do; it just notifies registrants that a restriction has been applied. It is up to both the client and server to listen for 'moderation' events through the Chat SDK's listenForEvents() method.
Listen for changes in user restrictions:
When a user's permissions change, it is important these changes are applied immediately and reflected throughout your solution. When a user is banned (for example, by a moderator using a web interface), the user's client app shows a message telling that user they are banned. Any attempt to circumvent the ban by the user, for example, by "hacking" the client application to bypass client-side checks, should immediately fail owing to additional checks on the server side.
The Chat SDK's listenForEvents() method will notify any interested party that a user's permissions in a specified channel have been updated. The client should listen for these changes to update the user experience and request a new access token from the server. On the server, any previous access token should be revoked using revokeToken(), and a new token should be generated with the updated access rules using grantToken().
Query what restrictions are in effect:
You need to be able to query what restrictions are in place for users within your solution. If you are creating a moderation dashboard that runs on a server, then you need to be able to query whether a user is already manned or muted to display this state to the moderator.
On the client side, you need the ability to query whether a message recipient is muted or banned so your app can warn the user that their message will not be received and cannot be sent.
The Chat SDK exposes a family of APIs to retrieve the current restrictions: getChannelRestrictions() and getUserRestrictions(), which act on the User, and getUsersRestrictions(), which acts on the Channel.
Reporting messages or users for inappropriate content:
To provide a safe and enjoyable chat experience for all your users, they should feel empowered to report problematic users or messages to a moderator for review and action.
On the client side, your chat application will need some way for a user to highlight a message as problematic and provide some optional additional feedback. The Chat SDK provides the message.report() and user.report() methods for this purpose, which the client should call.
On the server side, you need to listen to these message reports and display them to the administrator so they can take action. They might choose to edit/delete the message itself, or if the issue persists, perform some action on the user, such as muting or banning them. The Chat SDK provides the listenForEvents() method to receive reported messages, usually handled by the server.
Where does the Channel Monitor fit into this moderation architecture?
The Channel Monitor provides a dashboard to mute or ban users based on a manual review of the messages they are sending. The dashboard will take care of calling setRestrictions() for you and always presents you with the latest information on which of your users are banned within each Channel.
What remains for you, as the developer, is to integrate these ban and mute requests into your wider application architecture. Specifically, as a PubNub customer who has deployed a production application, you are already using the PubNub Access Manager to control access to your data, ensuring that users are only permitted the RW access they need for each channel. Based on the 'mute' and 'ban' updates you receive from listenForEvents(), call into your existing Access Manager server component to revoke and grant new Access tokens for the affected User.
You will also need to ensure that your client application is taking the appropriate steps based on the updates it receives from listenForEvents() or the getXRestrictions() family of APIs. Do not allow the user to send messages to a banned user since they are destined never to be received.
Muting and Banning Users: Demo using the Sample application
As explained in the previous section, the Channel Monitor is one piece of your robust moderation solution.
This article will show how you can take action on the client when a user is muted or banned from the dashboard, though a production application will also comprise server logic that integrates with the PubNub Access Manager.
The default sample application does not implement the listenForEvents() for API, so we need to make a small change.
In HomeScreen.tsx
, add the TimetokenUtils and Alert imports as shown:
import { Channel, Membership, TimetokenUtils } from "@pubnub/chat"
import { StyleSheet, ScrollView, TouchableHighlight, TouchableOpacity, Alert } from "react-native"
Then, in the same useEffect where the "invite" listener is defined, define a second listener to display the "moderation" event as an alert, as below:
const removeModerationListener = chat.listenForEvents({
channel: chat.currentUser.id,
type: "moderation",
callback: async (event: Event<"moderation">) => {
Alert.alert(
"Restriction: " + event.payload.restriction,
`Reason (bans only): ${
event.payload.reason == null ? "" : event.payload.reason
}\nChannel Id: ${event.channelId}\nBy: ${
event.userId
}\nTime: ${TimetokenUtils.timetokenToDate(event.timetoken).toLocaleString([], {
weekday: "short",
month: "short",
day: "numeric",
hour: "numeric",
minute: "numeric",
})}`,
[{ text: "OK" }]
)
},
})
Although far from production code, this will at least show that a moderation event has been received.
Mute Users in a Channel
After modifying the code running on both devices, muting test-user-607 will trigger the 'moderation' event, as shown below:
The format of the moderation event is given in types.ts; specifically, the ModerationEventPayload will be "muted."
Note that there is no reason given for muting a user since that field only applies to bans.
Ban Users from a Channel
Banning a user from a channel is very similar to muting them. The dashboard will prompt the administrator to provide a reason for the ban, and the above screenshot shows test-user-935 having just received a ban with the reason 'Testing ban feature.'
As with mute, the format of the moderation event is given in types.ts, and the ModerationEventPayload will be "banned."
Lifting a User's Mute or Ban
Lifting a ban or a mute will both result in the same event, "lifted." The above screenshot shows the result of both test-user-607 and test-user-935 having their respective restrictions lifted. As previously stated, the format of the moderation event is given in types.ts.
Summary
Developing any chat application is only the first step, with the hardest challenges coming after you deploy that app to support your growing user base. BizOps Workspace is a set of tools designed to manage every aspect of your chat application, simplifying your post-launch challenges.
Although this article has focussed on the Channel Monitor, we are continuing to expand the features of BizOps Workspace. This article has also focused exclusively on the Chat SDK - at the time of writing, this SDK supports the full feature set of the Channel Monitor, but look out for future announcements on additional SDK support.
If you need help or support, feel free to reach out to our dedicated support team or email our developer relations team at devrel@pubnub.com
How can PubNub help you?
This article was originally published on PubNub.com
Our platform helps developers build, deliver, and manage real-time interactivity for web apps, mobile apps, and IoT devices.
The foundation of our platform is the industry's largest and most scalable real-time edge messaging network. With over 15 points-of-presence worldwide supporting 800 million monthly active users, and 99.999% reliability, you'll never have to worry about outages, concurrency limits, or any latency issues caused by traffic spikes.
Experience PubNub
Check out Live Tour to understand the essential concepts behind every PubNub-powered app in less than 5 minutes
Get Setup
Sign up for a PubNub account for immediate access to PubNub keys for free
Get Started
The PubNub docs will get you up and running, regardless of your use case or SDK
Top comments (0)